SOA Suite 12C: Add version information to your ServiceBus projects using custom maven plugin

As you have seen in my previous posts it is possible to build your SB and SOA components using Maven. See here. One of the issues we encountered is that building ServiceBus projects supports some very basic maven stuff. For example the description property in the maven pom file is not mapped to the description field of a service bus project which would have been nice as this is the only extra field which we can use to put some extra information….for example version info!

For SOA composites you are able to input some versioning info by updating the composite.xml using a Google maven plugin. Just add this plugin to build:

<!--Needed to replace the revision in the composite.xml due to bug (20553998) which causes not to update the revision correctly -->
<plugin>
	<groupId>com.google.code.maven-replacer-plugin</groupId>
	<artifactId>replacer</artifactId>
	<version>1.5.3</version>
	<executions>
		<execution>
			<phase>initialize</phase>
			<goals>
				<goal>replace</goal>
			</goals>                   
		</execution>
	</executions>
	<configuration>
		<ignoreMissingFile>true</ignoreMissingFile>
		<file>${scac.input}</file>
		<xpath>//composite/@revision</xpath>
		<token>^.*$</token>
		<value>${composite.revision}</value>
	</configuration>
</plugin>

which result into:
versioningSoa

For SB projects there is no such thing. How can we then see which version we have?! Well the only field which we can use is the description field. The only problem is that you can not update this using Maven. The things you have to:

  • Unzip the sbconfig.sbar
  • Update the _projectdata.LocationData file which holds a proj:description tag
  • Zip the sbconfig.sbar again

Not too difficult at all. You probably can do this by using Ant but that is so 2001! We have Maven now so why not write a custom Maven plugin which does this all for you?! Well I won’t bother you with the Java details but you can download the plugin jar here!

Just install it into your Maven repository by running:

    mvn install:install-file -Dfile=version-information-plugin-1.0.jar -DgroupId=nl.redrock.maven.plugins.servicebus -DartifactId=version-information-plugin -Dversion=1.0 -Dpackaging=jar

Now that you have the plugin installed you can wire it to the package phase of your service bus project by adding the plugin to your service bus pom file. Mine looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
         xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.oracle.servicebus</groupId>
    <artifactId>sbar-project-common</artifactId>
    <version>12.1.3-0-0</version>
  </parent>
  <groupId>nl.redrock</groupId>
  <artifactId>ConversionRateService</artifactId>
  <version>1.1.2.5</version>
  <packaging>sbar</packaging>
  <description></description>
  <build>
    <plugins>
     <plugin>
        <groupId>nl.redrock.maven.plugins.servicebus</groupId>
        <artifactId>version-information-plugin</artifactId>
        <version>1.0</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>version</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <description>${project.version}</description>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

This will now call the plugin after the normal packaging has been completed. In the configuration you can now set the description. In my case I fill it with the versioning info of the component itself. Now just build your service bus project using Maven:

mavenbuild

and deploy and go to the sbconsole and voila:

sbconsole

Installing SOA BP 12.1.3.0.5 makes the flowinstance title disappear. Incoming workaround!

After installing bundle patch 12.1.3.0.5 we noticed that the flow instance title of our instances in SOA where flakey. Meaning sometimes they appeared, but sometimes they didn’t. After some testing and going back and forth with Oracle support, we where not able to steadily reproduce the bug. We did come to a work-around though and that is forcing a dehydrate. Not the best option is my opinion but a possible workaround. So if you have this issue, just add a dehydrate to the BPEL and magically see your flow instance titles come back to live again.

dehydrate

When this bug is going to be resolved is still unknown.

Continuous Discussions: Orchestrating Enterprise Software Development Testing

A while back I was asked by the people from Electric Cloud if I would be interested in participating in a panel to talk about Orchestrating Enterprise
Software Development as a part of their Continuous Discussions series.

c9d9-logo3
I thought it was a very cool idea and of course said yes. The questions we talked about where things like

  • What does your test matrix look like?
  • How do you define the pathway through your test cycle?
  • How do you manage test data and environments?
  • How have testing needs changed overtime?

