The last couple of weeks I've been messing around with Oracle BPM (former ALBPM) 10g version. More information on this product can be found on
http://www.oracle.com/technologies/bpm/index.htmlWhen I had some free time I tried messing around with the different activities, gateways and events. This turns out to be incredibly easy and you can develop a complex workflow in a matter of minutes. However when it comes to testing the actual workflow you always end up with those pop-ups... the standard input/display presentation layouts. At the beginning I didn't really mind because I was overwhelmed by the shear power of the BPM application but after some time I started to look for better ways of representing the flows.
As I'm currently assigned on an APEX project I thought it might be a nice idea to have APEX render the user interface and let the workflow be represented by Oracle BPM. After doing some research there are three ways to communicate with the BPM engine (user interface wise).
- Standard presentation/workspace
- Custom JSF
- Process API
None of these 3 features are supported natively by Oracle Application Express, thus rendering my idea useless. After looking at the PAPI features I stumbled on this little button.

Turns out the Process API is completely exposed as a webservice. Suddenly Oracle APEX is back on the table.
After starting the PAPI Webservice from the engine preferences, I copied the wsdl url into the
create web service reference feature of APEX.
Unfortunately after running a minute or so it returned with the
WSDL can't be parsed error.
At this point I thought I might as well put in a service bus (Oracle Service Bus) to act as a connection between APEX and BPM. This allows for some extra control over which functions are exposed to the user and gives me the freedom to create webservices that would otherwise require multiple calls.
The first webservice I extracted from the PAPI service.s was the
processesGetInstancesByFilter operation. This should supply me with enough information to create a kind of inbox of the currently still open instances.
Now before creating the business service in OSB, make sure you selected the appropriate authentication settings in the BPM engine. When accessing the
BPM Web Service Console, I selected
HTTP Basic Authentication, since this is natively supported by APEX webservices.
After having the WSDL file its no problem creating the business service. However take into account that you'll be doing the webservice authentication from APEX to BPM. This means selecting BASIC as Authentication when creating the business service and creating a Service Account that has
Pass Through as
resource type

This is the only business service that is required to connect apex to bpm. From now on we'll only need proxy services. For the creation of the proxy service we'll need a WSDL file. This isn't a requirement, since we'll be using manual webservice creation later (in apex) but it first much better in the SOA story if we create one.
Since I'm basically rerouting the new webservice to the PAPI service I decided to use the same IN/OUT elements as the original operation. Thus reducing the time required to create the webservice.
Creating a proxy service from the wsdl file is a piece of cake. Just select the port or binding and of we go. No need to set the HTTP Transport settings since these are handled by APEX. I decided to go with processesGetInstancesByFilter in this post because it's different that the other service I created. It actually does something useful in the message flow.

The first assign takes the processID from the request and stores it to a local variable. The replace in the request action of the Route node is where we find a little difference.

Basically I'm replacing the entire body (not best practice I know) with a new xml structure. Where I've taken the local variable and added the searchScope. The response of this message gives me all the currently in process instances that the requested user has acces to.
Can you see the inbox growing ?
Now that we have the webservice exposed with OSB we can move to APEX.
One more remark though.. If you attempt to test the proxy webservice with the OSB console you'll receive a Participant not authentication response from BPM. This will probably be because there were no HTTP basic authentication headers supplied. For quick testing just set the Service account to static and enter a username/password. Now the webservice should work.
Next up. APEX.
After doing the normal administration tasks like creating workspace, application etc. go to shared components -> Web service references -> Create.
Since we won't be using a UDDI for this small setup, select no on the first question.
Now there are two options.
- Create webservice reference by using the wsdl
- Create web service reference manually
Well It turns out that the second option works much better with me. Using the WSDL doesn't always work and gives you less freedom in your SOAP request.
So select
Create Web Service Reference Manually from the right side of the page.
- Name : duh . I went for processesGetInstancesByFilter.
- Url : pretty straight forward and it needs the enpoint uri. Should be something like http://<hostname>:<port>/<endpoint-uri>
- Action : you can write anything in this field. But this is placed in the soap action header.
- Proxy : in case you use a proxy service to access your OSB
- Basic authentication : select yes, since we'll be using this to authenticate with BPM
- SOAP Envelope : This is the most important field of all. Here we put the xml message that is send to the webservice. To make the xml dynamic use page items between # characters. When the webservice is called the current value will be placed there.
- SOA Response : All response are stored in apex_collections. Supply the name of this collection. This collection doesn't need to exist it is created automatically when the web service is called.
Now that the webservice is created we can test to see whether it works. Edit the soap envelope, supply the username and password and by magic you'll receive a response.
Next comes the really easy part. Calling the webservice from a page process.
The easiest way would be to create a from/report from a webservice however... This doesn't work with manually created services... Oké we'll create a new blank page and add a page process. Create this process based on a web service. Select On Load as point moment to make you're life a little bit easier for now.
Select the appropriate web service reference and supply static authentication parameters. You can link this to page items, so there is always a possibility to link this to the login, but for now supply static parameters.
Create a page item that holds the same name as the parameter used in the SOAP envelope. For now just give it a static value.
Note: the process id looks like this /<processName>#<Variation>-<version> or in my case /ExpenseReporting#Default-1.0
You can check this with the processesGetIds operation using e.g. SOAPUI.
Now when running the page the webservice will be called
on load. If it works from the first time be happy. Otherwise check all the steps or drop a line in the comments. Now that we've managed to request data from the webserice... We need to interpret the response.
Create a new report based on a sql query. You can use a report from webservice but the created select doesn't work for me. It never supplies a query that works, always returning nothing.
Below I've added the query I used to generate a report. Adopt it to fit your own instance needs.
select extractValue(value(b),'/instances/activityName') as activity,
extractValue(value(b),'/instances/author') as creator,
extractValue(value(b),'/instances/creationTime') as creationTime,
extractValue(value(b),'/instances/description') as description,
extractValue(value(b),'/instances/priority') as priority,
extractValue(value(b),'/instances/state') as state,
replace(extractValue(value(b),'/instances/id'),'#','%23') as instanceID
from wwv_flow_collections c,
table(xmlsequence(extract(xmltype(c.clob001), '//instances/instances'))) b
where c.collection_name = 'FILTER_BY_INSTANCE'
After the creation of the report you should end up with a page showing an inbox with all the open instances.
And thus the connection between APEX and BPM is completed.
Now you can do the same with the other services like, processCreateInstance, activityExecute and any other operation you might need.
You can let APEX create rows in tables and send the id's back to bpm or store everything in BPM and let the application store it in the database.
You're choose but keep in mind that APEX is meant to be used with a direct link to the database.
Now I can hear some you thinking, 'Won't the fact that we're using apex force us to develop our flow twice ? Once in BPM and again in APEX ?'
The answer to this question is NO. At least from my point of view. If you use Page aliases that are equivalent to activity or task names and just use the activity name as branch alias. Thus no need to start messing around with page numbers etc. And if you ever change the order of activities they will be automatically used in the apex application. And for new activities you just have to create a new page with the appropriate alias and the branching/urls do the rest.
When I was attempting this integration I found little to info on this subject. This leads me to believe there is either not need for this integration or no-one has tried it. But seeing the low complexity of this I can't see the second being true....
I hope you folks found this useful and if you have any suggestions/questions/remarks don't hesistate to let me know.
Beo.