BPEL SOA Suite Essentials for WLI Users

Comparison: Oracle WebLogic Integration's Custom Control and SOA Suite Spring Component

by Clemens Utschig-Utschig and Simone Geib

This installment of the SOA Suite Essentials for WLI Users series maps Oracle WebLogic Integration's custom control functionality to the equivalent in Oracle SOA Suite, the Spring Component.

Published December 2009

Downloads for this article:
 Oracle SOA Suite

Introduction

Custom Java code is an essential part of every Oracle WebLogic Integration (WLI) business process (JPD). Although most components of Oracle SOA Suite are XML-centric, Oracle is adding support for Spring components to give the developer full Java support and a powerful IOC container. The Spring components are available since SOA Suite 11g PS2.

This article explains how a Spring component in SOA Suite provides the same functionality as a Custom control in WLI. It uses the example of a logger component to describe step-by-step how the Spring component is implemented and deployed.

This article is intended for WLI developers and architects who want to get started with SOA Suite 11g.

Custom Control in WLI

WLI uses a custom control to encapsulate Java code (e.g. access to a resource or application functionality) which can then be used in a WLI process (JPD) by dragging-and-dropping the control method into the process.

Users can build their own custom controls that are based on the same framework on which system controls are based. A user designs a custom control from the ground up, designing its interface and implementation, and adding other controls as needed.

Spring Component in SOA Suite

Oracle SOA Suite uses its Spring Java component to implement specific business logic in Java, without ever worrying about XML.

Spring (see SpringSource) is an IOC container (Inversion of Control; see Inversion of Control Containers and the Dependency Injection by Martin Fowler) that allows dependency injection via configuration. So while it presents a little overhead when exposing one JavaBean without any dependencies, the more external components are needed, the easier it becomes to use.

While the main components of Oracle SOA Suite are based on XML as data-exchange format, the goal of this component is to allow seamless Java integration and hence the reuse of Java components and skills. Once a component is implemented, it can be subsequently exposed as service, and invoked from other components such as BPEL.

Using Java classes in a composite can be easily achieved through following a few steps.

a) Create a Java interface, and expose the methods that should be publicly available.

public interface IInternalPartnerSupplier
{
    /**
     * Get a price for a list of orderItems
     * @param pOrderItems the list of orderitems
     * @return the price
     */
    public double getPriceForOrderItemList(List<Orderitem> pOrderItems)
        throws InternalSupplierException;
}

b) Create an implementation of this interface.

public class InternalSupplierMediator implements IInternalPartnerSupplier
{
    /**
     * Get the price for a list of orderItems and write the quote via
     * injected reference
     * @param pOrderItems the list of orderItems
     * @return the price for the list of orderItems
     */
    @Override
    public double getPriceForOrderItemList(List<Orderitem> pOrderItems)
        throws InternalSupplierException
    {
        // just return a default price - or do something else ..
        return 0.0;
    }
}

c) Create a spring component, which also gives you a spring context, and create a bean, which describes the class created in Step b). Give it a name (so it can be referenced) and declare the class.

<!--
     spring bean inside a context, declaring a name, the class it's implemented 
         with and the scope (singleton or new instance on each BeanFactory.getBean())
-->

<bean id="InternalPartnerSupplierMediator"
        class="com.otn.sample.fod.soa.internalsupplier.InternalSupplierMediator"
        scope="prototype">
</bean>

d) Create an <sca:service> that exposes a bean as a service. A component must have a service declared, in order to be usable by other components' references.

<!-- 
    exposed bean 'InternalPartnerSupplierMediator'. 
    Note the type, which represents the java interface 
-->

<sca:service name="IInternalPartnerSupplier"
    target="InternalPartnerSupplierMediator"
    type="com.otn.sample.fod.soa.internalsupplier.IInternalPartnerSupplier"/>

Once a spring component, including a service, is created, it can be wired to any other component, as illustrated in Figure 1, below.

Figure 1
Figure 1

Use case example: a simple logging component

A very common example of a WLI Custom Control is a custom logger which is used at certain points in a process. In this case, we will log the name of the process, the instance ID and a log message.

Implementing the use case in WLI

This use case is not described in great detail as it is assumed that the audience knows how to create and use custom controls in WLI. The focus area is the Spring component in SOA Suite.

The logger control in WLI consists of two java files:

The interface class LoggerControl.java

