Some 'more, in-depth' information on Oracle BPEL PM, ESB and other SOA, day2day things

Friday, July 14, 2006

Searching BPEL process instances not only by conversationId

Ever tried to find an instance through the BPEL client API, but not by its converstationID? Sometimes it might be needed to search for an instance, not by it's unique identifier, but by some keyword of the payload.

The API that is used to invoke a process offers you to set custom key properties. They can be searched afterwards and also modified at runtime.

To set these key properties while invoking the process use the com.oracle.bpel.client.NormalizedMessage:setProperty(key, value) API. which allows you to set specific instance properties. For using the searchable ones, we provide static constants within the NM, named INDEX1, INDEX2, and INDEX3. Use them as key when setting a property - and there you go.

At runtime, you can use the bpelx:exec activity and inside the setIndex(int pIndex, String pValue) API.

For searching those instances afterwards use the com.oracle.bpel.client.Locator:findInstances( com.oracle.bpel.client.util.WhereCondition ) API, which encapsulates a prepared SQL statement. What is does behind the scenes is to join the cube_instance with the ci_indexes table, and make the join searchable through the API.

Check out the sample code below

To fill the message with the searchable property use

[..]
NormalizedMessage msg = new NormalizedMessage();
msg.setProperty(NormalizedMessage.INDEX1, "Clemens" );
[..]

WhereCondition searchForClemens = new WhereCondition(SQLDefs.CX_INDEX1 + " = ?");
searchForClemens.setString(1, "Clemens");

[..]
Locator mLoc = ...
IInstanceHandle[] foundInstances = mLoc.findInstances(searchForClemens);
[..]

5 Comments:

Blogger harald said...

hi clemens,
i tried your example on my bpel-environment (10.1.3.1) and got the following error.

2006-11-09 08:56:30,149 ERROR systemtest.collaxa.cube BaseCubeSessionBean::logError Fehler beim Aufrufen von Bean "Finder": Instanzen nicht gefunden.
Der Versuch, die Instanzen mit der WHERE-Klausel "index_1 = ?" aus dem Datenspeicher abzurufen, war nicht erfolgreich. Es wurde folgende Exception gemeldet: ORA-00904: "INDEX_1": ungültiger Bezeichner

Stellen Sie sicher, dass der Rechner mit der Datenquelle physisch mit dem Netzwerk verbunden ist. Wenn dies der Fall ist, stellen Sie sicher, dass die Verbindungsparameter für die Datenquelle (Benutzer/Kennwort) derzeit gültig sind.
SQL-Anweisung: SELECT * FROM admin_list_ci WHERE ci_domain_ref = 1 AND index_1 = ?

ORABPEL-04002

Instanzen nicht gefunden.
Der Versuch, die Instanzen mit der WHERE-Klausel "index_1 = ?" aus dem Datenspeicher abzurufen, war nicht erfolgreich. Es wurde folgende Exception gemeldet: ORA-00904: "INDEX_1": ungültiger Bezeichner

Stellen Sie sicher, dass der Rechner mit der Datenquelle physisch mit dem Netzwerk verbunden ist. Wenn dies der Fall ist, stellen Sie sicher, dass die Verbindungsparameter für die Datenquelle (Benutzer/Kennwort) derzeit gültig sind.
SQL-Anweisung: SELECT * FROM admin_list_ci WHERE ci_domain_ref = 1 AND index_1 = ?

sounds like the api is searching in the wrong table.

best regards,
harald

11:43 AM

 
Blogger Clemens Utschig - Utschig said...

Harald you are right - I took the wrong method into the sample. It should be Locator:listInstancesByIndex( WhereCondition )

thx for noting

10:05 PM

 
Blogger harald said...

hi clemens,
i tried your approach in a bpel-prozess containing only two activities to execute java-code. the first activity sets the NormalizedMessage and the second tries to find the instance. my problem is that the listInstancesByIndex always returns an empty array.

here is my code:
1. bpel:exec
Element element = (Element)getVariableData("ReadInProgressStatus_InputVariable","payload","/client:ReadInProgressStatusRequest/client:CustomProcessID");
String customProcessID = element.getTextContent();
System.out.println("SetInProgressStatus: " + customProcessID);

// set customProcessID as custom key properties
NormalizedMessage msg = new NormalizedMessage();
msg.setProperty(NormalizedMessage.INDEX1, customProcessID);


2. bpel:exec
Element element = (Element)getVariableData("ReadInProgressStatus_InputVariable","payload","/client:ReadInProgressStatusRequest/client:CustomProcessID");
String customProcessID = element.getTextContent();

WhereCondition searchForID = new WhereCondition(SQLDefs.CX_index_1 + " = ?");
searchForID.setString(1, customProcessID);

Locator mLoc = getLocator();
try {
IInstanceHandle[] foundInstances = mLoc.listInstancesByIndex(searchForID);
System.out.println("foundInstances: " + foundInstances);

setVariableData("ReadInProgressStatus_OutputVariable", "payload", "/client:ReadInProgressStatusResponse/client:Status", foundInstances.length + " instances found for customProcessID: " + customProcessID);

} catch (com.oracle.bpel.client.ServerException e) {
e.printStackTrace();
}

7:21 AM

 
Blogger Clemens Utschig - Utschig said...

you need to persist the instance in between - checkpoint();

9:39 AM

 
Blogger Clemens Utschig - Utschig said...

appearently there is a bug in 10.1.3.1 - a column missing for the view this API relies on.

here are the steps .
1) in bpelx:exec - use the setIndex(index, value) method ..

2) then use the API ..

furthermore run the following statement against the dehydration store..

create or replace view admin_list_cx
as select ci.cikey, domain_ref as ci_domain_ref, process_id, revision_tag,
creation_date ci_creation_date, creator ci_creator,
modify_date ci_modify_date, modifier ci_modifier,
state ci_state, priority ci_priority, title,
status, stage, conversation_id, metadata,
root_id, parent_id,
index_1, index_2, index_3, index_4, index_5, index_6,
ci.test_run_id
from cube_instance ci, ci_indexes cx
where ci.cikey = cx.cikey;

commit;

5:52 AM

 

Post a Comment

<< Home