We had quite a nice blend of people from the IT industry with different backgrounds so it was very interesting to hear others peoples stories, views and opinions! Have a look at the discussion right here:

Also see the blogpost of Electric Cloud here and the whole series here

Thanks Sam, Anders, Gilad and Avigail for having me!

For the people who can’t or don’t want to watch the video….here is a transcript of my contribution:

Continue reading

OFM 12C: Running WLST scripts in your build pipeline using the weblogic-maven-plugin

When you are building and deploying servicebus or soa composites to the server, you will have the certain dependencies with the server such as datasources or JMS resources. Those resources must be there if you want to deploy. A best practice is of course to script these. You can use WLST to run .py script which create your resources. The only problem is you want to know for sure the resources are there?! If you want to be consistent in your roll-outs on Dev, Tst, Acc and Prd, you all want to do this in the same manner. Operations usually do the roll-out on Acc and Prd but how do make sure we do this in the exact same way in Dev and Tst?

If you are using a build pipeline using Jenkins (see here and here ) you can easily add a step in there which can create the resources for you by running a script. How do we do this?

We are going to make use of the weblogic-maven-plugin. See here for the documentation. First make sure you have installed the plugin into you local repository. As the documentation says, do the following:

  • Change directory to ORACLE_HOME\oracle_common\plugins\maven\com\oracle\maven\oracle-maven-sync\12.1.3
  • mvn install:install-file -DpomFile=oracle-maven-sync-12.1.3.pom -Dfile=oracle-maven-sync-12.1.3.jar
  • mvn com.oracle.maven:oracle-maven-sync:push -Doracle-maven-sync.oracleHome=c:\oracle\middleware\oracle_home\

You can check if it was successful by running

mvn help:describe -DgroupId=com.oracle.weblogic -DartifactId=weblogic-maven-plugin -Dversion=12.1.3-0-0

This should list all 24 goals of the plugin.

Now for the simple test, I have created a simple script test.py which adds a queue to the SOAJMSModule

try:
        print('--> about to connect to weblogic')
	connect('USERNAME','PASSWORD','t3://localhost:7001')
	print('--> about to create a queue ' + "MyQueue")
	edit()
	startEdit()
	cd('/JMSSystemResources/SOAJMSModule/JMSResource/SOAJMSModule')
	cmo.createQueue("MyQueue")
	cd('/JMSSystemResources/SOAJMSModule/JMSResource/SOAJMSModule/Queues/' + "MyQueue")
	set('JNDIName', 'jms.myqueueu')
	set('SubDeploymentName', 'SOASubDeployment')
	save()
	print('--> activating changes')
	activate()
	print('--> done')
except:
  print('Failed connecting to server')

I created a simple .pom file which only defines the build plugin:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

	<modelVersion>4.0.0</modelVersion>
	<groupId>nl.redrock</groupId>
	<artifactId>ResourceService</artifactId>
	<version>1.0</version>
	<packaging>jar</packaging>
	<description/>

	<build>
		<plugins>
			<plugin>
				<!-- This is the configuration for the weblogic-maven-plugin -->
				<groupId>com.oracle.weblogic</groupId>
				<artifactId>weblogic-maven-plugin</artifactId>
				<version>12.1.3-0-0</version>
				<configuration>
					<middlewareHome>/fmwhome/wls12130</middlewareHome>
				</configuration>
				<executions>
					<!-- Execute the appc goal during the package phase -->
					<execution>
						<id>wls-wlst-server</id>
						<phase>post-integration-test</phase>
						<goals>
							<goal>wlst-client</goal>
						</goals>
						<configuration>
							<executeScriptBeforeFile>true</executeScriptBeforeFile>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build> 
</project>

Now lets see if we can run the script by running the following:
mvn com.oracle.weblogic:weblogic-maven-plugin:wlst-client -DfileName=test.py

As you can see, the script was ran successfully:

Run

and to be sure we can check in the console:
console

And if you incorporate it into your Jenkins build pipeline, it could look something like this:

jenkins

So this is an easy way to consistently run scripts through-out your DTAP.