package sample.oracle.otn.soaessentials.javainteg.controls;
/**
 * Simple logger interface
 * @author simone.geib@oracle.com
 * @author clemens.utschig@oracle.com
 */
import org.apache.beehive.controls.api.bean.ControlInterface;

@ControlInterface
public interface LoggerControl {

    /**
     * Implementation of the log method
     * @param pProcessName the name of the originating process
     * @param pInstanceId the instanceID
     * @param pMessage the message to be logged to std.out
     * @see sample.oracle.otn.soaessentials.javainteg.ILoggerComponent#log
     */
    public void log (String pProcessName, String pInstanceId, String pMessage);

}

The implementation LoggerControlImpl.java

package sample.oracle.otn.soaessentials.javainteg.controls;
import org.apache.beehive.controls.api.bean.ControlImplementation;
import java.io.Serializable;
/**
 * Implementation of a simple logger component
 * @see sample.oracle.otn.soaessentials.javainteg.ILoggerComponent
 * @author simone.geib@oracle.com
 * @author clemens.utschig@oracle.com
 */
@ControlImplementation
public class LoggerControlImpl implements LoggerControl, Serializable {
 private static final long serialVersionUID = 1L;
 
    /**
     * Implementation of the log method
     * @param pProcessName the name of the originating process
     * @param pInstanceId the instanceID
     * @param pMessage the message to be logged to std.out
     * @see sample.oracle.otn.soaessentials.javainteg.ILoggerComponent#log
     */
    public void log(String pProcessName, String pInstanceId, String pMessage)
    {  
       StringBuffer logBuffer = new StringBuffer ();
       logBuffer.append("[").append(pProcessName).append("] [Instance: ").
        append(pInstanceId).append("] ").append(pMessage);
 
       System.out.println(logBuffer.toString());
    }
}

Figure 2 shows the logging control in a JPD Data Palette.

Figure 2

Figure 3 shows the use of the logging control in a JPD

Figure 3

Implementing the use case in SOA Suite


In this section, we will create a simple logging component that can be used from other components, such as BPEL Process Manager or Mediator, to log messages, including the originating instance ID, to standard out.

Creating the Spring Component

To get started, create a new Application in JDeveloper, name it " SOASuiteWLIEssentials"...

Figure 4

And create a new Project named " JavaIntegration".

Figure 5

Click " Finish."

Create a new Java Package " sample.oracle.otn.soaessentials.javainteg" (this requires several steps).

Figure 6

Create a new Java Interface, named " ILoggerComponent" in the " sample.oracle.otn.soaessentials.javainteg" package.

Figure 7
Figure 8

Add a new method to the interface, named " log", with parameters for the originating component, the instance ID, and the message.

package sample.oracle.otn.soaessentials.javainteg;

/**
 * Simple logger interface
 * @author simone.geib@oracle.com
 * @author clemens.utschig@oracle.com
 */
public interface ILoggerComponent
{
   
    /**
     * Log a message, including the originating component, its instance id and
     * a message.
     * @param pComponentName the name of the component that sends this log msg
     * @param pInstanceId the instanceId of the component instance
     * @param pMessage the message to be logged
     */
    public void log (String pComponentName,
                     String pInstanceId, String pMessage);
}
Figure 9

Create a Java class (" LoggerComponentImpl") from the interface " ILoggerComponent".

Figure 10

Name the class and click on the plus sign to find the interface on which to base the class.

Figure 11
Figure 12
Figure 13

This is the implementation of the logging component:

package sample.oracle.otn.soaessentials.javainteg.impl;

import sample.oracle.otn.soaessentials.javainteg.ILoggerComponent;

package sample.oracle.otn.soaessentials.javainteg.impl;

import sample.oracle.otn.soaessentials.javainteg.ILoggerComponent;

/**
 * Implementation of a simple logger component
 * @see sample.oracle.otn.soaessentials.javainteg.ILoggerComponent
 * @author simone.geib@oracle.com
 * @author clemens.utschig@oracle.com
 */
public class LoggerComponentImpl implements ILoggerComponent
{

    /**
     * Implementation of the log method
     * @param pComponentName the name of the orginating component
     * @param pInstanceId the instanceid
     * @param pMessage the message to be logged to std.out
     * @see sample.oracle.otn.soaessentials.javainteg.ILoggerComponent#log
     */
    @Override
    public void log(String pComponentName, String pInstanceId,
                    String pMessage)
    {
        StringBuffer logBuffer = new StringBuffer ();
        logBuffer.append("[").append(pComponentName).append("] [Instance: ").
            append(pInstanceId).append("] ").append(pMessage);
        
        System.out.println(logBuffer.toString());
    }
}

