Archive for 2014

Implementing Quartz Scheduler in JDeveloper to call BEPL

Image result for jdeveloper logo


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">
<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>
8. You should get a "The Event published successfully" message.

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:CheckAddress
xmlns:add="http://www.osbcookbook.org/AddressCheckingService/">
{$request.parameters/Customer/cus:Addresses/cus:Address[$counter]}
</add:CheckAddress>
20. Click OK.

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.




Using the Publish action to asynchronously invoke a service



We will use the Publish action to asynchronously invoke a service from the proxy service message flow, without having to wait for the calling service to finish its processing.

For this recipe, we have an external Processing Service, available as a soapUI mock service which takes quite some time to do its processing. The interface in the Processing Service WSDL is defined synchronous. We have a business service Processing which allows us to invoke the external service from a proxy service.

Instead of directly invoking the business service from the Publish proxy service, an additional proxy service Processing is added, which only exposes a one-way interface. By doing that, the Publish proxy service can use a Publish action to invoke the Processing proxy service without having to wait for external service to complete.

Let's implement the Publish proxy service, which will use the Publish action to invoke the Processing proxy service. In Eclipse OEPE, perform the following steps:

1. Create a new proxy service in the proxy folder and name it Publish.

2. On the General tab select Any XML Service for the Service Type option.

3. Navigate to the Message Flow tab.

4. Insert a Pipeline Pair node and name it PublishPipelinePair.

 5. Insert a Stage node into the Request Pipeline and name it PublishStage.

6. Insert a Publish action into the Stage.

7. On the Properties tab of the Publish action, click Browse.

 8. Select the Processing proxy service inside the proxy folder and click OK.

9. Insert a Log action after the Publish action.

10. On the Properties tab of the Log action, click <Expression> and enter 'Publish completed, continue with processing in Publish proxy service' into the Expression field.

11. Click OK.

12. Select Warning from the Severity drop-down listbox.

13. Deploy the project to the OSB server.

Now, let's test OSB project by performing the following steps in the Service Bus console:

14. In the Project Explorer navigate to proxy folder inside the using-publish-to-asyncinvoke- service project.

15. Click on the Launch Test Console icon of the Publish proxy service.

16. Leave the Payload field empty and directly click Execute.

17. The output of the Log action from the Publish proxy service should be shown first in the Service Bus console window, followed a few seconds later by the output of the Log action from the Processing proxy service, which is shown after the external service has completed its work.

Difference between a Service Callout and a Routing action



A Routing action can only be used inside a Route node and will always have to be placed at the end of the proxy service message flow. No other actions can follow a routing node in the message flow. The Routing action will define where the request thread stops and where the response thread starts. The request and response pipeline of an OSB proxy service are always executed in two different threads. A Routing action supports both request/response as well as one-way message exchange patterns.

The Service Callout action can be placed anywhere where an OSB action is valid. There is no limit for the number of Service Callout actions which can be used. A Service Callout placed in the request pipeline will be performed by the request thread, a Service Callout in the response pipeline by the response thread. A Service Callout only supports the request/ response message exchange pattern and will always be synchronous, that is, it waits for the response message.

Using Service Callout action to invoke a service



We have used the Service Callout action in this recipe to invoke an additional service besides the one already called through the Routing action. By doing that, we are able to, for example, enrich a message, either before or after doing the routing. In our case, we have added the credit card information to the canonical response message returned to the consumer. By adding the Service Callout action into the Response Action of the Routing action, we decided that the callout is done after the Routing has been successfully executed.

A Service Callout only works with WSDL operation which implements the request/response message exchange pattern. One-way operations cannot be invoked by the Service Callout action, use the Publish action instead.

We will use a Service Callout action to call another service from a proxy service message flow.

Aadd an additional service call to another service Credit Card Info Service, which returns the credit card information. The service call will be done using the Service Callout action. Both the information from the Credit Card Info Service and from the Customer Service will then be merged by the XQuery transformation into one single response returned by the proxy service.