Some considerations though:

  • As you are running the script every time you are building a component, make sure the script takes in account that the resources might already have been created
  • The creation of some resources require a server restart. You can also restart servers using the weblogic plugin but I’m not yet sure what a good way of working is here

OFM 12C: Slow SB deployment issue

Working with 12C a while, we started noticing that the deployment of our SharedResources SB project started to slow down. This project contains re-usable resources and contracts. The strange thing was that it was only this specific SB project. All the other projects where fine. Both deploying in JDeveloper and deploying using Maven started at around 40 seconds but after a while, it went up to 10 minutes even which is of course not workable.

After some proper investigation and contact with Oracle Support we came to the conclusion that the Maven deployments where causing this. See bug 22051706: Maven OSB deploy causes open activation sessions on OSB in case of failure, which if unresolved cause slow deployment performance. So basically when your maven deployment fails, it causes an open session. If the session contains a lot of items, which our SharedResources project has, then even 1 or 2 open sessions will drastic slow your deployments down.

sessions

The solutions is either to use the servicebus console to navigate to the sessions tab at the bottom, select a session, take control of it and discard it. I think that also the $DOMAIN_HOME/osb folder holds the sessions which can be deleted on the server.

Another way is to remove them using a piece of code:

/* To run this, make sure the setDomainEnv.sh is sourced:
    cd $DOMAIN_HOME/bin
    . setDomainEnv.sh
*/

import weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean;
import weblogic.management.jmx.MBeanServerInvocationHandler;
import javax.management.MBeanServerConnection;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.JMXConnectorFactory;
import javax.management.ObjectName;
import com.bea.wli.sb.management.configuration.SessionManagementMBean;
import java.util.Set;
import java.util.Hashtable;
import java.util.HashSet;
import java.net.MalformedURLException;
import javax.naming.Context;
import java.io.IOException;

public class DiscardOSBSessions {
    public static final String hostname = "MY_HOSTNAME";
    public static final int port = 7001;
    public static final String username = "MY_USERNAME";
    public static final String password = "MY_PASSWORD";

    static public void main(String[] args)
    {
        JMXConnector conn = null;
        
        try
        {
            // get the jmx connector
            conn = initConnection(hostname, port, username, password);

            // get mbean connection
            MBeanServerConnection mbconn = conn.getMBeanServerConnection();

            // get the Session names:
            //com.bea:Name=ALSBConfiguration.weblogic,Location=AdminServer,Type=com.bea.wli.sb.management.configuration.ALSBConfigurationMBean
            ObjectName mbeanQuery = new ObjectName("*:Name=ALSBConfiguration.*,Type=com.bea.wli.sb.management.configuration.ALSBConfigurationMBean,Location=AdminServer");
            Set<ObjectName> mbeans = mbconn.queryNames(mbeanQuery, null);
            Set<String> sessionNames = new HashSet<String>();
            for (ObjectName mbeanName : mbeans) {
                sessionNames.add(mbeanName.getKeyPropertyList().get("Name").replace("ALSBConfiguration.",""));
            }
            
            System.out.println(sessionNames.size()+" open sessions:");
            if (!sessionNames.isEmpty()){
                for (String sessionName : sessionNames) {
                    System.out.println(" - "+sessionName);
                }

                System.out.println();
                System.out.println("Destroying the sessions:");
                
                // get domain service mbean. This is the topmost mbean
                DomainRuntimeServiceMBean domainService = (DomainRuntimeServiceMBean) MBeanServerInvocationHandler.newProxyInstance(mbconn, new ObjectName(DomainRuntimeServiceMBean.OBJECT_NAME));

                // obtain session management mbean to destroy a session.
                // This mbean instance can be used more than once to create/discard/commit many sessions
                SessionManagementMBean sm = (SessionManagementMBean) domainService.findService(SessionManagementMBean.NAME, SessionManagementMBean.TYPE, null);

                for (String sessionName : sessionNames) {
                    System.out.println(" - "+sessionName);
                    sm.discardSession(sessionName);
                }
            }
            System.out.println();
            System.out.println("Successful completion");
        }
        catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (conn != null)
                try {
                    conn.close();
                } catch (Exception e) {                
                    e.printStackTrace();
                }
        }
    }

    private static JMXConnector initConnection(String hostname, int port, String username, String password) throws IOException,MalformedURLException
    {
        JMXServiceURL serviceURL = new JMXServiceURL("t3", hostname, port, "/jndi/" + DomainRuntimeServiceMBean.MBEANSERVER_JNDI_NAME);
        Hashtable<String, String> h = new Hashtable<String, String>();
        h.put(Context.SECURITY_PRINCIPAL, username);
        h.put(Context.SECURITY_CREDENTIALS, password);
        h.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "weblogic.management.remote");
        return JMXConnectorFactory.connect(serviceURL, h);
    }
}