In the next few steps, we will create a new Spring context ("logger-context.xml"), define a Spring bean ("logger"), and expose the bean as a service ("logService").

Figure 14
Figure 15

Next, drag a bean from the Component Palette...

Figure 16

Onto the the spring context canvas.

Figure 17

Name it "logger" and declare a class attribute pointing to the implementation.

Figure 18

Now the bean can be exposed as an SCA service.

To do so, change the drop-down in the component palette to " Spring 2.5 SCA" and drag a " service" onto the canvas.

Figure 19

Give the service the name " logService". Its target will be the " logger" bean.

Figure 20

Finally, pick the type, which is the interface of the LoggerComponent class (" sample.oracle.otn.soaessentials.javainteg.ILoggerComponent").

Figure 21
Figure 22

The completed spring context looks like this:

<?xml version="1.0" encoding="windows-1252" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:lang="http://www.springframework.org/schema/lang"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:sca="http://xmlns.oracle.com/weblogic/weblogic-sca">
  <!-- expose the logger bean as service -->
  <sca:service name="logService" target="logger"
               type="sample.oracle.otn.soaessentials.javainteg.ILoggerComponent"/>
  <!-- declaration of the logger bean -->
  <bean name="logger"
    class="sample.oracle.otn.soaessentials.javainteg.impl.LoggerComponentImpl"/>
</beans>

Create a new composite and name it " JavaIntegration".

Figure 23

Use the "create with BPEL Process" option and name the process " BPELProcessWithLogger". Leave the rest with default settings.

Figure 24
Figure 25

Figure 26, below, shows the newly created BPEL process with a receive and a callback activity.

Figure 26

Switch back to the composite view, and drag a " Spring Context" onto the composite canvas. Name it " logger-context" and pick the spring context you created earlier.

Figure 27
Figure 28

Compile the Java classes so you can create a valid WSDL definition that can be used from within a BPEL process.

Figure 29

Drag the service of the spring component over to the BPEL process. This will create a wsdl and a partnerlink in the process.

Figure 30
Figure 31

Next, drag an invoke activity from the component palette onto the BPEL canvas. This will be used to invoke the log() method on the log service created earlier.

Figure 32

Wire invoke to the partnerlink for the logger service.

Figure 33

Create input and output variables. They will be used later to assign the values for component name, component instance id and a log message.

Figure 34

With the finished invoke activity, the process should resemble Figure 35, below.

Figure 35

In order to populate the created variables, drag an assign activity from the palette onto the BPEL process.

Figure 36

In the next three steps you will create the necessary copy rules to populate the input variable.

Double-click the assign activity and add a copy operation to assign the component name to the first parameter.

Figure 37

Add another copy operation to assign the process instance id to the second parameter.

Figure 38

Add a third copy operation to assign a message to the third parameter.

Figure 39

Make sure the assign activity contains all three copy rules.

Figure 40

Once all the copy rules have been built, the process should resemble Figure 41, below, with an initial receive, the assign for the log message values, followed by an invoke of the log service's log method, and finally, a callback, implemented via invoke.

Figure 41

Deploying the SOA Composite

The next step is to deploy the composite with Oracle JDeveloper. Please make sure that your SOA server is running.

Please check Section 43 in Deploying SOA Composite Applications to learn how to deploy SOA composite applications with Oracle JDeveloper and scripting tools and create configuration plans that enable you to move SOA composite applications to and from development, test, and production environments.

Please check Section 5 in Deploying SOA Composite Applications to learn how to deploy, redeploy, and undeploy a SOA composite application from Oracle Enterprise Manager Fusion Middleware Control Console.

When deploying the composite from within JDeveloper, the log should look similar to the one below:

[06:15:55 AM] ----  Deployment started.  ----
[06:15:55 AM] Target platform is  (Weblogic 10.3).
[06:15:55 AM] Running dependency analysis...
[06:15:55 AM] Building...
[06:16:11 AM] Deploying profile...
[06:16:11 AM] Updating revision id for the SOA Project 'JavaIntegration.jpr' to '1.0'..
[06:16:12 AM] Wrote Archive Module to C:\JDeveloper\mywork\SDOStuff\JavaIntegration\
              deploy\sca_JavaIntegration_rev1.0.jar
