How to create/update records in another dataspace

How to create/update records in another dataspace

book

Article ID: KB0073976

calendar_today

Updated On:

Products Versions
TIBCO EBX All supported versions.

Description

In EBX5, a Procedure is the way to implement a transaction.
https://docs.tibco.com/pub/ebx/5.9.7/doc/html/en/Java_API/com/orchestranetworks/service/Procedure.html

There are several places where updates can be performed in EBX through a procedure.

Ex : 

A procedure can only perform CUD (Create, Update, Delete) on the dataspace on which it is executed.
This is due to EBX transaction management and usage contraints.

https://docs.tibco.com/pub/ebx/5.9.7/doc/html/en/Java_API/com/orchestranetworks/service/Procedure.html#execute-com.orchestranetworks.service.ProcedureContext-
Transaction management and usage constraints.

The following constraints apply:

  • A procedure can only impact one dataspace or snapshot.
  • A procedure cannot call a sub-procedure in the same dataspace or snapshot in the same thread.
  • A procedure can call a sub-procedure on any other dataspace or snapshot in the same thread. Limitation: If the main procedure fails after the sub-procedure has committed, the sub-procedure is not cancelled.

Resolution

Let's use an example here. I have 2 tables "Person" and "Address" that are in 2 different dataspaces "PersonDataSpace" and "LocationDataSpace". "Person" has a field "FKAddress" which is a foreign key to the "Address" table.
When a user creates a record in the "Person" table, we want EBX to automatically create a record in "Address" table and also automatically fill the foreign key field in "Person".
Such operations are performed in a TableTrigger declared on the "Person" table.

CreateAddressTrigger
public class CreatAddressTrigger extends TableTrigger{
...
}


In the method "handleAfterCreate", I am able to retrieve the ProcedureContext of the current procedure but it will not allow to write in "LocationDataSpace" due to the constraint we mentioned above.

handleAfterCreate
public void handleAfterCreate(AfterCreateOccurrenceContext aContext)
        throws OperationException {
    ProcedureContext procContext = aContext.getProcedureContext();
}


In order to write in "LocationDataSpace", we will implement a new procedure that implements "Procedure" Interface. The method execute of this class will then contain the code which performs the CUD on the  "LocationDataSpace".

CreateAddressProc
private class CreateAddressProc implements Procedure {
     
    private Adaptation addressRecord;
     
    public void execute(ProcedureContext aContext) throws Exception {
         
        AdaptationHome locationDataSpace = aContext.getAdaptationHome();
        Adaptation locationDataSet = locationDataSpace.findAdaptationOrNull(AdaptationName.forName("Location"));
        AdaptationTable addressTable = locationDataSet.getTable(Path.parse("/root/address"));
         
        ValueContextForUpdate vcfu = aContext.getContextForNewOccurrence(addressTable);
         
        vcfu.setValue("France", Path.parse("./country"));
        vcfu.setValue("Paris", Path.parse("./city"));
        vcfu.setValue("Avenue des Champs Elysées", Path.parse("./Street"));
         
        this.addressRecord = aContext.doCreateOccurrence(vcfu, addressTable);
    }
 
    public Adaptation getAddressRecord() {
        return addressRecord;
    }      
}


Once the procedure is implemented, we still need to execute it on the appropriate dataspace.

In the method handleAfterCreate of the TableTrigger, we will retrieve a ProgrammaticService.

https://docs.tibco.com/pub/ebx/5.9.7/doc/html/en/Java_API/com/orchestranetworks/service/ProgrammaticService.html

handleAfterCreate
public void handleAfterCreate(AfterCreateOccurrenceContext aContext)
        throws OperationException {
     
    Repository repository = aContext.getAdaptationHome().getRepository();
    AdaptationHome addressDataSpace = repository.lookupHome(HomeKey.forBranchName("LocationDataSpace"));
    ProgrammaticService service = ProgrammaticService.createForSession(aContext.getSession(), addressDataSpace);
    ...
}


With this ProgrammaticService instanciated on the "LocationDataSpace" it is now possible to execute the procedure.

handleAfterCreate
public void handleAfterCreate(AfterCreateOccurrenceContext aContext)
        throws OperationException {
     
    Repository repository = aContext.getAdaptationHome().getRepository();
    AdaptationHome addressDataSpace = repository.lookupHome(HomeKey.forBranchName("LocationDataSpace"));
    ProgrammaticService service = ProgrammaticService.createForSession(aContext.getSession(), addressDataSpace);
     
    CreateAddressProc createAdressProc = new CreateAddressProc();      
    service.execute(createAdressProc);
     
}


At this step, we are able to create a new record in "Address" table. What we want to do now is to update the foreign key field in the "Person" table.

We will use the getter on the "CreateAddressProcedure" to retrieve the "Address" record Adaptation.

Then, we will need to retrieve the ProcedureContext that will allow to write in "PersonDataSpace".

Finally, we will update the foreign key field using the method "ProcedureContext.doModifyContent(...)".

handleAfterCreate
public void handleAfterCreate(AfterCreateOccurrenceContext aContext)
        throws OperationException {
     
    Repository repository = aContext.getAdaptationHome().getRepository();
    AdaptationHome addressDataSpace = repository.lookupHome(HomeKey.forBranchName("LocationDataSpace"));
    ProgrammaticService service = ProgrammaticService.createForSession(aContext.getSession(), addressDataSpace);
     
    CreateAddressProc createAdressProc = new CreateAddressProc();      
    service.execute(createAdressProc);
    Adaptation addressRecord = createAdressProc.getAddressRecord();
     
    ProcedureContext procContext = aContext.getProcedureContext();
    Adaptation personRecord = aContext.getAdaptationOccurrence();
    ValueContextForUpdate vcfu = procContext.getContext(aContext.getAdaptationOccurrence().getAdaptationName());
    vcfu.setValue(addressRecord.getOccurrencePrimaryKey().format(), Path.parse("./FKAddress"));
    procContext.doModifyContent(personRecord, vcfu);       
}


We were able to create a record in the "address" table and to fill the foreign key field automatically.

There is still something important we need to remember : In EBX5, a procedure is the way to implement a transaction.

In this use case we executed 2 different procedures, which means that the updates that are performed on the "LocationDataSpace" are not rolled back if an exception occurs while executing the procedure on "PersonDataSpace".

Issue/Introduction

How to create/update records in another dataspace