As you can see, you can only run this on the appropriate server with the right classes on the classpath. I tried to Mavenize it into a maven project with the proper dependencies but I wasn’t able to find the right jar files for:

  • weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean
  • weblogic.management.jmx.MBeanServerInvocationHandler
  • com.bea.wli.sb.management.configuration.SessionManagementMBean

If anyone can help me out here….that would be great!

A feature request has been made to add the ‘discard session’ parameter to the Maven properties so hopefully this will come in future releases.

Custom 11G XPath function not showing up in JDeveloper 12C

You can write your own XPath lib in Java to make certain things easier and re-usable. For an example see here.

From the documentation of 12C, nothing indicated that things would have been changed so I stuck in an old library and restarted JDev. When I opened the xslt mapper, I didn’t see my functions under User Defined. This made me wonder if maybe something did have changed. Last week I attended the OFM Summercamp in Lisbon and Wilfred van der Deijl mentioned that JDev caches a lot so maybe clearing the cache would solve the problem. Someone also mentioned you could use -clean as a parameter when starting JDev but to be quite thorough I just renamed the cache folder which is default under C:\Users\\AppData\Roaming\JDeveloper from 12.1.3.0.0 to 12.1.3.0.0.old. Then I started again and voil√†…..there it was. Cheers Wilfred!

UserDefined

Automated acceptance testing using Fitnesse, Java and the OSB

When I was at Xebicon this year I saw a talk from Dave Farley. At 26 minutes or so he starts talking about Domain Specific Languages. Making an abstraction layer on top of your system where your tests run against so when the underlying system changes, you only have to adjust your layer in between instead of all the tests. This idea got me thinking of how we could be able to do this as I am mainly working in the integration business building services. This lead me to Fitnesse. Fitnesse has been around for many years now but I never had the chance to do something with it. But what is Fitnesse?

fitnesse

Fitnesse is a lightweight, open-source framework that makes it easy for software teams to:

  • Collaboratively define Acceptance Tests, web pages containing simple tables of inputs and expected outputs.
  • Run those tests and see the results.

I was interested if I could make a simple abstraction from a service which I build using the OSB and got Fitnesse to run tests against it. Also I was interested if you could then possibly wire it into a build/release pipeline.

The first thing was to get a simple webservice running. I used an old 12C webservice of mine which I build in a previous post. It is a conversion rate webservices with a SOAP or REST entry. I will be using the SOAP one for now. The service takes two parameters, a from and a to currency and the fetches the conversionrate. I deployed it and tested it and as you can see, it works.

soap-service

Next is to get Fitnesse up and running. This is as simple as downloading it and running it using Java like java -jar fitnesse-standalone.jar. When it is up, you can go to http://localhost:80 to see the Fitnesse wiki startpage.

fitnesse-wiki

