BI Publisher 11g exposes a lot of functionality through its four new Web Services. In part one we looked at how we can examine the services and prototype calls into them. In part two we saw how a Web Service can be accessed programmatically, through Java code generated by JDeveloper in what's called a Web Service Proxy. The third part of this little series shows how to incorporate a BI Publisher Web Service in a BPEL process of a SOA application.
BPEL is an industry standard for describing interactions between Web Services. Oracle’s implementation of BPEL is as part of their SOA Suite. BPEL is described in XML, but JDeveloper provides a GUI for describing BPEL processes. To use it, you need to make sure you've got the SOA Composite Editor extension for JDeveloper installed.
Creating the BPEL process
In this example we will implement a very simple BPEL process, to run an existing report, and save the output as PDF.
Before you start, make sure you've got JDeveloper, with SOA Composite Editor extension. If you want to test your BPEL process, then you'll also need a SOA server running. You can deploy one in the same FMW home as your existing OBI, but be aware if you're running on a laptop or development VM that it'll bump the memory consumption of the machine up - 4GB may not be enough.
This was tested on 188.8.131.52 versions of JDeveloper, OBI and SOA Suite.
First, create a New Application in JDeveloper, picking the SOA Application template, and then when prompted for a Composite Template, choose Composite with BPEL Process. Once the application is created, you'll be prompted to create the BPEL process. Set the Template to Synchronous BPEL Process, and click OK.
This takes us to the SOA Composite editor, showing the BPEL process component. We're interested in defining what the BPEL process will actually do, so double click on it to open it. This will open a .bpel tab in JDeveloper, showing the process graphically.
From the Component Palette on the right, find BPEL Services, and from here drag a Web Service item to the grey area on the right of the canvas that is titled Partner Links.
Specify the WSDL URL, for example,
and enter a Name, eg ReportService (this doesn't have to match the Web Service name). Tick the box to copy the WSDL into the project. When prompted to Localize Files, click OK
We've defined the Web Service (known in the BPEL process as a Partner Link), and now want to use it in the BPEL process. To do this, use an Invoke step. You'll find this in the Component Palette, under BPEL Constructs. Drag and drop it over the main canvas diagram, where you'll see plus icons appear between the steps. Place it between 'receiveInput' and 'replyOutput'
Double-click on the new Invoke step, and set the Partner Link and Operation so that it calls the runReport method of ReportService. Create the input and output variables to the Web Service by clicking the green plus icon next to each ("Automatically Create Input/Output Variable"), and accepting the defaults for each. When it creates the variables it uses the WSDL of the Web Service to determine the structure of the variable that is required.
So, we've got a Web Service defined ("Partner Link"), and a call to it ("Invoke"). Now we need to set up the input variable, which defines the message contents that gets passed to the Web Service. To do this, we use an Assign step. Drag this from the Component Palette to the main canvas just before the Invoke step.
Variables are held in XPath format, which needs a bit of love and care to work with correctly. As we saw in part one, the input to runReport method is a message of reportRequest data type, and this has many possible elements. You'll see that these have all been added to the input variable that we just created in the Invoke step, and we now need to remove the ones that we don't want to use.
To manipulate variables in BPEL, you use various BPEL methods, which the Edit Assign dialog helps you set up graphically. We want to remove quite a lot of the input variable to the Invoke step, so use the Remove method. To use it, expand the variable (if you've used the defaults, it'll be called something like Invoke1runReportInputVariable) until you find the element that you want to remove (for example, ns1:XDOPropertyList), and then drag and drop the red cross from the tool bar of the window onto it. You should see an entry appear in the bottom of the window with a Remove step.
Repeat this until the reportRequest element has just these three elements that do not have the Remove method applied to them:
attributeFormat reportAbsolutePath reportOutputPath
Now we need to assign values to those elements that we do want to pass through to the Web Service. To do this there are two options. One is to assign a fixed string, to hard code the value. The other is to use a value that has been passed in to the BPEL process.
To assign a value to an element, drag and drop the Expression icon (Fx) from the toolbar onto the element. Assuming it's a string, enter the value in single quotes and click OK. You should see it appear in the list at the bottom, under the Remove steps. Set up the elements as follows:
ns1:attributeFormat : 'pdf' ￼ns1:reportOutputPath : '/tmp/bpel_ws1.pdf' ns1:userID : 'weblogic' ns1:password : 'Admin123'
We finish off the variable configuration by setting the report that is to be run to the value that's passed in to the BPEL process. In our example, it will just be when we manually invoke it, but it could easily be part of a more complex SOA flow in which different reports are created at different stages as required. In the left pane of the Assign window, expand 'inputVariable' (this is what gets passed in to our BPEL process) until you see 'client:input : string'. Drag and drop this on to the ns1:reportAbsolutePath element on the right of the window.
Click OK to close the Assign window, and breathe a sigh, as this is the most fiddly bit completed.
All that remains to complete the BPEL process now is to do something with the return from the Web Service. Add a second Assign step, just after the Invoke step. Edit this second Assign step to copy ns1:reportFileID from the output of the web service (called something like Invoke1runreportOutputVariable) to client:result : string of the BPEL process output (called outputVariable).
Your BPEL process should now look like this:
Once you've saved your BPEL process, you can deploy it ready for testing. To do this, right-click on the Project and click Deploy. You'll be prompted for an Application Server, which the first time through you'll need to define. Rememeber, you need to have installed SOA Suite and SOA Server to be up and running. Check in Web Logic Console if necessary.
Assuming that you get a successful build and deploy, you can test your BPEL process from Enterprise Manager (Fusion Middleware Console). Navigate to the SOA folder, click on your deployed project, and select Test. Under Input Arguments specify the full path of your report, for example:
/6. Published Reporting/Sales/North America Sales.xdo
Click on Test Web Service, and hold your breath...
If all has gone well, you should get a successful Response, and the PDF file created in the path specified.
If there's a problem with your process, or the call to the web service, you'll get an error message and some diagnostics. At this point I hasten to mention my point made in the first article. If you prototype your web service calls through a tool like soapUI first, you'll understand exactly what data you need to pass to the method you are using, and therefore can reduce your development time by knowing exactly what you need your code to be doing, whether it's BPEL, Java, or whatever. Debug your web service calls in a web service tool, and then all you should have to debug in your application is your application code.