Archive for 2014
Implementing Quartz Scheduler in JDeveloper to call BEPL
We will create a simple a web service proxy component, a scheduler job class that is called by the SOAScheduler and a java class SOASchedulerServlet that initiate the quartz scheduler.
1. To get started, create a new Application in JDeveloper by click CTRL-N, name it SOAScheduler,
2. select “Generic Application”.
3. Create a new Project named "SchedulerProject", select “Java” and “Web Services” as “Project Technologies”.
4. Click "Finish".
5. Create a new Web Service Proxy by click “File/New” or CRTL-N.
6. Click “OK” and “Next”.
7. Select “JAX-WS Style” and click “Next”.
8. Paste the WSDL location into “WSDL Document URL” and click “Next”.
9. Write “sample.oracle.otn.soascheduler.proxy” into “Package Name” and “sample.oracle.otn.soascheduler.proxy.types” into “Root Package for Generated Types” and click “Finish”.
10. In the new HelloWorldProcess_ptClient.java add the Line
System.out.println(helloWorldProcess.process("SOAScheduler"));
public static void main(String [] args)
{
helloworldprocess_client_ep = new Helloworldprocess_client_ep();
HelloWorldProcess helloWorldProcess = helloworldprocess_client_ep.getHelloWorldProcess_pt();
// Add your code to call the desired methods.
System.out.println(helloWorldProcess.process("SOAScheduler"));
}
11. Click on F11 or on the run icon . The composite will be executed by the new generated service proxy.
In the message window you will see the correct output of SOA example composite.
Add Quartz library to the project
1. Click on “Application” “Project Properties”, “Add JAR/Directory…”.
2. Select in your JDeveloper home “…\jdeveloper\soa\modules\quartz-all-1.6.5.jar”. Click “Select”.
3. Click “OK”.
Creating the Scheduler Job Component
1. Create a new “Java Class” in JDeveloper by click “File/New” or CRTL-N...
2. Click “OK”.
3. Set the Name to “HelloWorldJob” and Package to “sample.oracle.otn.soascheduler.job” and click “OK”.
4. Replace the generated source with the following lines.
package sample.oracle.otn.soascheduler.job;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import sample.oracle.otn.soascheduler.proxy.Helloworldprocess_client_ep;
import sample.oracle.otn.soascheduler.proxy.HelloWorldProcess;
import javax.xml.ws.WebServiceRef;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
public class HelloWorldJob implements Job{
@WebServiceRef
private static Helloworldprocess_client_ep helloworldprocess_client;
public HelloWorldJob() {
helloworldprocess_client = new Helloworldprocess_client_ep();
}
public void execute(JobExecutionContext jobExecutionContext) {
DateFormat df = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
Date date = new Date();
System.out.println("HelloWorldJob started");
try {
helloworldprocess_client = new Helloworldprocess_client_ep();
HelloWorldProcess helloWorldProcess = helloworldprocess_client.getHelloWorldProcess_pt();
// Add your code to call the desired methods.
System.out.println("HelloWorld Response: " + helloWorldProcess.process("SOAScheduler@" + df.format(date)));
} catch (Exception e) {
System.out.println("HelloWorld Process failed: " + e.toString());
e.printStackTrace();
}
}
}
Creating the SOASchedulerServlet java class
1. Create a new Java Class in JDeveloper by click “File/New” or CRTL-N...
2. Set the Name to “SOASchedulerServlet”, Package to “sample.oracle.otn.soascheduler”, Extends “javax.servlet.http.HttpServlet” and click on “OK”.
3. Replace the generated source with the following lines.
package sample.oracle.otn.soascheduler;
import sample.oracle.otn.soascheduler.job.HelloWorldJob;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.calendar.AnnualCalendar;
public class SOASchedulerServlet extends HttpServlet {
StdSchedulerFactory schedFact;
Scheduler sched;
public void init(ServletConfig config) throws ServletException {
super.init(config);
try {
schedFact = new StdSchedulerFactory("soa_quartz.properties");
sched = schedFact.getScheduler();
System.out.println(this.getClass().getName() + " started");
/*
// Add the holiday calendar to the schedule
AnnualCalendar holidays = new AnnualCalendar();
// fourth of July (July 4)
Calendar fourthOfJuly = new GregorianCalendar(2011, 7, 4);
holidays.setDayExcluded(fourthOfJuly, true);
// halloween (Oct 31)
Calendar halloween = new GregorianCalendar(2011, 9, 31);
holidays.setDayExcluded(halloween, true);
// christmas (Dec 25)
Calendar christmas = new GregorianCalendar(2011, 11, 25);
holidays.setDayExcluded(christmas, true);
// tell the schedule about our holiday calendar
sched.addCalendar("holidays", holidays, false, false);
*/
sched.start();
JobDetail jd = new JobDetail(JOB_NAME, GROUP_NAME, HelloWorldJob.class);
CronTrigger cronTrigger = new CronTrigger(TRIGGER_NAME, GROUP_NAME);
String cronExpr = null;
// Get the cron Expression as an Init parameter
cronExpr = getInitParameter("cronExpr");
System.out.println(this.getClass().getName() + " Cron Expression for " + JOB_NAME + ":" + cronExpr);
cronTrigger.setCronExpression(cronExpr);
System.out.println(this.getClass().getName() + " Scheduling Job " + JOB_NAME);
sched.scheduleJob(jd, cronTrigger);
System.out.println(this.getClass().getName() + " Job " + JOB_NAME + " scheduled.");
} catch (Exception e) {
System.out.println(this.getClass().getName() + e.getLocalizedMessage());
e.printStackTrace();
}
}
public void destroy() {
try {
if (sched != null) {
sched.unscheduleJob(TRIGGER_NAME, JOB_NAME);
sched.shutdown();
}
} catch (Exception e) {
System.out.println(this.getClass().getName() + " failed to shutdown: " + e.toString());
e.printStackTrace();
}
System.out.println(this.getClass().getName() + " stopped");
}
public void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
PrintWriter ajax = new PrintWriter(response.getOutputStream());
// logger.warning("get");
String action = request.getParameter("action");
if ("single".equals(action)) {
if (sched != null) {
try {
Trigger trigger =
new SimpleTrigger("SOASingleTrigger", GROUP_NAME, new Date());
trigger.setJobName(JOB_NAME);
trigger.setJobGroup(GROUP_NAME);
// Schedule the trigger
sched.scheduleJob(trigger);
} catch (Exception e) {
System.out.println(this.getClass().getName() + e.getLocalizedMessage());
e.printStackTrace();
}
}
} else if ("start".equals(action)) {
if (sched != null) {
try {
JobDetail jd = new JobDetail(JOB_NAME, GROUP_NAME, HelloWorldJob.class);
CronTrigger cronTrigger = new CronTrigger(TRIGGER_NAME, GROUP_NAME);
// Get the cron Expression as an Init parameter
String cronExpr = getInitParameter("cronExpr");
System.out.println(this.getClass().getName() + " Cron Expression for " + JOB_NAME + ":" + cronExpr);
cronTrigger.setCronExpression(cronExpr);
System.out.println(this.getClass().getName() + " Scheduling Job " + JOB_NAME);
sched.scheduleJob(jd, cronTrigger);
System.out.println(this.getClass().getName() + " Job " + JOB_NAME + " scheduled.");
} catch (Exception e) {
System.out.println(this.getClass().getName() + e.getLocalizedMessage());
e.printStackTrace();
}
}
} else if ("stop".equals(action)) {
if (sched != null) {
try {
sched.unscheduleJob(TRIGGER_NAME, GROUP_NAME);
System.out.println(this.getClass().getName() + " stopped");
} catch (Exception e) {
System.out.println(this.getClass().getName() + " failed to shutdown: " + e.toString());
e.printStackTrace();
}
}
}
ajax.println("<html>");
ajax.println(" <head>");
ajax.println(" <title>SOAScheduler - Web Interface</title>");
ajax.println(" <link rel=\"stylesheet\" type=\"text/css\" href=\"css/mystyle.css\"></link>");
ajax.println(" </head>");
ajax.println(" <body onload='startAjaxPeriodicalUpdater()'>");
ajax.println(" <h2>");
ajax.println(" SOAScheduler @");
ajax.println(" <span class=\"server\">" + System.getProperty("weblogic.Name") + "</span>");
ajax.println(" </h2>");
ajax.println("<table id=\"events_table\" class=\"events_table\" width=\"100%\">");
ajax.println("<tbody>");
String[] jobGroups;
String[] jobsInGroup;
String[] triggerGroups;
Trigger[] jobTriggers;
String[] calendersList;
AnnualCalendar calen;
CronTrigger cronTrigger;
int i, j, k;
try {
jobGroups = sched.getJobGroupNames();
triggerGroups = sched.getTriggerGroupNames();
calendersList = sched.getCalendarNames();
for (i= 0; i < calendersList.length; i++) {
calen = (AnnualCalendar)sched.getCalendar(calendersList[i]);
//System.out.println("Calendar: " + calendersList[i]);
ajax.printf("Calendar: " + calendersList[i]);
}
for (i = 0; i < jobGroups.length; i++) {
// System.out.println("Group: " + jobGroups[i] + " contains the following jobs");
jobsInGroup = sched.getJobNames(jobGroups[i]);
for (j = 0; j < jobsInGroup.length; j++) {
// System.out.println("- " + jobsInGroup[j]);
jobTriggers = sched.getTriggersOfJob(jobsInGroup[j], jobGroups[i]);
for (k = 0; k < jobTriggers.length; k++) {
// System.out.println("- " + triggersInGroup[j]);
if ("org.quartz.CronTrigger".equals(jobTriggers[k].getClass().getName())) {
cronTrigger = (CronTrigger)jobTriggers[k];
ajax.printf("<tr class=\"%s\"><td align=\"left\">Trigger: %s</td><td>Next: %s</td><td>Last: %s</td><td>Cron: %s</td></tr>",
"events", jobTriggers[k].getName(),
jobTriggers[k].getNextFireTime(),
jobTriggers[k].getPreviousFireTime(),
cronTrigger.getCronExpression());
} else {
ajax.printf("<tr class=\"%s\"><td align=\"left\">Trigger: %s</td><td>Next: %s</td></tr>",
"events", jobTriggers[k].getName(),
jobTriggers[k].getNextFireTime());
}
}
}
}
} catch (Exception e) {
System.out.println("SOASchdulerServlet failed: " + e.toString());
e.printStackTrace();
}
ajax.println("</tbody>");
ajax.println("</table>");
ajax.flush();
}
static final String GROUP_NAME = "SOAGroup";
static final String TRIGGER_NAME = "SOATrigger";
static final String JOB_NAME = "SOAJob";
static final String TARGET_PAGE = "index.jsp";
}
Create a quartz property file
1. Create a new File (General) in JDeveloper by click “File/New” or CRTL-N...
2. Select “File (General)”.
3. Set File Name to “soa_quartz.properties” and Directory to the src directory of your project. Click “OK”.
4. Insert the following lines into the property file.
#
# Configure Main Scheduler Properties
#
org.quartz.scheduler.instanceName = SOASchedulerorg.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
#
# Configure ThreadPool
#
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 5
org.quartz.threadPool.threadPriority = 4
#
# Configure JobStore
#
org.quartz.jobStore.misfireThreshold = 5000
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
Create a J2EE Deployment Descriptor (web.xml)
1. Create a new web.xml in JDeveloper by click “File/New” or CRTL-N...
2. Select “Java EE Deployment Descriptor”. Click “OK”.
3. Select “web.xml”. Click “Next”.
4. Select “2.5”. Click “Finish”.
5. Select “Servlets” and click on the green “+” (Create Servlet).
Set Name to “SOASchedulerServlet”, Servlet Class to “sample.oracle.otn.soascheduler.SOASchedulerServlet”. Set “Load Servlet on” to “Application Start”.
6. Select “Servlet Mappings” and click on the green “+” (Create “Servlet Mappings”). Add “/soaschedulerservlet” as URL Pattern.
7. Select “Initialization Parameters” and click on the green “+” (Create “Servlet Initialization parameters”). Add “cronExpr” as Name and “0 0,5,10,15,20,25,30,35,40,45,50,55 * * * ?” as Value.
8. Select “Pages” and click on the green “+” (Create “Welcome File”). Add “/soaschedulerservlet”.
9. The Source should look like this…
<?xml version = '1.0' encoding = 'windows-1252'?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
<servlet>
<servlet-name>SOASchedulerServlet</servlet-name>
<servlet-class>sample.oracle.otn.soascheduler.SOASchedulerServlet</servlet-class>
<init-param>
<param-name>cronExpr</param-name>
<param-value>0 0,5,10,15,20,25,30,35,40,45,50,55 * * * ?</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SOASchedulerServlet</servlet-name>
<url-pattern>/soaschedulerservlet</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>/soaschedulerservlet</welcome-file>
</welcome-file-list>
</web-app>
10. Click “Save All”.
11. Attention: The name “cronExpr” is requested in the SOASchedulerServlet.java, and the value means, that the SOA composite bpel-101-helloworld is started every five minutes every day.
Create WAR File (Deployment Profile)
1. Create a new “WAR File” in JDeveloper by click “File/New” or CRTL-N...
2. Click “OK”.
3. Set the Profile Name to “SOAScheduler”. Click “OK”.
4. On the “General” tab set the “Web Context Root” to “SOAScheduler”.
5. On the Filters subtub of WEB-INF/lib deselect “quartz-all-1.6.5.jar”, because it is already available on the WebLogic Server 10.3.1/2/3. Click “OK”.
6. Click “OK”.
Deploy your application
1. Right click on your Project, select “Deploy” and click on “SOAScheduler”.
2. Select “Deploy to Application Server”. Click “Next”.
3. Select your Application Server, where the Oracle SOA Suite is installed. If you have not your application server already configured. Add a new connection with the green “+”. Click “Next”.
4. Select “AdminServer”. Click “Finish”.
If deployment successful, the message window shows following:
Use of Event Delivery Network (EDN) : Tutorial - POProcessing
You add a new mediator component called receivePO, which subscribes to an event called NewPO and sends the received PO to the routePO service.
1. Open the POProcessing application in JDeveloper and open composite.xml, and click on the Event Definition Creation icon:
2. In the Event Definition Creation window, enter POEvents as the name of the event definition. Accept the namespace value generated.
3. Add a new event by clicking on the + icon.
4. Select the PuchaseOrder element from the po.xsd file using the chooser.
5. Enter NewPO as the name of the event and click on OK to close the Add an Event window.
6. Click on OK to complete the event definition.
7. Close the POEvents.edl panel.
8. Save all.
Subscribing to the NewPO event
1. Drag-and-drop a Mediator component onto the composite.
2. Name the mediator receiveNewPO.
3. Select Subscribe to Events for the Template.
4. Click on the + to add an event. Select the NewPO event from the Event Chooser window.
5. Click on OK to accept and create the mediator.
6. Save all.
7. Connect the receiveNewPO mediator to the routePO mediator:
8. Double-click on the receiveNewPO mediator and define a new transformation map. In the transformation-map, map the all the fields from the source to the target.
9. Close the mediator and save all.
Deploying and testing
1. Deploy the POProcessing composite to the server.
2. Browse to the EM console at http://localhost:7001/em.
3. Right-click on folder soa-infra (soa_server1) under folder SOA:
4. Click on item Business Events.
5. You should see the Business Events management page with the NewPO event listed in the Events tab.
6. Select the event and click on the Test… button to publish the event.
7. In the pop-up window, enter the following XML and click on Publish:
<PurchaseOrder xmlns="http://xmlns.oracle.com/ns/order">8. You should get a "The Event published successfully" message.
<CustID>1111</CustID>
<ID>33412</ID>
<productName>Sony Bluray DVD Player</productName>
<itemType>Electronics</itemType>
<price>350</price>
<quantity>5</quantity>
<status>Initial</status>
<ccType>Mastercard</ccType>
<ccNumber>1234-1234-1234-1234</ccNumber>
</PurchaseOrder>
9. Click on soa-infra in the navigation panel on the left to get the soa-infra dashboard.
10. Click on the POProcessing composite to view new instances. You should see an instance created for processing the event you just published. Click on the instance ID to view the flow trace.
Event Delivery Network (EDN)
The Event Delivery Network (EDN) in Oracle SOA Suite 11g provides a declarative way to use a publish/subscribe model to generate and consume business events without worrying about the underlying message infrastructure.
Developers only need to produce or consume events without having to deal with any particular messaging API like JMS, AQ, and MQ, and so on.
EDN uses an XML-based Event Definition Language(EDL), which allows you to define the event and its associated, strongly typed data. This definition is then registered with the SOA Infrastructure and is available to all composites to publish or subscribe.
This allows for a fully-declarative, business-oriented, rather than developer-oriented approach for using events in a SOA application.
Another feature of EDN is the ability to publish and subscribe to these events from a variety of programming environments such as Java, PL/SQL, SOA Composites, and ADF-BC applications.
Creating and managing event definitions
Events are defined using an Event Definition Language (EDL), an XML schema used to build business event definitions.
An EDL consists of the following:
- A global name.
- Custom headers: These can be used for content-based routing without having to parse the XML payload and apply XPath queries to get at the value to be used for the routing decisions.
- Payload definition: Typically this is an XML schema for the business data that needs to accompany the event.
If you want to raise events on one or more database operations such as insertion of a new row or update of an existing one, you can use ADF-BC to define these events.
Registered events, their subscribers, and any faulted deliveries can all be tracked and monitored using the Oracle Enterprise Manager.
Consuming events from the Event Delivery Network
The first step to consume an event is to discover its definition. Event definitions can be stored locally in a composite or globally on the server—in either case, they can be discovered through the JDeveloper resource catalogue.
To subscribe to an event within an SOA composite application, you start by defining a Mediator component, selecting the event of interest from a list of registered events in the network.
To further refine a subscription, and narrow down the information you will receive, you can define an XPath-based filter on your subscriptions.
For example, for an event named "NewPOCreated", you could either subscribe to all "NewPOCreated" events (default when no filter is defined) or only those where the order amount is more than a million dollars (by defining an XPath-based filter on the order amount field within the payload).
Perform message validation in OSB using Validate action
The Validate action can be used to check the content of any variable against an element or
type of an XML schema. The validation can be configured to either save the Boolean result of
the validation in a variable or to raise an error if the validation fails. An error will hold the error
code BEA-382505 and the message will hold further details about the failed validation.
By using the XPath expression, it's also possible to only check fragments, inside a larger XML
message, for validity.
We will show how to use the Validate action to perform message validation.
In Eclipse OEPE, perform the following steps:
1. Open the MessageValidation proxy service and navigate to the Message Flow tab.
2. Insert a new stage into the MessageProcessingPipelinePair and name it MessageValidationStage.
3. Insert a Validate action into the stage.
4. On the Properties tab of the Validate action, enter body into the In Variable field.
5. Click <XPath> and enter ./cus:Customer into the Expression field. Click OK.
6. Click Browse to the right of Against Resource and select the Customer (element) in the xsd/Customer.xsd XML Schema. Click OK.
7. Select the Raise Error option.
8. Deploy the project to the OSB server.
Now let's test the validation of our proxy service. In the Service Bus console, perform the following steps:
9. In the Project Explorer navigate to proxy folder inside the using-validate-to-domessage-validation project.
10. Click on the Launch Test Console icon of the MessageValidation proxy service.
11. Enter a message with an invalid CardIssuer (only the lowercase values visa and mastercard are valid) and click Execute.
12. The Validate action will raise a validation error, which is shown in the following screenshot:
Using dynamic Split-Join to perform work in parallel in OSB
We have seen how the OSB's advanced mediation feature, called Split-Join, can help to improve the performance of the service by concurrently processing individual parts of a message. The Split-Join first splits the input message payload into submessages (split), processes these submessages concurrently and then aggregates the responses into one return message (join). In our case, the splitting has been done on the collection of addresses in the customer request message and the concurrent processing involves the invocation of the Address Checking Service in parallel.
Split-Joins are useful for optimizing the overall response time when parts of the request messages need to be processed by slower services, that is, each individual address has to be handled by a call to the Address Checking Service, taking four seconds to respond. Because of the parallel nature, the whole Split-Join finishes in little more than four seconds. This is a huge benefit compared to the solution with the For Each action shown in the Using the For Each action to process a collection recipe.
The Split-Join of the Oracle Service Bus comes in two flavors:
- Static Split-Join – branches from the main execution thread of the OSB message flow by splitting the payload into a fixed number of branches according to the configuration of the Split-Join at design time.
- Dynamic Split-Join – branches from the main execution thread of the OSB message flow by dynamically creating new branches according to the contents of the incoming payload. Conditional logic is used to determine the number of branches at runtime.
We will use the Split-Join functionality of the Oracle Service Bus to handle outgoing service callouts in parallel instead of the usually used sequential method.
A Split-Join is a separate artifact, which we will create first. In Eclipse OEPE, perform the following steps:
1. Create an additional folder flow in the project using-dynamic-split-join.
2. Right-click on flow and select New | Split-Join.
3. Enter SplitJoin into the File name field and click Next.
4. Navigate to the operation: StoreCustomer node of the CustomerManagement.wsdl file and click Finish.
5. The SplitJoin flow artifact will be shown in the detail window.
6. Drag a For Each operation from the Flow Control section of the Design Palette to the flow between Receive and Reply.
7. On the Properties tab of the For Each operation, click <Counter Name> and enter counter into the Counter Variable Name field on the pop-up window. Click OK.
8. Enter number(1) into the Start Counter Value field.
9. Enter count($request.parameters/Customer/cus:Addresses/cus:Address) into the Final Counter Value field.
10. Drag an Invoke Service operation from the Communication section of the Design Palette into the For Each operation.
11. On the Properties tab of the Invoke Service operation, click Browse and select the operation: CheckAddress node from the AddressChecking business service in the business folder.
12. Click OK.
13. Navigate to the Input Variable tab and select the Create Message Variable item of the Message Variable drop-down listbox.
14. Enter addressCheckRequest into the Name field and click OK.
15. Navigate to the Output Variable tab and select the Create Message Variable item of the Message Variable drop-down listbox.
16. Enter addressCheckResponse into the Name field and click OK.
17. Drag an Assign operation from the Assign Operations section of the Design Palette and drop it before the Invoke Service operation.
18. On the Properties tab of the Assign, select addressCheckRequest.parameters from the Variable drop-down listbox.
19. Click on <Expression> and enter the following XML fragment into the Expression field:
<add:CheckAddress20. Click OK.
xmlns:add="http://www.osbcookbook.org/AddressCheckingService/">
{$request.parameters/Customer/cus:Addresses/cus:Address[$counter]}
</add:CheckAddress>
21. Drag an Assign operation from the Assign Operations section of the Design Palette and drop it after the Invoke Service operation.
22. On the Properties tab of the Assign, select response.parameters from the Variable drop-down listbox.
23. Click on <Expression> and enter the following XML fragment into the Expression field:
<out>COMPLETED</out>
We have successfully created the Split-Join flow artifact. Now, let's create the business service, which will invoke the Split-Joint through the flow transport. The business service can easily be generated by performing the following steps in Eclipse OEPE:
24. Right-click on the SplitJoin.flow artifact and select Oracle Service Bus | Generate Business Service.
25. Select the business folder in the Service Location tree and enter SplitJoin into the Service Name field and click OK.
Now, let's add the call of the business service to the already existing SplitJoinInvoker proxy service. In Eclipse OEPE, perform the following steps:
26. Open the SplitJoinInvoker proxy service and navigate to the Message Flow tab.
27. Insert a Route node into the StoreCustomer branch and name it InvokeSplitJoinRoute.
28. Insert a Routing action into the Route node.
29. On the Properties tab of the Routing action, click Browse and select the SplitJoin business service. Click OK.
30. Select the StoreCustomer operation from the Invoking drop-down listbox.
31. Deploy the project to the OSB server.
Now, we can test the proxy service. In the Service Bus console, perform the following steps:
32. In the Project Explorer navigate to proxy folder inside the using-dynamic-split-join project.
33. Click on the Launch Test Console icon of the SplitJoinInvoker proxy service.
34. Select the StoreCustomer operation from the Available Operations drop-down listbox.
35. Enter a message with two addresses into the Payload field as shown in the following screenshot:
36. Click on Execute.
37. It should not take more than four seconds until the Test console response window is shown (each single Address Checking Service call is taking four seconds to answer).
38. Click Back to retest.
39. Enter a message with four addresses into the Payload field and click Execute.
40. It should still take about four seconds until the response window is shown. The four calls to the Address Checking Service are done in parallel.
Using the Java Callout action to invoke Java code
We have created a Java class, packaged it as a JAR and invoked it from the OSB proxy service through a Java Callout action. Only static methods can be invoked through the Java Callout action; other, non-static methods will not be shown when browsing the classes/methods.
The JAR is deployed with the OSB project to the OSB server and it will always run inside the OSB server.
We will show how we can use a Java Callout action to invoke Java code, which might already exist. This is an easy way to extend the standard functionality of the service bus.
We will use the Java Callout action to call a Java method which returns the Checksum of the message passed as the parameter. The functionality of calculating a checksum is not available as an XPath/XQuery function and adding it through a Java Callout action is of course much simpler and more efficient than using a real web service.
We will first create the Java project with the Java class holding the checksum calculation functionality. In Eclipse OEPE, perform the following steps:
1. Right-click on the Project Explorer and select New | Project.
2. Enter java into the Wizards field, select Java Project and click Next.
3. Enter osb-checksum-util into the Project name field.
4. Click Finish and confirm the pop-up window with Yes to switch to the Java perspective.
5. Right-click on the osb-checksum-util project and select New | Class.
6. Enter osbcookbook.util.checksum into the Package field.
7. Enter ChecksumUtil into the Name field and click Finish.
8. Implement the following static method inside the ChecksumUtil class:
public static long calculateChecksum(String data) { Checksum checksum = new CRC32(); checksum.update(data.getBytes(), 0, data.getBytes().length); return checksum.getValue(); }9. Right-click on the source and select Source | Organize Imports.
By doing that, the checksum functionality is ready to be used. In order to invoke it through a Java Callout, it needs to be packaged into a Java Archive (JAR) file and copied into the OSB project. In Eclipse OEPE, perform the following steps:
10. Right-click on the osb-checksum-util project and select Export.
11. Enter java into Select an export destination and select JAR file.
12. Click Next.
13. In the Select the resources to export tree, select the osb-checksum-util project.
14. Click Browse right to the JAR file drop-down listbox.
15. Navigate to the jar folder inside the using-java-callout-to-invoke-java OSB project, enter osb-checksum-util.jar into the File name field and click Save.
16. Click Next and then Finish.
Now, let's switch to the OSB project and implement the proxy service calling our new Java calls through a Java Callout. In Eclipse OEPE, perform the following steps:
17. Switch to the Oracle Service Bus perspective.
18. Refresh the jar folder inside the using-java-callout-to-invoke-java project by pressing F5 and check that the JAR file created previously is located inside the jar folder.
19. Create a new proxy service inside the proxy folder and name it Checksum.
20. On the General tab, select Messaging Service for the Service Type option.
21. Navigate to the Messaging tab and select Text for both the Request Message Type and Response Message Type option.
22. Navigate to the Message Flow tab.
23. Insert a Pipeline Pair node and name it CalculateChecksumPipelinePair.
24. Insert a Stage into the Request Pipeline and name it CalculateChecksumStage.
25. Insert a Java Callout action into the stage.
26. On the Properties tab of the Java Callout action, click Browse to select the method to call.
27. Navigate to osb-checksum-util.jar in the jar folder of the project and click OK.
28. Select the public static long calculateChecksum(java.lang.String) method and click OK.
29. Click <Expression> and enter $body/text() into the Expression field and click OK.
30. Enter checksumValue into the Result Value field.
We have added the Java Callout action to invoke our Java method and after that the checksum value is available in the checksumValue variable. Let's add a Replace action to return the checksum in the body variable. In Eclipse OEPE, perform the following steps.
31. Insert a Replace action after the Java Callout action.
32. Enter $checksumValue into the Expression field.
33. Enter body into the In Variable field.
34. Deploy the project to the OSB server.
Now let's test the proxy service by performing the following steps in the Service Bus console:
35. In the Project Explorer navigate to proxy folder inside the using-java-callout-toinvoke-java project.
36. Click on the Launch Test Console icon of the Checksum proxy service.
37. Enter some text to calculate the checksum on into the Payload field and click on Execute.
38. The output of the Java Callout action and the checksum calculation will be shown in the Response Document section.