The next thing is to create a test page. Click the Add link and choose Test Page. Give the page a name and a description. If you start a page name with Test….Fitnesse will automatically recognize it as a test page. Save it for now because we first have to make a piece of Java which will be the abstraction layer between the tests and our OSB webservice. Open your favourite IDE and create a simple Java project based on Maven. I am going to use jax-ws to create a webservice client and write a fixture. A fixture is a Java class which can be extended so Fitnesse can inject the test variables and retrieve the results making use of reflection and such. So we need to add a Fitnesse dependency in our pom and I am going to use the jax-ws maven plugin to generate classes based on the service WSDL. You can do this in various ways but for now I am going to use plain Java. My pom looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>nl.redrock</groupId>
    <artifactId>FitnesseTest</artifactId>
    <version>1.0</version>
    <packaging>jar</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.fitnesse</groupId>
            <artifactId>fitnesse</artifactId>
            <version>20081201</version>
        </dependency>
        <dependency>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxws-maven-plugin</artifactId>
            <version>1.12</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- usage of jax-ws maven plugin-->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>jaxws-maven-plugin</artifactId>
                <version>1.12</version>
                <executions>
                    <execution>
                        <id>wsimport-from-jdk</id>
                        <goals>
                            <goal>wsimport</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <!--wsdls file directory -->
                    <wsdlDirectory>src/main/resources/wsdls</wsdlDirectory>
                    <!-- which wsdl file -->
                    <wsdlFiles>
                        <wsdlFile>conversionrateservice.wsdl</wsdlFile>
                    </wsdlFiles>
                    <!-- Keep generated files -->
                    <keep>true</keep>
                    <!-- Package name -->
                    <packageName>nl.redrock.fitnessetest</packageName>
                    <!-- generated source files destination-->
                    <sourceDestDir>target/generated-code/src</sourceDestDir>
                </configuration>
            </plugin>
            <!-- adding generated source -->
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>add-source</id>
                        <phase>generate-sources</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>target/generated-code/src</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

As you can see I refer to src/main/resources/wsdls where my service WSDL is located. I can now just run mvn generate-sources to generate the classes I need for calling the OSB service. When I ran mvn generate-sources I have the following classes:

generated-sources

I can now write the fixture and use JUnit to test it. I am going to use a simple fixture but as your can see here there are many fixtures which you can extend. Mine looks like this:

package nl.redrock.fitnessetest.fixtures;

import fit.*;
import nl.redrock.fitnessetest.ConversionRateService_Service;
import nl.redrock.fitnessetest.Currency;
import nl.redrock.fitnessetest.GetConversionRateRequest;
import nl.redrock.fitnessetest.GetConversionRateResponse;

/**
 *
 * @author Hugo
 */
public class ConversionRateServiceFixture extends ColumnFixture {
    
    public String from;
    public String to;
    
    public double getConverionRate() throws Exception
    {
        ConversionRateService_Service client = new ConversionRateService_Service();
        GetConversionRateRequest req = new GetConversionRateRequest();
        req.setFromCurrency(Currency.fromValue(this.from));
        req.setToCurrency(Currency.fromValue(this.to));
        
        GetConversionRateResponse response = client.getConversionRateServicePort().getConversionRate(req);
        return response.getConversionRateResult();
    }
    
}

As you can see it extends the class ColumnFixture and I have 2 public variables to and from.

The next thing is to write a JUnit test to see if the fixture works:

package nl.redrock.fitnessetest;

import nl.redrock.fitnessetest.fixtures.ConversionRateServiceFixture;
import org.junit.Test;

public class ConversionRateServiceTest {

    @Test
    public void ConversionRateClientTest() throws Exception {
        
        ConversionRateServiceFixture fix = new ConversionRateServiceFixture();
        fix.from="EUR";
        fix.to="USD";
        System.out.println(fix.getConverionRate());
    }
}

I have no assertion here, just a System.out to see if the service works. Lets run it and see the magic.

junit-test

Perfect. The last thing we have to do now is to package everything into a jar so we can tell Fitnesse to put it on the classpath. Just run mvn clean package and it should create your jar in the target directory. Now lets get back to Fitnesse. Open the page you have just create and edit it.

Add the following code to the wiki page:

!path D:\Workspace\Java\FitnesseTest\target\FitnesseTest-1.0.jar

!|nl.redrock.fitnessetest.fixtures.ConversionRateServiceFixture |
| to | from | getConverionRate? |
| USD | EUR | 1.111 |
| EUR | EUR | 1.0 |