[06:16:12 AM] Deploying sca_JavaIntegration_rev1.0.jar to soa_server1 
              [sta00251.us.oracle.com:8001] 
[06:16:12 AM] Processing sar=/C:/JDeveloper/mywork/SDOStuff/JavaIntegration/deploy/
              sca_JavaIntegration_rev1.0.jar
[06:16:12 AM] Adding sar file - C:\JDeveloper\mywork\SDOStuff\JavaIntegration\deploy\
              sca_JavaIntegration_rev1.0.jar
[06:16:12 AM] Preparing to send HTTP request for deployment
[06:16:12 AM] Creating HTTP connection to host:sta00251.us.oracle.com, port:8001
[06:16:13 AM] Sending internal deployment descriptor
[06:16:13 AM] Sending archive - sca_JavaIntegration_rev1.0.jar
[06:16:41 AM] Received HTTP response from the server, response code=200
[06:16:41 AM] Successfully deployed archive sca_JavaIntegration_rev1.0.jar to 
              soa_server1 [sta00251.us.oracle.com:8001] 
[06:16:41 AM] Elapsed time for deployment:  46 seconds
[06:16:41 AM] ----  Deployment finished.  ----

Testing the BPEL Process

After successful deployment, you can initiate the composite service through Oracle Enterprise Manager Fusion Middleware Control Console (Enterprise Manager).

To log in to Enterprise Manager, use Internet Explorer 7, Mozilla Firefox 2.0.0.2, or Firefox 3.0.x to access the following URL: http://host_name:port/em. (Where host_name is the name of the host on which Enterprise Manager is installed and port is a number that is dynamically set during installation.)

Enter weblogic/password and click Login.

Please check Getting Started with Administering Oracle SOA Suite for more information.

Figure 42

Locate the JavaIntegration composite on the EM dashboard and click on it. This will get you to the composite homepage:

Figure 43

Once on the page, you can test a composite service.

Figure 44

Fill in " clemens" as input and click " Test Web Service"

Figure 45

Once the instance is created, you can click on the Launch Message Flow Trace which will get you to the composite instance:

Figure 46

You can check the BPEL instance flow as well, which will show you the actual message that was passed to the spring component:

Figure 47

Check the standard output of the server, that hosts the soa suite. It should show an entry similar to the one below:

==> CubeEngine deploy BPELProcessWithLogger took 4 seconds
INFO: DeploymentEventPublisher.invoke Publishing deploy event for 
default/JavaIntegration!1.0*c39dc7a2-5031-424e-9ae0-aeec949769b3
[BPELProcessWithLogger] [Instance: 20009] Got input: clemens

Download the complete project

A zip file contiaining the complete project, including the java sources and the composite, is available for download: wli-soaessentials-JavaIntegration-source.zip.

To open it in JDeveloper, create a new Application, and then open the project file (JavaIntegration.jpr)

Key Takeaways and Recommendations

  • Java can be seamlessly embedded into the composite / xml based world.
  • Multiple Java beans can be easily exposed as services, or get external references injected - just by declaring, and later wiring them.
  • No need to code around XML, inside the Spring component - it's POJOs.

In order to create reusable entities and beans, a spring context can be packaged and deployed itself, without composite, into the WebLogic Server, and beans can be exposed as EJBs / webservices.

This makes it very easy to create reusable Java components that can be used from within a BPEL process o

r a Mediator component in the same way as a WLI JPD uses custom controls.

Further reading


Clemens Utschig-Utschig Clemens Utschig-Utschig is a Sr. Principal Product Manager and SOA Architect at Oracle. He is one of the original authors of the SOA Manifesto, a contributor to Thomas Erl's SOA Design Patterns, and a member of the Masons of SOA, an international, inter-company group of SOA architects dedicated to sharing information in the name of better, more successful SOA.
[ Oracle Mix / Blog / LinkedIn]
Simone Geib Simone Geib is Product Manager for SOA technologies at Oracle Corporation. She joined Oracle through the BEA Systems acquisition, where she was Product Manager for WebLogic Integration. Simone has extensive experience of SOA strategy and implementation across a wide range of industries and geographies.
[ Oracle Mix / Blog / LinkedIn]