First, we will create a new business service which will wrap the additional Credit Card Info Service interface on the CRM system. In Eclipse OEPE, perform the following steps:

1. Create a new business service in the business folder and name it CreditCardInfoService.

2. On the General tab choose WSDL Web Service for the Service Type option and click Browse.

3. Click Consume and select URI from the Service Resource drop-down listbox.

4. Enter the endpoint URI of the soapUI mock service http://localhost:8090/mockCreditCardInfoServiceSOAP?WSDL into the URI field and click OK.

5. Select the CreditCardInfoServiceSOAP (port) node and click OK.

6. Confirm the pop-up window by clicking OK.

7. Rename the imported WSDL from mockCreditCardInfoServiceSOAP.wsdl to CreditCardInfoService.wsdl and move it into the wsdl folder.

By doing that, we have created the new business service. Now, let's add the Service Callout action to the proxy service calling the new business service. In Eclipse OEPE, perform the following steps:

8. Open the Message Flow tab of the CustomerManagement proxy service.

9. In the FindCustomer branch, right-click on the Response Action flow of the Routing action and select Insert Into | Communication | Service Callout to add a Service Callout action just before the Replace action. We want to enrich the message, before the transformation to the canonical format is made.

10. On the Properties tab of the Service Callout action, click Browse and select the CreditCardInfoService business service.

11. Select RetrieveCreditCardById from the Invoking drop-down listbox.

12. Select the Configure Soap Body option.

13. Enter creditCardInfoRequest into the Request Body field and creditCardInfoResponse into the Response Body field.


14. Insert an Assign action into the Request Action flow of the Service Callout action.

15. On the Properties tab of the Assign action, click on <Expression> and enter the following XML fragment into the Expression field:

<soap-env:Body>
<cred:RetrieveCreditCardById>
<id>{$body/cus:FindCustomer/ID/text()}</id>
</cred:RetrieveCreditCardById>
</soap-env:Body>

16. Navigate to the Namespace Definition tab, add a namespace with cred for the Prefix and http://www.crm.org/CreditCardInfoService/ for the URI field and click OK.

17. Enter creditCardInfoRequest into the Variable field.

We have added the Service Callout  action to the proxy service. The message flow should look as shown in the following screenshot:


The result of the Service Callout action is available in the creditCardInfoResponse variable. We now have to adapt the XQuery transformation to merge the message from the Service Callout and the Routing into one single response message. In Eclipse OEPE, perform the following steps:

18. Open the TransformFindCustomerResponse.xq XQuery transformation and navigate to the Source tab.

19. Add an additional parameter to the XQuery transformation by adding the following line to the top:

(:: pragma bea:global-element-parameter parameter="$retrieveCreditCardInfoByIdResponse1" element="ns4:RetrieveCreditCardByIdResponse" location="../wsdl/CreditCardInfoService.wsdl" ::)

20. Declare an additional namespace:

declare namespace ns4 = "http://www.crm.org/CreditCardInfoService/"; 

21. Add the parameter to the declaration of the TransformFindCustomerResponse function:

declare function xf:TransformFindCustomerResponse ($retrieveCustomerByCriteriaResponse1 as element(ns0:RetrieveCustomerByCriteriaResponse), $retrieveCreditCardInfoByIdResponse1 as element(ns4:RetrieveCreditCardByIdResponse)) as element(ns3:FindCustomerResponse) { <ns3:FindCustomerResponse>

22. Declare an additional variable and add the variable to the invocation call:

declare variable $retrieveCreditCardInfoByIdResponse1 as element(ns4:RetrieveCreditCardByIdResponse) external; 

xf:TransformFindCustomerResponse( $retrieveCustomerByCriteriaResponse1, $retrieveCreditCardInfoByIdResponse1) 
23. Navigate back to the Design tab and the new parameter with the Credit Card Info data will be shown. Map the credit card information to the FindCustomerResponse message. The mapping should look as shown in the following screenshot:



Last but not least we have to change the existing invoke of the XQuery in the Replace action so that the additional parameter is passed. In Eclipse OEPE, perform the following steps:

24. Select the Replace action following the Service Callout action and navigate to the Properties tab.

25. Click on the link to the right of Expression to reselect the XQuery transformation.

26. Click Browse, select the TransformFindCustomerResponse.xq XQuery resource and click OK.

27. Enter $body/ext:RetrieveCustomerByCriteriaResponse into the retrieveCustomerByCriteriaResponse1 field and $creditCardInfoResponse/ cred: RetrieveCreditCardByIdResponse into the retrieveCreditCardInfoByIdResponse1 field.

28. Click OK.

29. Deploy the project to the OSB server.

Now let's test the proxy service from soapUI:

30. Import the CustomerManagement-soapui-project.xml .

31. Double-click on Request 1 inside the FindCustomer operation.

32. Check that the endpoint of the proxy service is correctly set up in the drop-down listbox on the top.

33. Click on the green arrow to execute the test and make sure that the CreditCard information is returned in the response.



Testing the proxy service through soapUI - OSB Recipe 7



soapUI is such a specialized tool, which offers both a free as well as a pro version. The free version supports the testing web services with a lot of convenient functionalities.

Thanks to the standardization through web services, a tool such as soapUI can create the right requests for a service just by analyzing the provided WSDL of the service. SoapUI creates requests for each operation of the service. These requests are persisted in the soapUI project and they can be combined into a test suite. This allows them to be automatically executed, that is, they can be used together with continuous integration.

To perform this recipe, soapUI needs to be downloaded and installed. We can get it from here:
http://www.soapui.org.

In order to test the service from soapUI, we need to know the WSDL URL of the deployed proxy service.

The URL is constructed by the OSB at deployment time, based on the location of the OSB server (http://[OSBServer]:[Port]) and the endpoint URI specified in the proxy service (that is, /basic-osb-service/proxy/CustomerService). We need to concatenate the two and add the suffix ?wsdl to get the WSDL URL of the OSB proxy service:

http://localhost:7001/basic-osb-service/proxy/CustomerService?wsdl.

In soapUI, perform the following steps:

1. In the File menu, select New soapUI Project.

2. Enter the URL of the WSDL, for the service to be tested (http://localhost:7001/basic-osb-service/proxy/CustomerService?wsdl) into the Initial WSDL/WADL field.

3. Enter CustomerService into the Project Name field.

4. Click on the OK button.

SoapUI will analyze the WSDL and creates a project with some initial requests for all operations defined by the WSDL. Still in soapUI, perform the following steps:

5. Expand the project in the Navigator on the left.

6. Double-click on the Request 1 entry of the RetrieveCustomerByCriteria operation.


7. A new window for the Request 1 will open in the details section.

8. Replace the ? character in the request message on the left by the input parameter values for the test. The following screenshot shows the request with the ? characters replaced:


9. Click on the green arrow to start the test.

10. Check that a valid customer is returned in the response window on the right.

11. Save the soapUI project so that it is available to use later.

Validate that the response is correct


In soapUI, perform the following steps to validate the response from the proxy service against
the XML schema in the WSDL:

1. Right-click on the response message window and select Validate.

2. Either a pop-up window will appear indicating that the XML message is valid or the validation errors will be displayed in a window below the response message, as shown in the following screenshot:


Creating another request for the same operation


SoapUI supports more than one request per operation, so that a request can be created for each test case to be executed. It's recommended to properly name the different requests in order to be able to identify them later and to clearly indicate the case tested by a given request.

To rename a request, just right-click on the request and select Rename.

An existing request can also be cloned. This reduces the amount of work necessary to correctly set up all the information in the request message. To create a copy of a request, right-click on the request and select Clone Request.

To create a new request from scratch, right-click on the operation and select New request.

About This Site

Howdy! My name is Suersh Rohan and I am the developer and maintainer of this blog. It mainly consists of my thoughts and opinions on the technologies I learn,use and develop with.
Powered by Blogger.

- Copyright © My Code Snapshots -Metrominimalist- Powered by Blogger - Designed by Suresh Rohan -