The !path will tell Fitnesse that it should put this jar on its classpath when running the tests. The
!|nl.redrock.fitnessetest.fixtures.ConversionRateServiceFixture | will tell which is the fixture class. After that it is just easy. The first two columns say which parameters can be used as input, and the third on for output. Notice the questionmark at the end of getConverionRate?.
The last 2 rows are just testcases.

Now save the page and press the Test button at the top of the screen.

fitnesse-test

There we go. We ran the 2 testcases and got the results back. I checked Jenkins for plugins and there is a plugin which enables you to run the Fitnesse tests so you easily add them to release pipeline.

So

  • The abstraction layer between your service and the tests is quite a big benefit. Lets say the contract of the service has a breaking change. We add a mandatory field. Normally you would have to change all your existing testcases. With the abstraction layer you would be able to just fix this in the fixture (if your existing testcases are unaffected by the added field of course)
  • another nice feature is that anyone can make testcases without any knowledge of soap/xml/webservice. If your fixture is nicely programmed, even business people could write tests. Quite often acceptence testers are not used to testing services without a GUI. With this its possible to do that.
  • last one is that you completely automate it. Quite often acceptance tests are done by hand which take quite some time and effort. Now you automate them and reduce the time you can possibly deliver your software to production.

Some considerations though are:

  • You do need to put in the effort to make the abstraction layer. In the beginning this will take more effort but you will earn this back quite fast when you need to regression tests or so. In the long run….this will pay of!
  • Fitnesse can be used by different languages such as .Net and Java but you will still need people who are capable of this.

SOA Suite 12C: Simple example of using the Spring component

A few days ago, we needed a some business functionality to validate an IBAN account number. You can use inline Java in your BPEL process but there are more elegant ways as you don’t want to pollute your orchestration layer with business functionality. An nice and elegant way, in my opinion, is the use of the Spring component. By using this component you can expose a Java bean as simple as you would by calling another webservice. This way the business functionality can be bundled in a nice .jar which you can also nicely test separate from the rest. Let’s see how this all works.

First of all, I will need to create a simple jar file which contains the function I want to use with an appriopriate interface. I my case I will create a BankAccountUtils class and IBankAccountUtils interface and a simple JUnit testcase to see if my function does what it has to do.

package nl.redrock.soa.utils;

/**
 * BankAccountUtils interface
 * @author Hugo
 */
public interface IBankAccountUtils {
    
    /**
     * Check an account number
     * @param account the account number to check
     * @return true of a valid IBAN, false if not
     */
    public boolean ibanTest(String account);
}
package nl.redrock.soa.utils;

import java.math.BigInteger;

/**
 * BankAccountUtils class
 * @author Hugo
 */
public class BankAccountUtils implements IBankAccountUtils {

    public final int IBANNUMBER_MIN_SIZE = 15;
    public final int IBANNUMBER_MAX_SIZE = 34;
    public final BigInteger IBANNUMBER_MAGIC_NUMBER = new BigInteger("97");

    @Override
    public boolean ibanTest(String accountNumber) {

        boolean result;

        String newAccountNumber = accountNumber.trim();

        // Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid. We could also check
        // for specific length according to country, but for now we won't
        if (newAccountNumber.length() < IBANNUMBER_MIN_SIZE || newAccountNumber.length() > IBANNUMBER_MAX_SIZE) {
            result = false;
        } else {

            // Move the four initial characters to the end of the string.
            newAccountNumber = newAccountNumber.substring(4) + newAccountNumber.substring(0, 4);

            // Replace each letter in the string with two digits, thereby expanding the string, where A = 10, B = 11, ..., Z = 35.
            StringBuilder numericAccountNumber = new StringBuilder();
            for (int i = 0; i < newAccountNumber.length(); i++) {
                numericAccountNumber.append(Character.getNumericValue(newAccountNumber.charAt(i)));
            }

            // Interpret the string as a decimal integer and compute the remainder of that number on division by 97.
            BigInteger ibanNumber = new BigInteger(numericAccountNumber.toString());
            result = ibanNumber.mod(IBANNUMBER_MAGIC_NUMBER).intValue() == 1;
        }
        return result;
    }
}
import nl.redrock.soa.utils.BankAccountUtils;
import org.junit.Test;
import static org.junit.Assert.*;

/**
 * Simple JUnit test class for the BankAccountUtils
 * @author Hugo
 */
public class BankAccountUtilsTest {
    
   
    @Test
    public void ibanTest(){
        assertTrue(new BankAccountUtils().ibanTest("NL28RBOS0569988888"));
        assertTrue(new BankAccountUtils().ibanTest("PL61109010140000071219812874"));
        assertTrue(new BankAccountUtils().ibanTest("CH3608387000001080173"));
        assertTrue(new BankAccountUtils().ibanTest("IT60X0542811101000000123456"));
        assertTrue(new BankAccountUtils().ibanTest("CY17002001280000001200527600"));
        assertTrue(new BankAccountUtils().ibanTest("FI2112345600000785"));
    }
}

Lets run the tests and see if the functionality works:
junit

Now package the class and interface in a nice .jar and we are done for this bit!

Now lets fire up JDeveloper and create a simple composite. Right click on the Project and choose Project Properties. Go to the Libraries and Classpath tab and add the .jar of the Java project we have created above. You can also just drop the .jar in the SCA-INF/lib folder of your project.

ProjectProperties

I created a BPEL process which should process a money transfer.

project

The in- and output look like this:

<?xml version="1.0" encoding="UTF-8"?> 
<schema attributeFormDefault="unqualified"
	elementFormDefault="qualified"
	targetNamespace="http://xmlns.oracle.com/SoaApplication/SpringComponent/ProcesMoneyTransfer"
	xmlns="http://www.w3.org/2001/XMLSchema">
	<element name="process">
		<complexType>
			<sequence>
				<element name="fromAccount" type="string"/>
                                <element name="toAccount" type="string"/>
                                <element name="amount" type="integer"/>
			</sequence>
		</complexType>
	</element>
	<element name="processResponse">
		<complexType>
			<sequence>
				<element name="result" type="boolean"/>
			</sequence>
		</complexType>
	</element>
</schema>

Now for the interesting part. We want to check if the fromAccount and the toAccount are valid IBAN accounts in the BPEL. First we drag the Spring component onto the composite and name the Spring Context.

SpringContext

A new Spring context file will be created. For all you Java-Spring people….this file will look very familiar in the next couple of steps. Open the Spring xml file and select the Weblogic SCA components.

SpringContext

Now drag the Service component onto the XML file. Give it a name and a target and select the interface from the .jar using the cog. For some documentation see here

Service

Save and close it. When you return to your composite you can see that the Spring component has an interface now.

Interface

We do need to make some extra adjustments. We also need to declare the bean which actually holds the implementation so go back and open the context and add the bean and we also need to add an extra interface.java element to the sca:service element to tell it is a Java interface.

<?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" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://xmlns.oracle.com/weblogic/weblogic-sca META-INF/weblogic-sca.xsd">
  <!--Spring Bean definitions go here-->
  <sca:service name="BankAccountUtils" target="int" type="nl.redrock.soa.utils.IBankAccountUtils">
    <interface.java interface="nl.redrock.soa.utils.IBankAccountUtils"/>
  </sca:service>
  <bean name="int" class="nl.redrock.soa.utils.BankAccountUtils"/>
</beans>

Also one thing you will have to do is that you will need to replace the whole spring schema-location with a much simpler version as the one generated or else you will get an error during deployment. Found the solution for this here.

xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://xmlns.oracle.com/weblogic/weblogic-sca META-INF/weblogic-sca.xsd">

Now we can wire the BPEL to the Spring component.

CreateInterface

You can see it has created a WSDL and a wrapper WSDL in the WSDLs folder. Now you can just call the bean like any other normal partner link.

BPEL

Don’t forget to drop the .jar file also on your server in the /lib directory. The server will need a restart after this to pick up the new .jar file.

Now build and deploy it and call it from the EM test console:

ResultTrue

and the result:

ResultTrue

And there we go. A nice and simple way to implement business functionality which is re-usable and doesn’t clutter your orchestration layer.