Using JMX to list installed 12C OSB and SOA projects including versions using Java

Lately we where looking for a way to easily list all the services (OSB and SOA) installed on our DTAP machines. A CMDB works as well as it is maintained. As this is tedious and manual labour, we all know from experience that the CMDB is never fully correct. So how do we know then what is installed where? We can open the EM and the sbconsole and have a look there but wouldn’t it be more fancy if we would just select an environment, run some script and it would give you a list of the services?

Ok, how do we obtain al this information then? Weblogic has a JMX (Java Management eXtensions) interface which we can use to access mbeans which should hold all the information we need. Let’s start of with our SOA server first. You can use WLST but as I’m a Java fan, I will use Java. Starting of with a simple Maven project I first need to setup a connection to a server, lookup the right mbean which can give me a list of the installed services, access it and fill some result. Let’s first init the connection and the use the connection to lookup the right mbean.

   /**
     * Initialize the connection with the server
     * @param hostname the host
     * @param port the port
     * @param username the username
     * @param password the password
     * @return a JMXConnector
     * @throws IOException
     * @throws MalformedURLException
     */
    public 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);
    }

    /**
     * List the SOA services
     *
     * @throws Exception
     */
    public static List<DeployedService> getSOA(String host, int port, String username, String password) throws Exception {

        List<DeployedService> result = new ArrayList();

        JMXConnector connector = initConnection(host, port, username, password);
        // get mbean connection
        MBeanServerConnection mbconn = connector.getMBeanServerConnection();

        ObjectName queryObject = new ObjectName("oracle.soa.config:Location=soa_ms01,name=soa-infra,j2eeType=CompositeLifecycleConfig,Application=soa-infra,*");
        Set<ObjectName> queryObjectName = mbconn.queryNames(queryObject, null);
        Iterator iterator = queryObjectName.iterator();

        while (iterator.hasNext()) {
            ObjectName compositeObjectName = (ObjectName) iterator.next();

            CompositeData[] composites = (CompositeData[]) mbconn.getAttribute(compositeObjectName, "DeployedComposites");
            for (CompositeData composite : composites) {
                String dn = (String) composite.get("DN");
                Boolean isDefault = (Boolean) composite.get("isDefault");
                String state = (String) composite.get("state");
                String mode = (String) composite.get("mode");

                if (isDefault && state.equalsIgnoreCase("on") && mode.equalsIgnoreCase("active")) {
                    DeployedService service = new DeployedService();
                    service.setName(dn.substring(dn.indexOf('/') + 1, dn.indexOf('!')));
                    service.setVersion(dn.substring(dn.indexOf('!') + 1, dn.indexOf('*')));
                    if (!result.contains(service)) {
                        result.add(service);
                    }
                }
            }
        }
        connector.close();
        return result;
    }

As you can see the CompositeData data has all of the data we need. We can check if the composite is Active and if it is Default and we can extract the version from the DN. As for dependencies, I suspected I would need the wlfullclient and probably some other jars. Netbeans neatly suggested the dependencies for me from my local maven repository and it seemed I only needed 1 which was soa-infra-mgmt. So my first dependcies where:

        <dependency>
            <groupId>com.oracle.weblogic</groupId>
            <artifactId>wlfullclient</artifactId>
            <version>12.1.3</version>
        </dependency>
        <dependency>
            <groupId>com.oracle.soa</groupId>
            <artifactId>soa-infra-mgmt</artifactId>
            <version>12.1.3-0-0</version>
            <type>jar</type>
        </dependency>

Next but is the OSB. This was a bit more tricky as the OSB doesn’t support versioning. We worked around this issue by adding version info in the description field of the project. See here for an explanation. So it was kind of obvious there was no mbean to retrieve this info. The best way I found was just to export all the project, unzip them and just loop through all the projects and check their description field. The code looks like this:

    /**
     * List all the OSB services
     *
     * @throws Exception
     */
    public static List<DeployedService> getOSB(String host, int port, String username, String password) throws Exception {

        List<DeployedService> result = new ArrayList();

        // get the jmx connector
        JMXConnector connector = initConnection(host, port, username, password);

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

        // get domain service mbean. This is the topmost mbean
        DomainRuntimeServiceMBean domainService = (DomainRuntimeServiceMBean) MBeanServerInvocationHandler.
                newProxyInstance(mbconn, new ObjectName(DomainRuntimeServiceMBean.OBJECT_NAME));

        // Obtain MBean for peforming read only operations. Notice that the name
        // of the mbean for the core data does not contain any session name.
        ALSBConfigurationMBean alsbCore = (ALSBConfigurationMBean) domainService.findService(ALSBConfigurationMBean.NAME, ALSBConfigurationMBean.TYPE, null);

        Set<Ref> refs = alsbCore.getProjects();
        byte[] contentsProj = alsbCore.exportProjects(new ArrayList(refs), null);

        //write the projects to the target directory
        FileOutputStream fos = new FileOutputStream("target/export-sbconfig.jar");
        fos.write(contentsProj);
        fos.close();

        //unzip the zip file
        File unzipDir = new File("target/export-sbconfig");
        FileUtils.unZipIt("target/export-sbconfig.jar", unzipDir);

        //loop through them and read the value
        File[] files = unzipDir.listFiles();
        DeployedService service;
        for (File file : files) {
            //name of the directory
            String name = file.getName();
            if (name.contains("_")) {
                String description = XMLUtils.readDescription(file.getAbsolutePath() + "/_projectdata.LocationData");
                service = new DeployedService();
                service.setNaam(name);
                service.setVersie(description);
                result.add(service);
            }
        }

        //delete the zip and the unzip dir
        FileUtils.delete(unzipDir);
        FileUtils.delete(new File("target/export-sbconfig.jar"));

        connector.close();
        return result;
    }

As you can see I export the zip file to the target directory, unzip it there and then loop through them and checking the _projectdata.LocationData file. What about the dependencies here? Netbeans found the obvious ones for me which where module-kernel-api and module-configfwk both in com.oracle.servicebus.core. So

        <dependency>
            <groupId>com.oracle.servicebus.core</groupId>
            <artifactId>module-kernel-api</artifactId>
            <version>12.1.3-0-0</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>com.oracle.servicebus.core</groupId>
            <artifactId>module-configfwk</artifactId>
            <version>12.1.3-0-0</version>
            <type>jar</type>
        </dependency>

Well that seemed about right. I tried to give it a spin but unfortunately I ran into a ClassNotFoundException……..specificaly com.bea.wli.sb.management.configuration.DelegatedALSBConfigurationMBean. It seemed I needed something else at runtime. After some Googling, I found out the jar I needed was sb-kernel-impl.jar but I couldn’t find it anywhere on the 12C installation. In a 11G installation, it was under OSB_DOMAIN/lib so I spinned up an old 11G VM and grabbed the jar and uploaded it into my maven repo. Again, give it a try…..and there we go….it work. Next I tweaked it a bit so I could start it from Jenkins and it would output the list in easy readable format. The result look like this.

overview

SOA Suite 12C: Generating a JSON Web Token (JWT) in OSB

“JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for creating access tokens that assert some number of claims. For example, a server could generate a token that has the claim “logged in as admin” and provide that to a client. The client could then use that token to prove that it is logged in as admin. The tokens are signed by the server’s key, so the client is able to verify that the token is legitimate. The tokens are designed to be compact, URL-safe and usable especially in web browser single sign-on (SSO) context. JWT claims can be typically used to pass identity of authenticated users between an identity provider and a service provider, or any other type of claims as required by business processes. The tokens can also be authenticated and encrypted.” Wikipedia

jwt

I guess the above text says it all. I won’t be going into all the JWT details as you can read most of it online on JWT.io. For my current customer I had to interface with a SaaS product which used JWT as authentication measure. There are quite some libraries for Java which you can use to generate tokens. To mention a few:

  • com.auth0.java-jwt
  • org.bitbucket.b_c.jose4j
  • com.nimbusdsnimbus.jose-jwt
  • io.jsonwebtoken.jjwt

Easy as I thought, I grabbed the most obvious one I could find and created a simple class which could create a token for me. Sounded fairly easily but the used jar also had it’s dependencies which of course had to be available in Weblogic also for it to work. This is where the problem started as the dependencies seem to cause some class loading issues. I tried another JWT implementation but this also seem to cause some issues. After some googling I found that Oracle also had JWT support looking at the page. The only thing I really couldn’t find very quickly was which jars I needed and where they where….

After some poking around in my Oracle_Home I found the right jars though. The ones you need to create a token are:

  • osdt_cert.jar
  • osdt_core.jar
  • osdt_restsec.jar
  • jackson-core-asl-1.1.1.jar
  • jackson-mapper-asl-1.1.1.jar

The first 3 are located in your OracleHome\oracle_common\modules\oracle.osdt_12.1.3 folder. The 2 jackson ones you can just grab of the internet
These jars contain all the classes you need to create a token and verify it in your Java development environment. The first three are already on your Weblogic classpath. The two Jackson also seem to be somewhere on the server although the documentation makes you think otherwise but I didn’t need to put the 2 Jackson libraries somewhere on the server to make it work.

To create a token you can just use the following code for example:

package nl.redrock.jwt;

import oracle.security.restsec.jwt.*;

public class JWTGenerator {
    
    
    public static String generateJWT(String aCode, String aAmount, String aKey) throws Exception {
        
        String result = null;
        
        JwtToken jwtToken = new JwtToken();
        //Fill in all the parameters- algorithm, issuer, expiry time, other claims etc
        jwtToken.setAlgorithm(JwtToken.SIGN_ALGORITHM.HS512.toString());
        jwtToken.setType(JwtToken.JWT);
        jwtToken.setClaimParameter("Amount", aAmount);
        jwtToken.setClaimParameter("Code", aCode);
        // Get the private key and sign the token with a secret key or a private key
        result = jwtToken.signAndSerialize(aKey.getBytes());
        return result;
    }
}

To call the generateJWT class, just create a custom xquery lib file…in my case custom-redrock-xquery.xml which looks like this:

<?xml version="1.0" encoding="UTF-8" ?>
<xpf:xpathFunctions xmlns:xpf="http://www.bea.com/wli/sb/xpath/config">
	<xpf:category id="RedRock Custom Functions">
		<xpf:function>
			<xpf:name>generateJWT</xpf:name>
			<xpf:comment>Generate a JSON Web Token based on inputs</xpf:comment>
			<xpf:namespaceURI>http://www.redrock.nl/soa/xpath</xpf:namespaceURI>
			<xpf:className>nl.redrock.jwt.JWTGenerator</xpf:className>
			<xpf:method>java.lang.String generateJWT(java.lang.String, java.lang.String, java.lang.String)</xpf:method>
			<xpf:isDeterministic>false</xpf:isDeterministic>
			<xpf:scope>Pipeline</xpf:scope>
			<xpf:scope>SplitJoin</xpf:scope>
		</xpf:function>
	</xpf:category>
</xpf:xpathFunctions>

Stick this file under OracleHome\osb\config\xpath-functions along with the jar-file which contains your utility class and dont’t forget the osdt_restsec.jar as it is a dependency which seems to be needed at deploytime. Then start JDev up and in XQuery Expression builder popup you should now see the custom xquery.

xqueryexpressionbuilder

Now just deploy you project to the servicebus and run a test. If you enable execution tracing you will see that the assign works and we get a token.

token

Next select the token and go to JWT.io and check if it verifies:

jwtcheck

Using the Coherence Adapter in SOA Suite 12C

Retrieving data from a back-end system or executing something in a business rule engine can cost quite some time. When we build services we want to strife for performance but sometimes you make services which you just can’t make any faster. One thing to keep in mind is that it is possible to cache in SOA Suite using the coherence adapter. For example retrieving data from a back-end system in a composite and enriching it takes 1400ms average but during a 24 hours, you might get 15% call with the same request, which should give exactly the same answer! To do the retrieving and enrichment every time seems like a shame. This is where the Coherence adapter comes in.

The Coherence adapter can store certain pieces of data for a certain amount of time. This overview consists of 2 parts. The first one is the configuration of the coherence adapter in weblogic, the second part is the usage of the coherence adapter in a composite. Now lets get started.

Configuring the Coherence adapter

  1. The Coherence adapter isn’t active out of the the box. It is not targeted to any managed server so the first thing you have to do is to target it.

    Go to your SOA server’s console, go to Deployments and click the CoherenceAdapter. Go the the tab Targets. Look if it is targeted. If it is not….target it. Click Lock & Edit and check soa_cluster checkbox, click Save and Activate Changes: Target

  2. The next step is to add cache configuration file. This step requires that you have to physically put an XML on the file system of the server. In our example it is a file called ProductServiceCache-Configuration.xml and sat in location /u01/domains/dev_soa_domain. On a clustered environment the file have to be on both servers! My configuration file looks like:
    <?xml version="1.0"?>
    <!DOCTYPE cache-config SYSTEM "cache-config.dtd">
    <cache-config>
      <caching-scheme-mapping>
        <cache-mapping>
          <cache-name>ProductServiceCache</cache-name>
          <scheme-name>transactional</scheme-name>
        </cache-mapping>
      </caching-scheme-mapping>
      <caching-schemes>
        <transactional-scheme>
          <scheme-name>transactional</scheme-name>
          <service-name>DistributedCache</service-name>
          <autostart>true</autostart>
        </transactional-scheme>
      </caching-schemes>
    </cache-config>
    

    It is wise to create separate caches for separate services in case you want to set different cache timers or in case of the occasional flush.

  3. The next step is creating a Coherence Adapter Connection Factory. Go to your SOA environment console, deployments and click on the Coherence Adapter. Go to the tab Outbound Connection Pools. Click New. Choose javax.resource.cci.ConnectionFactory. Input your JNDI name. I will have eis/Coherence/ProductService and click Finish. Now select the connection factory you just created and choose the Properties tab. Set the following values:ConnectionFactorySettings
  4. As a last step, you will have to update the CoherenceAdapter with the settings. You can do this by stopping en starting the CoherenceAdapter. Go to Deployments and click Lock & Edit. Select the checkbox of the CoherenceAdapter and click Update and the Finish.
    CoherenceAdapter

Oke now we have configured Coherence including a cache for the ProductService.

Making use of the Coherence adapter in a composite

To make use of the adapter in your BPEL, you will have to add 2 JCA connections.
Coherence-JCA

We are going to call them retrieveResult and writeResult. Lets start of with the retrieveResult. Drag the Coherence Adapter onto the right part of the canvas and follow the wizard:

RetrieveResult

On the step 4 when pressing Finish it will ask you No cache key specified. No worries as we will do this later on.

No we will create a writeResult JCA adapter:
WriteResult I set the Time To Live of the cache to 10.000 milliseconds for the test.

Now wire your BPEL to your 2 adapters like you would normally do. This would look like this then.

CompleteComposite

Now in your BPEL you want to do 2 things:

  • Check if something is in the cache based on your key, and if it is return the result.
  • If it is not in there, do your normal thing and write the result into the cache

The reading and writing can take place like normal call-outs as you can see. Just drag an Invoke action onto your BPEL and wire it the correct Partnerlink. Lets first do the retrieve. Invoke the retrieveResult and create input and output variables like you would normally do. For the unique key, go to the Properties tab and add property jca.coherence.Key. Here you define the unique key for your result. I just concatenated some string from the request.

retrieveCall

In your BPEL you can check if the retrieve call gave you some data back. If it did, you can skip all the normal processing and just return the result. If you ended up with nothing, you want to do normal processing and at the end, write the result to the cache. Use the same Property again and make sure you assign the expression or variable which you used to retrieve something.

retrieveCall

It is that easy. My composite will look something like this now:
final

Now just build and deploy and see if it works!

My first soap call takes about 1777 ms….and that is without a cache hit. Now lets call it again within 10 seconds. There we go….800 ms. Now let check the EM to see if we hit the actual cache:

EM

There we go!

Some considerations:

  • This is an easy way to make things faster. Do keep checking with Performance, Load and Stress tests what will happen to you CPU and Memory usage on big loads. The A-team have some good articles about this.
  • You might want to have the Time-To-Live different per environment. So for example 10 minutes on Dev but 1 hour on Test and 24 houres on Prod. You can easily do this making use of server tokens. Add them in the EM under tokens and use them in the JCA files like ${ProductServiceCacheTime} for example.

References:

  • http://www.ateam-oracle.com/using-the-12c-coherence-adapter-to-access-a-non-transactional-local-cache/
  • https://docs.oracle.com/middleware/1221/adapters/develop-soa-adapters/GUID-EA82A9A3-656E-464A-B764-E076C172BAEF.htm#TKADP2495

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.

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

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.

Oracle Fusion Middleware 12C: Deploy the MDS using Maven

In two previous posts here and here, I demonstrated how you can setup CI for OFM 12C projects. One of the things I hadn’t figured out yet was how I could deploy the MDS using Maven. After a vague hint on the internet, Oracle’s response that this feature wasn’t officially supported yet and some trial and error I came across the solution. It is actually quite simple.

Basically it comes down to this:

  • Create a zip file of the files you want to stick into the MDS
  • Use the com.oracle.soa.plugin:oracle-soa-plugin:deploy maven goal to deploy it

That wasn’t that hard as you can see :) Let’s go into a bit more detail. You can use a command line to create the zip or use the maven-assembly-plugin to give you a bit more flexibility. I used the last option because I wanted to filter certain files. Within my Jenkins job, I checked out my MDS files and zipped them using the package goal into a file called sca-MDS_rev1.0.jar. Look in the plugin section in the pom file down below to see about the configuration of the assembly plugin. The pom file is just a copy of a normal soa composite project.

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
         <!--
           This POM was automatically generated during SOA project creation.           
           This POM relates to this SOA Composite, i.e. the one in this same directory.
           There is another POM in the SOA Application directory which handles
           the whole SOA Application, which may contain additional projects. 
        -->
    <modelVersion>4.0.0</modelVersion>
    <groupId>nl.cvgz</groupId>
    <artifactId>MDS</artifactId>
    <version>1.0</version>
    <packaging>sar</packaging>
    
    <!--
           The parent points to the common SOA parent POM.  That is a special POM that is
           shipped by Oracle as a point of customization (only). You can add default values
           for properties like serverUrl, etc. to the SOA common parent POM, so that you
           do not have to specify them over and over in every project POM.
    --> 
    <parent>
        <groupId>com.oracle.soa</groupId>
        <artifactId>sar-common</artifactId>
        <version>12.1.3-0-0</version>
    </parent>
    
    <properties>
        <!-- These parameters are used by the compile goal -->
        <scac.input.dir>${project.basedir}\SOA/</scac.input.dir>
        <scac.output.dir>${project.basedir}/target</scac.output.dir>
        <scac.input>${scac.input.dir}/composite.xml</scac.input>
        <scac.output>${scac.output.dir}/out.xml</scac.output>
        <scac.error>${scac.output.dir}/error.txt</scac.error>
        <scac.displayLevel>1</scac.displayLevel>
        <!-- if you are using a config plan, uncomment the following line and update to point
             to your config plan -->
        <!--<configplan>${scac.input.dir}/configplan.xml</configplan>-->
        
        <!-- These parameters are used by the deploy and undeploy goals --> 
        <composite.name>${project.artifactId}</composite.name>
        <composite.revision>${project.version}</composite.revision>
        <composite.partition>default</composite.partition>        
        <serverUrl>${oracleServerUrl}</serverUrl>        
        <user>${oracleUsername}</user>
        <password>${oraclePassword}</password>
        <overwrite>true</overwrite>
        <forceDefault>true</forceDefault>
        <regenerateRulebase>false</regenerateRulebase>
        <keepInstancesOnRedeploy>false</keepInstancesOnRedeploy>
        
        <!-- These parameters are used by the test goal 
         if you are using the sca-test (test) goal, you need to uncomment the following
             line and point it to your jndi.properties file. --> 
             
        <!--<jndi.properties.input>UNDEFINED</jndi.properties.input>-->
        <scatest.result>${scac.output.dir}/testResult</scatest.result>
        <!--  input is the name of the composite to run test suties against -->
        <input>${project.artifactId}</input>
        
        <!--<scac.ant.buildfile>${env.MW_HOME}/soa/bin/ant-sca-compile.xml</scac.ant.buildfile>
        <sca.ant.testfile>${env.MW_HOME}/soa/bin/ant-sca-test.xml</sca.ant.testfile>
        -->
        
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>com.oracle.soa.plugin</groupId>
                <artifactId>oracle-soa-plugin</artifactId>
                <version>12.1.3-0-0</version>
                <configuration>
                    <compositeName>${project.artifactId}</compositeName>
                    <composite>${scac.input}</composite>
                    <sarLocation>${scac.output.dir}/sca-${project.artifactId}_rev${composite.revision}.jar</sarLocation>
                    <serverUrl>${serverUrl}</serverUrl>
                    <user>${user}</user>
                    <password>${password}</password>
                    <!-- Note: compositeRevision is needed to package, revision is needed to undeploy -->
                    <compositeRevision>${composite.revision}</compositeRevision>
                    <revision>${composite.revision}</revision>
                    <scacInputDir>${scac.input.dir}</scacInputDir>                    
                    <input>${input}</input> 
                </configuration>
                <!-- extensions=true is needed to use the custom sar packaging type -->
                <extensions>true</extensions>
            </plugin>
	    <!-- plugin om te zorgen dat de apps directory gezipt wordt voor de MDS -->
	    <plugin>
			<artifactId>maven-assembly-plugin</artifactId>
			<version>2.4.1</version>
			<configuration>
				<finalName>sca</finalName>
				<descriptors>
					<descriptor>zip-assembly-descriptor.xml</descriptor>
				</descriptors>
			</configuration>
			<executions>
				<execution>
					<id>make-assembly</id>
					<phase>package</phase>
					<goals>
						<goal>single</goal>
					</goals>
				</execution>
		     </executions>
		</plugin>
        </plugins>
    </build>
</project>

Here is the zip-assembly-descriptor.xml

<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
  <id>MDS_rev1.0</id>
  <baseDirectory>/</baseDirectory>
  <formats>
    <format>jar</format>
  </formats>
  <fileSets>
	<fileSet>
      <directory>../../../GedeeldeObjecten/apps</directory>
      <outputDirectory>/</outputDirectory>
	  <includes>
        <include>services/**</include>
		<include>dvm/**</include>
      </includes>
    </fileSet>
	
  </fileSets>
</assembly>

As you can see I create a jar which includes my services and dvm directory. One thing to take in account is that you don’t need an apps directory in the zip. At first I created an apps directory as a top directory but when I deployed this, my MDS had a apps/apps structure so I removed this. My sca-MDS_rev1.0.jar has the following structure:

-dvm
   -MyDVM.dvm
-services
   -HelloService_1.0
       -HelloService_1.0.xsd
       -HelloService_1.0.wsdl

The only now left to do is to point the ${scac.output.dir}/sca-${project.artifactId}_rev${composite.revision}.jar in the pom to the right location where your jar file is located.

When you run the com.oracle.soa.plugin:oracle-soa-plugin:deploy goal, maven will deploy you MDS jar like this:

[INFO] --- maven-assembly-plugin:2.4.1:single (make-assembly) @ MDS ---
[INFO] Reading assembly descriptor: zip-assembly-descriptor.xml
[INFO] Building jar: D:\tomcatfiles\.jenkins\jobs\SOA - MDS\workspace\MDS\soa\MDS\target\sca-MDS_rev1.0.jar
[INFO] 
[INFO] --- oracle-soa-plugin:12.1.3-0-0:deploy (default-cli) @ MDS ---
[INFO] ------------------------------------------------------------------------
[INFO] ORACLE SOA MAVEN PLUGIN - DEPLOY COMPOSITE
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] setting user/password..., user=weblogic
Processing sar=D:\tomcatfiles\.jenkins\jobs\SOA - MDS\workspace\MDS\soa\MDS/target/sca-MDS_rev1.0.jar
Adding shared data file - D:\tomcatfiles\.jenkins\jobs\SOA - MDS\workspace\MDS\soa\MDS\target\sca-MDS_rev1.0.jar
INFO: Creating HTTP connection to host:MY_SERVER, port:7010
INFO: Received HTTP response from the server, response code=200
---->Deploying composite success.
[JENKINS] Archiving disabled
[JENKINS] Archiving disabled[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 24.313 s

[INFO] Finished at: 2015-05-23T02:59:22+02:00
[INFO] Final Memory: 36M/360M
[INFO] ------------------------------------------------------------------------
[workspace] $ cmd /c call D:\ProgramFiles\Apache\Tomcat8.0\temp\hudson4288153212971789360.bat
channel stopped

OFM 12C: An example of the Business Rule Engine with Java facts

One of the components of the Oracle SOA Suite is the Business Rule Engine. The Oracle Business Rules engine….and I quote ‘allows the externalization of specific business logic and
parameters. Business analysts can easily define, update, and manage key parameters and decision trees that are likely to change based on business evolution (for instance discount levels, credit rates, etc.) without having to involve IT and developers.

This all sounds pretty nice but I haven’t seen it implemented anywhere yet but lately I have been working for a customer which has a good case to actually use the BRE so I had time look into it. In this blog I will show you a basic way to use the BRE using a decisions table and with the use of some custom Java facts.

A simple explanation: We have persons who wants to insure themselves from a certain date with a certain type of insurance. We are going to use the BRE to determine whether they are allowed to do this. We are going to use a decision table instead of if-then-else structures and in the decision table we are going to use java facts which we created to make certain functions more easy to define.

Lets start of with a simple SOA project. I created a simple schema with a input and output.

<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:rr="http://nl.redrock-it"
            targetNamespace="http://nl.redrock-it" elementFormDefault="qualified">
  <xsd:element name="breExampleRequest">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="dateOfBirth" type="xsd:date"/>
        <xsd:element name="startDate" type="xsd:date"/>
        <xsd:element name="insuranceType">
          <xsd:simpleType>
            <xsd:restriction base="xsd:string">
              <xsd:enumeration value="Basic"/>
              <xsd:enumeration value="Better"/>
              <xsd:enumeration value="Best"/>
            </xsd:restriction>
          </xsd:simpleType>
        </xsd:element>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
  <xsd:element name="breExampleResponse">
    <xsd:complexType>
      <xsd:sequence>
        <xsd:element name="result" type="xsd:boolean"/>
      </xsd:sequence>
    </xsd:complexType>
  </xsd:element>
</xsd:schema>

Lets add a Mediator to the composite and expose it as a web service.

createMediator

Now lets create the BRE component. Drag the Business Rule into the composite. Input a name and select the input and output where you can select the request and response we have previously defined in the insurance.xsd and press OK.

createBR

If you edit the Business Rule you have different tabs.

BRtabs

Settings has some general settings as expected. The Facts tabs hold the request and response data structures which you will be using. These should already have the breExampleRequest and breExampleResponse in there. Also the checkbox visible should have been checked as we are going to use them.

BRfacts

In the Globals tab we can define globals which we might be using. We are going to define here the AdultAge.

BRglobal

Now lets create the actual ruleset. Go to the generated RuleSet1. Rename the RuleSet1 to InsuranceRuleSet. Then add a DecisionTable.

BRruleset

When you create the DecisionTable it opens automatic. A decision table is like a matrix. You have Conditions which together with Rules result into Actions. Lets insert a Condition first.

BRCondition

Now select the InsuranceType from the breExampleRequest.

BRConditionConfig

After this we can input the possible value which will be “Basic”. Now lets attach an action to it.

BRAction

Double-click the action and the popup opens. Here we can select from the facts the breExampleResponse and select the fact its parameterized.

BRActionConfig

Now press OK. Then add a value to the action which will be the simple boolean value “true”.

BRActionValue

Now we have 1 Rule but we want 3 so we at least can see the difference which different inputs so lets create an two extra Rules with the following values:

R1R2R3

So basically this ruleset should return “true” when I pick the insurance of type “Basic” and “false” if pick the insurance of type “Better” or “Best”. Before we connect it all together we have to define the interface for the BusinessRule component on the Decision Functions tab. Here we will configure the webservice interface which we will use to call the business rule. Go to the Decisions Functions tab and double click on the already created decision function. In the next popup you can define the name, the name of the operation of the webservice and the input and output. Also make sure the ruleset is selected on the Rule Sets & Decision Functions tab.

DecisionFunction

Now connect the mediator to the business rule. As you can see the BusinessRule component as an interface to which we can connect.

connecting

Make sure you map the input and output in the mediator.

Mapping

Now that it is all hooked up together, lets deploy it and give it a spin. I use SoapUI to call the service and lets see what happens.

SoapUITest

As you can see, we get TRUE for the ‘Basic’ insurance but FALSE for the ‘Better’ and ‘Best’ option. So now we have seen how to make use of a simple decision table. In a business environment, you probably want some more complex functions in the decision table. There are possibilities to make use of functions but from what I have seen, these are quite limited and not very clear on their usages. Another option is to write functions yourself using Java. You create a jar file which contain classes with your helper functions. I will demonstrate below how this works.

First create a simple class with a helper function. I created a simple class with a static function which determines if a person is an adult on a certain date. This will look like this:

package nl.redrock.bre;

import java.util.Calendar;
import javax.xml.datatype.XMLGregorianCalendar;

/**
 *
 * @author Hugo Hendriks
 */
public class Insurance {
    
    /**
     * Check whether the person is already an adult at the startDate
     * @param aStartDate the starting date
     * @param aBirthDate the day of birth
     * @param aAdultAge the legal age a person becomes an adult
     * @return true or false
     */
    public static boolean isAdultAtDate(XMLGregorianCalendar aStartDate, XMLGregorianCalendar aBirthDate, int aAdultAge){
     
        boolean result = false;
        
        Calendar birthdayLegalAge = aBirthDate.toGregorianCalendar();
        birthdayLegalAge.add(Calendar.YEAR, aAdultAge);
        
        if(birthdayLegalAge.before(aStartDate.toGregorianCalendar())){
            result = true;
        }
        return result;
    }
    
}

Keep in mind that xsd:date is tranformed to an XMLGregorianCalendar object. As a good practice write a JUnit test for it to check if it works as desired and build a jar. I am using maven so this would be the outcome.

Scanning for projects...

Using the builder org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder with a thread count of 1
                                                                        
------------------------------------------------------------------------
Building BRE-Test 1.0
------------------------------------------------------------------------

--- maven-clean-plugin:2.5:clean (default-clean) @ BRE-Test ---
Deleting D:\Amazon EC2\SVN\trunk\java\BRE-Test\target

--- maven-resources-plugin:2.6:resources (default-resources) @ BRE-Test ---
Using 'UTF-8' encoding to copy filtered resources.
skip non existing resourceDirectory D:\Amazon EC2\SVN\trunk\java\BRE-Test\src\main\resources

--- maven-compiler-plugin:2.5.1:compile (default-compile) @ BRE-Test ---
Compiling 1 source file to D:\Amazon EC2\SVN\trunk\java\BRE-Test\target\classes

--- maven-resources-plugin:2.6:testResources (default-testResources) @ BRE-Test ---
Using 'UTF-8' encoding to copy filtered resources.
skip non existing resourceDirectory D:\Amazon EC2\SVN\trunk\java\BRE-Test\src\test\resources

--- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ BRE-Test ---
Compiling 1 source file to D:\Amazon EC2\SVN\trunk\java\BRE-Test\target\test-classes

--- maven-surefire-plugin:2.12.4:test (default-test) @ BRE-Test ---
Surefire report directory: D:\Amazon EC2\SVN\trunk\java\BRE-Test\target\surefire-reports

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running nl.redrock.bre.InsuranceTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.098 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0


--- maven-jar-plugin:2.4:jar (default-jar) @ BRE-Test ---
Building jar: D:\Amazon EC2\SVN\trunk\java\BRE-Test\target\BRE-Test-1.0.jar
------------------------------------------------------------------------
BUILD SUCCESS
------------------------------------------------------------------------
Total time: 4.922 s
Finished at: 2015-01-09T12:17:07+01:00
Final Memory: 13M/126M
------------------------------------------------------------------------

Now I have a jar containing the class which I want to use but how do I get in into my designtime environment? Very simple…just drop the jar file into the \SOA\.rulesdesigner\jaxb_classes folder….in my case BreTestProject\SOA\.rulesdesigner\jaxb_classes. Now lets go back to the Business Rule component. Go to the Facts tab and the Java Fact tab below and click Add.

AddJavaFact

In the popup select Add and select the .jar file we have just copied. When selected, the tree below should display the classes. Select the Insurance class and click OK.

SelectJar

You should see the class now in the list of Java facts. Now for the magic. Go to your decision table and add a new condition. Double click it and click the calculator icon on the top right. In the popup select the method from the Functions tab and select the right input parameters from the variables tab. We also put in there the AdultAge from the Constant tab we had defined before.

JavaFactCondition

The table will look like this now.

JavaFactDT

Now compile and deploy again. Don’t forget to add the jar into the /lib directory and restart your domain. When we run our SoapUI test you will see it also takes the Java check in the decision table into account.

Down the line the business rule component can help you, by putting some business logic into your middleware layer which can be edited through the soa-composer. The Java facts work quite nicely when the IDE is stable and the decision table works as it should. Sorting certain business functionality in the decision table instead of the decision tables takes some head twisting.

Thing to take into consideration:

  • There is a memory leak in the DecisionTable IDE editor. When you open it, the table will start to eat resources and eventually crash especially when you have a lot of columns and rows. There is a patch available but will also introduce a new bug which crashes the IDE completely! Un-patching using opatch seemed to get rid of the crash and of the memory leak.
  • There are classes being generated when you define your interface. If you want to change the interface later on, you have to delete and create the classes again or else you will run into errors here.
  • The BRE component has it’s fits. Sometimes you will have strange glitches or unexplainable behavior. I think this comes to the fact that not many customers use it so it doesn’t receive much love from Oracle :)

CI using Oracle Fusion Middleware 12C: Part 2. Building a SB and SOA project using maven and the MDS

In the part 1 I have shown how to setup a simple CI environment and how to build a Service Bus project using Maven. In this part I will try to make a release pipeline which builds, deploys, tests, packages and release a whole service using Jenkins and if all successful and finally install the artifact in Nexus.

Lets start where we left of. Startup Tomcat and log into Jenkins. We need some sort of plugin to be able to run multiple actions in a sequence. Jenkins has alot of plugins but the one which I am going to use is the MultiJob one. Go to Manage Jenkins->Manage plugins, choose the available tab, check the Multijob plugin and click Install without restart.

Multijob

The multi-job plugin can chain jobs together and share variables and artifact between jobs. You can make very intricate jobs but for now I will keep it simple. I will make 1 job that will:

  1. Build the service bus component which also refers to a SharedObjects project and deploy it to my server
  2. Build the soa component which also refers to the MDS and deploy it to my server
  3. Run the matching soap ui test
  4. If succesfull, install the artifact to nexus

I have created a simple HelloService which first goes to the SB and then routes to a SOA component. The SB component makes use of a SharedObjects SB project which holds the WSDL and XSD. This project is setup so you don’t have to sync between this project and the MDS. This because the SB isn’t able yet to access the MDS. The SOA component does nothing else the return a string response. So the setup will look like this:

HelloService

So the first job we have to create is one which builds and deploys an SB project using maven. We will have to have 2 jobs as we want to deploy the SharedObjects project and we want to deploy the SB service afterwards. Lets make the SharedObject first. This is an easy one as it has no references to any other project.

Create a new Jenkins job called OSB – SharedObjects which is based on a maven project. The .pom file is very simple. This will look 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.cvgz</groupId>
	<artifactId>GedeeldeObjecten</artifactId>
	<version>1.0</version>
	<packaging>sbar</packaging>
	<description/>
</project>

As a maven goal we can just use the following command to build and deploy the SharedObject project to the designated server:

clean pre-integration-test -DoracleHome=${oracleHome} -DoracleServerUrl=${osbServername} -DoracleUsername=${osbUsername} -DoraclePassword=${osbPassword}

You can insert the variables from a property file as you can see. Now lets try this first job and see how it runs.

SharedObjects-jenkins

Started by user Hugo Hendriks
[EnvInject] - Loading node environment variables.
Building in workspace D:\tomcatfiles\.jenkins\jobs\OSB - GedeeldeObjecten\workspace
Cleaning local Directory GedeeldeObjecten
Checking out svn://hendriksh@u10023o/mmi/trunk/OSB/GedeeldeObjecten at revision '2015-02-18T19:18:29.973 +0100'
A         GedeeldeObjecten.jpr
A         apps
A         apps\services
A         apps\services\HelloService
A         apps\services\HelloService\1.0
A         apps\services\HelloService\1.0\HelloService.wsdl
A         apps\services\HelloService\1.0\cdm.xsd
A         apps\services\HelloService\1.0\HelloService.xsd
A         servicebus.sboverview
A         alerts
A         alerts\Log.alert
A         alerts\ErrorDestination.alert
A         pom.xml
 U        .
At revision 927
Cleaning local Directory Build
Checking out svn://hendriksh@u10023o/mmi/trunk/build at revision '2015-02-18T19:18:29.973 +0100'
A         build-env-TST.properties
A         build-env-ONT.properties
At revision 927
no change for svn://hendriksh@u10023o/mmi/trunk/OSB/GedeeldeObjecten since the previous build
no change for svn://hendriksh@u10023o/mmi/trunk/build since the previous build
[EnvInject] - Executing scripts and injecting environment variables after the SCM step.
[EnvInject] - Injecting as environment variables the properties file path 'Build/build-env-ONT.properties'
[EnvInject] - Variables injected successfully.
Parsing POMs
[GedeeldeObjecten] $ D:\ProgramFiles\Java\jdk1.7.0_71/bin/java -cp D:\tomcatfiles\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven31-agent-1.5.jar;D:\ProgramFiles\Apache\apache-maven-3.2.3\boot\plexus-classworlds-2.5.1.jar;D:\ProgramFiles\Apache\apache-maven-3.2.3/conf/logging jenkins.maven3.agent.Maven31Main D:\ProgramFiles\Apache\apache-maven-3.2.3 D:\ProgramFiles\Apache\Tomcat8.0\webapps\jenkins\WEB-INF\lib\remoting-2.48.jar D:\tomcatfiles\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven31-interceptor-1.5.jar D:\tomcatfiles\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven3-interceptor-commons-1.5.jar 58198
<===[JENKINS REMOTING CAPACITY]===>���channel started
Executing Maven:  -B -f D:\tomcatfiles\.jenkins\jobs\OSB - GedeeldeObjecten\workspace\GedeeldeObjecten\pom.xml clean pre-integration-test -DoracleHome=[MY-ORACLEHOME] -DoracleServerUrl=http://[MY-SERVER] -DoracleUsername=[MY-USER] -DoraclePassword=[MY-PASSWORD]
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building GedeeldeObjecten 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ GedeeldeObjecten ---
[INFO] 
[INFO] --- oracle-servicebus-plugin:12.1.3-0-0:package (default-package) @ GedeeldeObjecten ---
[INFO] 
[INFO] --- oracle-servicebus-plugin:12.1.3-0-0:deploy (default-deploy) @ GedeeldeObjecten ---
[INFO] Service Bus Archive deployed using session Service_Bus_Maven-GedeeldeObjecten-1424283534524.
Diagnostic XML Bean debug log file created: C:\Windows\TEMP\xmlbeandebug7850265000274769465.log
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 02:37 min
[INFO] Finished at: 2015-02-18T19:21:15+01:00
[INFO] Final Memory: 22M/362M
[INFO] ------------------------------------------------------------------------
[JENKINS] Archiving D:\tomcatfiles\.jenkins\jobs\OSB - GedeeldeObjecten\workspace\GedeeldeObjecten\pom.xml to nl.cvgz/GedeeldeObjecten/1.0/GedeeldeObjecten-1.0.pom
[JENKINS] Archiving D:\tomcatfiles\.jenkins\jobs\OSB - GedeeldeObjecten\workspace\GedeeldeObjecten\.data\maven\sbconfig.sbar to nl.cvgz/GedeeldeObjecten/1.0/GedeeldeObjecten-1.0.sbar
D:/tomcatfiles/.jenkins/jobs/OSB - GedeeldeObjecten/workspace/GedeeldeObjecten/pom.xml is not inside D:/tomcatfiles/.jenkins/jobs/OSB - GedeeldeObjecten/workspace/GedeeldeObjecten/GedeeldeObjecten/; will archive in a separate pass
D:/tomcatfiles/.jenkins/jobs/OSB - GedeeldeObjecten/workspace/GedeeldeObjecten/.data/maven/sbconfig.sbar is not inside D:/tomcatfiles/.jenkins/jobs/OSB - GedeeldeObjecten/workspace/GedeeldeObjecten/GedeeldeObjecten/; will archive in a separate pass

channel stopped
Finished: SUCCESS

As you can see….success!

The next bit will be to make a job which deploys the HelloService SB component. This job will actually be quite the same as the previous one except for the fact that it references the SharedObjects project. If you run the normal maven build, it will complain that it can’t find the shared resources. The way to solve this, is to also checkout the SharedObject project during the build in your workspace. This way it can find the project compile time.

Started by user Hugo Hendriks
[EnvInject] - Loading node environment variables.
Building in workspace D:\tomcatfiles\.jenkins\jobs\OSB - Service\workspace
Cleaning local Directory HelloService_v1.0
Checking out svn://hendriksh@u10023o/mmi/trunk/OSB/HelloService_v1.0 at revision '2015-02-18T19:31:12.398 +0100'
A         pom.xml
A         Business
A         Business\HelloService.bix
A         LogPipeline.pipeline
A         HelloPipeline.pipeline
A         Proxy
A         HelloService_v1.0.jpr
A         ValidatePipeline.pipeline
A         HelloService.proxy
A         servicebus.sboverview
At revision 927
Cleaning local Directory GedeeldeObjecten
Checking out svn://hendriksh@u10023o/mmi/trunk/OSB/GedeeldeObjecten at revision '2015-02-18T19:31:12.398 +0100'
A         GedeeldeObjecten.jpr
A         apps
A         apps\services
A         apps\services\HelloService
A         apps\services\HelloService\1.0
A         apps\services\HelloService\1.0\HelloService.wsdl
A         apps\services\HelloService\1.0\cdm.xsd
A         apps\services\HelloService\1.0\HelloService.xsd
A         servicebus.sboverview
A         alerts
A         alerts\Log.alert
A         alerts\ErrorDestination.alert
A         pom.xml
 U        .
At revision 927
Cleaning local Directory Build
Checking out svn://hendriksh@u10023o/mmi/trunk/build at revision '2015-02-18T19:31:12.398 +0100'
A         build-env-TST.properties
A         build-env-ONT.properties
At revision 927
Cleaning local Directory Customization
Checking out svn://hendriksh@u10023o/mmi/trunk/OSB/Customization at revision '2015-02-18T19:31:12.398 +0100'
A         all_BS_ACC.xml
A         all_BS_TST.xml
A         all_BS_ONT.xml
At revision 927
no revision recorded for svn://hendriksh@u10023o/mmi/trunk/OSB/HelloService_v1.0 in the previous build
no change for svn://hendriksh@u10023o/mmi/trunk/build since the previous build
no change for svn://hendriksh@u10023o/mmi/trunk/OSB/Customization since the previous build
[EnvInject] - Injecting environment variables from a build step.
[EnvInject] - Injecting as environment variables the properties file path 'Build/build-env-ONT.properties'
[EnvInject] - Variables injected successfully.
Parsing POMs
Modules changed, recalculating dependency graph
[HelloService_v1.0] $ D:\ProgramFiles\Java\jdk1.7.0_71/bin/java -cp D:\tomcatfiles\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven31-agent-1.5.jar;D:\ProgramFiles\Apache\apache-maven-3.2.3\boot\plexus-classworlds-2.5.1.jar;D:\ProgramFiles\Apache\apache-maven-3.2.3/conf/logging jenkins.maven3.agent.Maven31Main D:\ProgramFiles\Apache\apache-maven-3.2.3 D:\ProgramFiles\Apache\Tomcat8.0\webapps\jenkins\WEB-INF\lib\remoting-2.48.jar D:\tomcatfiles\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven31-interceptor-1.5.jar D:\tomcatfiles\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven3-interceptor-commons-1.5.jar 58247
<===[JENKINS REMOTING CAPACITY]===>���channel started
Executing Maven:  -B -f D:\tomcatfiles\.jenkins\jobs\OSB - Service\workspace\HelloService_v1.0\pom.xml clean pre-integration-test -DoracleHome=[MY-ORACLEHOME] -DoracleServerUrl={MY-SERVER} -DoracleUsername=[MY-USER] -DoraclePassword=[MY-PASSWORD]
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building HelloService 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ HelloService ---
[INFO] 
[INFO] --- oracle-servicebus-plugin:12.1.3-0-0:package (default-package) @ HelloService ---
[INFO] 
[INFO] --- oracle-servicebus-plugin:12.1.3-0-0:deploy (default-deploy) @ HelloService ---
[INFO] Service Bus Archive deployed using session Service_Bus_Maven-HelloService-1424284297240.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 34.955 s
[INFO] Finished at: 2015-02-18T19:31:56+01:00
[INFO] Final Memory: 23M/226M
[INFO] ------------------------------------------------------------------------
Waiting for Jenkins to finish collecting data
[JENKINS] Archiving D:\tomcatfiles\.jenkins\jobs\OSB - Service\workspace\HelloService_v1.0\pom.xml to nl.cvgz/HelloService/1.0/HelloService-1.0.pom
[JENKINS] Archiving D:\tomcatfiles\.jenkins\jobs\OSB - Service\workspace\HelloService_v1.0\.data\maven\sbconfig.sbar to nl.cvgz/HelloService/1.0/HelloService-1.0.sbar
channel stopped
Finished: SUCCESS

Also success! So we now have 2 separate jobs:

      OSB – SharedObjects = which builds and deploys your SharedObject project.
      OSB – Service = which builds and deploys your HelloService project.

The next thing is to do the same for the SOA component. I actually want a SOA – MDS jenkins job which zips and deploys the MDS but it seems Oracle doesn’t support the deployment of the MDS through maven yet. I have heard rumors though that you can zip it and deploy it using the normal maven plugins. I am able to zip the apps directory but I haven’t been able to deploy it yet so if anyone knows how to do this….let me know :)

The last job is a SOA – Service job which builds and deploys the SOA component. When you create a SOA project you get a pom with it. To make this work with the MDS you do have to tweak it here and there. The problem is that the MDS reference is made through the application which references the adf-config.xml. Lets start of with the adf-config.xml which is located in .adf\META-INF. You should make a MDS like this:

<adf-mds-config xmlns="http://xmlns.oracle.com/adf/mds/config">
    <mds-config xmlns="http://xmlns.oracle.com/mds/config">
      <persistence-config>
        <metadata-namespaces>
          <namespace path="/apps" metadata-store-usage="mstore-usage_apps"/>
        </metadata-namespaces>
        <metadata-store-usages>
          <metadata-store-usage id="mstore-usage_apps">
            <metadata-store class-name="oracle.mds.persistence.stores.file.FileMetadataStore">
              <property name="metadata-path" value="${soamds.apps.home}" />
            </metadata-store>
          </metadata-store-usage>
        </metadata-store-usages>
      </persistence-config>
    </mds-config>
  </adf-mds-config>

As you can see we made the metadata-path for the /apps settable using a variable soamds.apps.home. So now you can set the directory of your apps of your application which holds the soa project. Now for the last bit….the .pom file of you soa project. As I said, you will have to tweak some settings here as it doesn’t completely work out of the box. You should make the following adjustments:

<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
         <!--
           This POM was automatically generated during SOA project creation.           
           This POM relates to this SOA Composite, i.e. the one in this same directory.
           There is another POM in the SOA Application directory which handles
           the whole SOA Application, which may contain additional projects. 
        -->
    <modelVersion>4.0.0</modelVersion>
    <groupId>VGZ-SOA-Application</groupId>
    <artifactId>HelloService</artifactId>
    <version>1.0</version>
    <packaging>sar</packaging>
    
    <!--
           The parent points to the common SOA parent POM.  That is a special POM that is
           shipped by Oracle as a point of customization (only). You can add default values
           for properties like serverUrl, etc. to the SOA common parent POM, so that you
           do not have to specify them over and over in every project POM.
    --> 
    <parent>
        <groupId>com.oracle.soa</groupId>
        <artifactId>sar-common</artifactId>
        <version>12.1.3-0-0</version>
    </parent>
    
    <properties>
        <!-- These parameters are used by the compile goal -->
        <scac.input.dir>${project.basedir}\SOA/</scac.input.dir>
        <scac.output.dir>${project.basedir}/target</scac.output.dir>
        <scac.input>${scac.input.dir}/composite.xml</scac.input>
        <scac.output>${scac.output.dir}/out.xml</scac.output>
        <scac.error>${scac.output.dir}/error.txt</scac.error>
        <scac.displayLevel>1</scac.displayLevel>
        <!-- These parameters are used by the deploy and undeploy goals --> 
        <composite.name>${project.artifactId}</composite.name>
        <composite.revision>${project.version}</composite.revision>
        <composite.partition>default</composite.partition>        
        <serverUrl>${oracleServerUrl}</serverUrl>        
        <user>${oracleUsername}</user>
        <password>${oraclePassword}</password>
        <overwrite>true</overwrite>
        <forceDefault>true</forceDefault>
        <regenerateRulebase>false</regenerateRulebase>
        <keepInstancesOnRedeploy>false</keepInstancesOnRedeploy>
        
        <!-- These parameters are used by the test goal 
         if you are using the sca-test (test) goal, you need to uncomment the following
             line and point it to your jndi.properties file. --> 
             
        <!--<jndi.properties.input>UNDEFINED</jndi.properties.input>-->
        <scatest.result>${scac.output.dir}/testResult</scatest.result>
        <!--  input is the name of the composite to run test suties against -->
        <input>${project.artifactId}</input>
        
        <!--<scac.ant.buildfile>${env.MW_HOME}/soa/bin/ant-sca-compile.xml</scac.ant.buildfile>
        <sca.ant.testfile>${env.MW_HOME}/soa/bin/ant-sca-test.xml</sca.ant.testfile>
        -->
        
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>com.oracle.soa.plugin</groupId>
                <artifactId>oracle-soa-plugin</artifactId>
                <version>12.1.3-0-0</version>
                <configuration>
                    <compositeName>${project.artifactId}</compositeName>
                    <composite>${scac.input}</composite>
                    <sarLocation>${scac.output.dir}/sca_${project.artifactId}_rev${composite.revision}.jar</sarLocation>
                    <serverUrl>${serverUrl}</serverUrl>
                    <appHome>../../../</appHome>
                    <!-- Note: compositeRevision is needed to package, revision is needed to undeploy -->
                    <compositeRevision>${project.version}</compositeRevision>
                    <revision>${composite.revision}</revision>
					<scacInputDir>${scac.input.dir}</scacInputDir>
					<user>${user}</user>
                    <password>${password}</password>                    
                    <input>${input}</input> 
                </configuration>
                 <!-- extensions=true is needed to use the custom sar packaging type -->
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>
</project>

You should add

<appHome>../../../</appHome>

to you plugin. This will have to point to the place where your application is located and thus where your .adf/META-INF/adf-config.xml is also. In my case, that is 3 folders up when I do a checkout of my svn. You also have to fix ${project.version} as it will by default generates a 1.0-SNAPSHOT version but it will look for a 1.0 to deploy.

After you have done all this lets create a Jenkins job called SOA – Service and run the following maven command:

clean pre-integration-test -DoracleServerUrl=${soaServername} -DoracleUsername=${soaUsername} -DoraclePassword=${soaPassword}

Don’t forget to set soamds.apps.home=${workspace}\GedeeldeObjecten as environment variable and to also checkout the application.jws including .adf/META-INF/adf-config.xml. Now lets give the job a spin:

Started by user Hugo Hendriks
[EnvInject] - Loading node environment variables.
Building in workspace D:\tomcatfiles\.jenkins\jobs\SOA - Service\workspace
Cleaning local Directory .
Checking out svn://hendriksh@u10023o/mmi/trunk/services at revision '2015-02-18T20:23:09.684 +0100'
A         VGZ-SOA-Application.jws
 U        .
At revision 927
Cleaning local Directory .adf
Checking out svn://hendriksh@u10023o/mmi/trunk/services/.adf at revision '2015-02-18T20:23:09.684 +0100'
A         META-INF
A         META-INF\adf-config.xml
At revision 927
Cleaning local Directory GedeeldeObjecten/apps
Checking out svn://hendriksh@u10023o/mmi/trunk/OSB/GedeeldeObjecten/apps at revision '2015-02-18T20:23:09.684 +0100'
A         services\HelloService
A         services\HelloService\1.0
A         services\HelloService\1.0\HelloService.xsd
A         services\HelloService\1.0\HelloService.wsdl
A         services\HelloService\1.0\cdm.xsd
 U        .
At revision 927
Cleaning local Directory HelloService_v1.0/soa/HelloService_v1.0
Checking out svn://hendriksh@u10023o/mmi/trunk/services/HelloService_v1.0/soa/HelloService_v1.0 at revision '2015-02-18T20:23:09.684 +0100'
A         HelloService_v1.0.jpr
A         SOA
A         SOA\composite.xml
A         SOA\Schemas
A         SOA\Events
A         SOA\Mediators
A         SOA\Mediators\HelloMediator.mplan
A         SOA\measurements.xml
A         SOA\Transformations
A         SOA\WSDLs
A         SOA\testsuites
A         SOA\testsuites\fileList.xml
A         pom.xml
 U        .
At revision 927
Cleaning local Directory Build
Checking out svn://hendriksh@u10023o/mmi/trunk/build at revision '2015-02-18T20:23:09.684 +0100'
A         build-env-TST.properties
A         build-env-ONT.properties
At revision 927
no change for svn://hendriksh@u10023o/mmi/trunk/services/.adf since the previous build
no revision recorded for svn://hendriksh@u10023o/mmi/trunk/services/HelloService_v1.0/soa/HelloService_v1.0 in the previous build
no change for svn://hendriksh@u10023o/mmi/trunk/build since the previous build
[EnvInject] - Injecting environment variables from a build step.
[EnvInject] - Injecting as environment variables the properties file path 'Build/build-env-ONT.properties'
[EnvInject] - Variables injected successfully.
[EnvInject] - Injecting as environment variables the properties content 
soamds.apps.home=${workspace}\GedeeldeObjecten

[EnvInject] - Variables injected successfully.
Parsing POMs
Modules changed, recalculating dependency graph
[HelloService_v1.0] $ D:\ProgramFiles\Java\jdk1.7.0_71/bin/java -cp D:\tomcatfiles\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven31-agent-1.5.jar;D:\ProgramFiles\Apache\apache-maven-3.2.3\boot\plexus-classworlds-2.5.1.jar;D:\ProgramFiles\Apache\apache-maven-3.2.3/conf/logging jenkins.maven3.agent.Maven31Main D:\ProgramFiles\Apache\apache-maven-3.2.3 D:\ProgramFiles\Apache\Tomcat8.0\webapps\jenkins\WEB-INF\lib\remoting-2.48.jar D:\tomcatfiles\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven31-interceptor-1.5.jar D:\tomcatfiles\.jenkins\plugins\maven-plugin\WEB-INF\lib\maven3-interceptor-commons-1.5.jar 58351
<===[JENKINS REMOTING CAPACITY]===>���channel started
Executing Maven:  -B -f D:\tomcatfiles\.jenkins\jobs\SOA - Service\workspace\HelloService_v1.0\soa\HelloService_v1.0\pom.xml clean pre-integration-test -DoracleServerUrl=[MY-SERVER] -DoracleUsername=[MY-USER] -DoraclePassword=[MY-PASSWORD]
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building HelloService 1.0
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ HelloService ---
[INFO] 
[INFO] --- maven-resources-plugin:2.7:resources (default-resources) @ HelloService ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\tomcatfiles\.jenkins\jobs\SOA - Service\workspace\HelloService_v1.0\soa\HelloService_v1.0\src\main\resources
[INFO] 
[INFO] --- oracle-soa-plugin:12.1.3-0-0:compile (default-compile) @ HelloService ---
[INFO] ------------------------------------------------------------------------
[INFO] ORACLE SOA MAVEN PLUGIN - COMPILE
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] ABOUT TO RUN oracle.soa.scac.ValidateComposite...
[INFO] compile: Executing: [cmd:[D:\ProgramFiles\Java\jdk1.7.0_71\bin\java, -Djava.protocol.handler.pkgs=oracle.mds.net.protocol|oracle.fabric.common.classloaderurl.handler|oracle.fabric.common.uddiurl.handler, oracle.soa.scac.ValidateComposite, D:\tomcatfiles\.jenkins\jobs\SOA - Service\workspace\HelloService_v1.0\soa\HelloService_v1.0\SOA//composite.xml, -level=1, -appHome=../../../]]
[INFO] Process being executed, waiting for completion.
[INFO] [exec] 2015-02-18 20:23:35.950/4.421 Oracle Coherence 12.1.3.0.0 <Info> (thread=main, member=n/a): Loaded operational configuration from "jar:file:/D:/ProgramFiles/Apache/apache-maven-repository/com/oracle/coherence/coherence/12.1.3-0-0/coherence-12.1.3-0-0.jar!/tangosol-coherence.xml"
[INFO] [exec] 2015-02-18 20:23:36.091/4.562 Oracle Coherence 12.1.3.0.0 <Info> (thread=main, member=n/a): Loaded operational overrides from "jar:file:/D:/ProgramFiles/Apache/apache-maven-repository/com/oracle/coherence/coherence/12.1.3-0-0/coherence-12.1.3-0-0.jar!/tangosol-coherence-override-dev.xml"
[INFO] [exec] 2015-02-18 20:23:36.091/4.562 Oracle Coherence 12.1.3.0.0 <D5> (thread=main, member=n/a): Optional configuration override "/tangosol-coherence-override.xml" is not specified
[INFO] [exec] 2015-02-18 20:23:36.107/4.578 Oracle Coherence 12.1.3.0.0 <D5> (thread=main, member=n/a): Optional configuration override "cache-factory-config.xml" is not specified
[INFO] [exec] 2015-02-18 20:23:36.107/4.578 Oracle Coherence 12.1.3.0.0 <D5> (thread=main, member=n/a): Optional configuration override "cache-factory-builder-config.xml" is not specified
[INFO] [exec] 2015-02-18 20:23:36.107/4.578 Oracle Coherence 12.1.3.0.0 <D5> (thread=main, member=n/a): Optional configuration override "/custom-mbeans.xml" is not specified
[INFO] [exec] 
[INFO] [exec] Oracle Coherence Version 12.1.3.0.0 Build 52031
[INFO] [exec]  Grid Edition: Development mode
[INFO] [exec] Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
[INFO] [exec] 
[INFO] [exec] 2015-02-18 20:23:36.247/4.718 Oracle Coherence GE 12.1.3.0.0 <Info> (thread=main, member=n/a): Created cache factory com.tangosol.net.DefaultConfigurableCacheFactory
[INFO] [exec] Feb 18, 2015 8:23:37 PM oracle.fabric.common.wsdl.SchemaManager isIncrementalBuildSupported
[INFO] [exec] INFO: XMLSchema incremental build enabled.
[INFO] [exec] Mediators/HelloMediator.mplan: warning: Assigning property/constant "concat("Hallo ", $in.payload/tns:HelloRequest/tns:Naam)" to element "$out.payload/tns:HelloResponse/tns:begroeting". Please make sure target is single leaf node, otherwise non-leaf node will contain only string value which may generate non-valid xml as per the xsd.
[INFO] compile: [cmd:[D:\ProgramFiles\Java\jdk1.7.0_71\bin\java, -Djava.protocol.handler.pkgs=oracle.mds.net.protocol|oracle.fabric.common.classloaderurl.handler|oracle.fabric.common.uddiurl.handler, oracle.soa.scac.ValidateComposite, D:\tomcatfiles\.jenkins\jobs\SOA - Service\workspace\HelloService_v1.0\soa\HelloService_v1.0\SOA//composite.xml, -level=1, -appHome=../../../]] exit code=0
[INFO] SOA COMPILE DONE
[INFO] 
[INFO] --- maven-resources-plugin:2.7:testResources (default-testResources) @ HelloService ---
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory D:\tomcatfiles\.jenkins\jobs\SOA - Service\workspace\HelloService_v1.0\soa\HelloService_v1.0\src\test\resources
[INFO] 
[INFO] --- maven-compiler-plugin:3.2:testCompile (default-testCompile) @ HelloService ---
[INFO] No sources to compile
[INFO] 
[INFO] --- maven-surefire-plugin:2.18.1:test (default-test) @ HelloService ---
[INFO] No tests to run.
[JENKINS] Recording test results
[INFO] 
[INFO] --- oracle-soa-plugin:12.1.3-0-0:sar (default-sar) @ HelloService ---
[INFO] Building sar: D:\tomcatfiles\.jenkins\jobs\SOA - Service\workspace\HelloService_v1.0\soa\HelloService_v1.0\target\sca_HelloService_rev1.0.jar
[INFO] 
[INFO] --- oracle-soa-plugin:12.1.3-0-0:deploy (default-deploy) @ HelloService ---
[INFO] ------------------------------------------------------------------------
[INFO] ORACLE SOA MAVEN PLUGIN - DEPLOY COMPOSITE
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] setting user/password..., user=weblogic
Processing sar=D:\tomcatfiles\.jenkins\jobs\SOA - Service\workspace\HelloService_v1.0\soa\HelloService_v1.0/target/sca_HelloService_rev1.0.jar
Adding sar file - D:\tomcatfiles\.jenkins\jobs\SOA - Service\workspace\HelloService_v1.0\soa\HelloService_v1.0\target\sca_HelloService_rev1.0.jar
INFO: Creating HTTP connection to host:[MY-SERVER], port:[MY-PORT]
INFO: Received HTTP response from the server, response code=200
---->Deploying composite success.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 21.328 s
[INFO] Finished at: 2015-02-18T20:23:41+01:00
[INFO] Final Memory: 27M/356M
[INFO] ------------------------------------------------------------------------
Waiting for Jenkins to finish collecting data
[JENKINS] Archiving D:\tomcatfiles\.jenkins\jobs\SOA - Service\workspace\HelloService_v1.0\soa\HelloService_v1.0\pom.xml to VGZ-SOA-Application/HelloService/1.0/HelloService-1.0.pom
[JENKINS] Archiving D:\tomcatfiles\.jenkins\jobs\SOA - Service\workspace\HelloService_v1.0\soa\HelloService_v1.0\target\sca_HelloService_rev1.0.jar to VGZ-SOA-Application/HelloService/1.0/HelloService-1.0.jar
channel stopped
Archiving artifacts
Finished: SUCCESS

Perfect! As a final we can make a job to run a unit test against the just deployed server. I already made a description of how to do this here.

Now for the multijob. This will be a Release-Service job which calls all of the above step in a specific order. In the end you can use the CopyArtifact plugin to copy all of the generated artifacts into the Release-Service job. You can then zip these. I’m using the promote plugin to authorize the upload of the zip into Nexus. So the job looks like this now:

Release-Service

The stars on the left side will tell you that these where builds which where promoted and ended up in Nexus. I’m using a windows batch command to upload the zip to Nexus like this:

mvn deploy:deploy-file -Durl=[MY-SERVER] -DrepositoryId=local-nexus -DgroupId=nl.cvgz.mmi.services -DartifactId=%servicenaamkort% -Dversion=%serviceversie% -Dpackaging=zip -Dfile=target/%servicenaam%.zip

And finally they will end up in Nexus then. A zip which will contain:

  • OSB/SharedObject.sbar
  • OSB/Service.sbar
  • OSB/Customizations. Directory with customizations files for DTAP
  • SOA/MDS.zip
  • SOA/Service.jar

Nexus

So this could possibly be a way to automatically build, deploy, test, package and release a whole service using Jenkins. Some issues which I haven’t solved yet:

  • It seems adding a customization file during the deploy of the SB component gives an error. Could be a bug though.
  • Deploying the MDS.zip to the soa server through maven. If you know how to do this….drop me a line please

OFM 12C from the trenches: Business flow instance name bug and solution

A new feature in OFM 12C is that you can track Business flow instances. I won’t go into the details as you can read all about it here. As this is a nice feature I was going to use this to set a good Flow instance name as descripted here in chapter 47.5.4 How to Set the Business Flow Instance Name or Composite Instance Name at Design Time. I created a simple service and added an assign in my mediator component as written in the documentation.

<assign>
   <copy
      target="$out.property.tracking.setFlowInstanceTitle"
      expression="oraext:setFlowInstanceTitle("Test")"
      xmlns:med="http://schemas.oracle.com/mediator/xpath"/>
</assign>

As I added it, I noticed that the namespace declared here for the setFlowInstanceTitle wasn’t declared. I thought I would have have been declared somewhere else so I just tried it. As I compiled and deployed my service and ran the test I got the following error though:

ORAMED-01001:[Error in assign operation]Error occurred while assigning to target "$out.property.tracking.setFlowInstanceTitle" using expression "oraext:setFlowInstanceTitle('Test')".Possible Fix:Check if source message has right values or source expression is valid. Cause:Extension function error: Method not found 'setFlowInstanceTitle' 

After some digging around and a chat with Oracle support it seems that

a) You have to add the namespace. It seems they forgot it in the online documentation. So the assign should look like this:

<copy
target="$out.property.tracking.setFlowInstanceTitle"
expression="oraext:setFlowInstanceTitle('Test')" xmlns:oraext="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.ExtFunc"
xmlns:med="http://schemas.oracle.com/mediator/xpath"/> 

b) You have to apply patch 18310693 to the server. This means downloading it, unzipping and running the patch.

C:\Oracle_patch\18310693>c:\Oracle\Middleware\Oracle_Home\OPatch\opatch apply
Oracle Interim Patch Installer version 13.2.0.0.0
Copyright (c) 2014, Oracle Corporation.  All rights reserved.


Oracle Home       : C:\Oracle\Middleware\Oracle_Home
Central Inventory : C:\Program Files\Oracle\Inventory
   from           : n/a
OPatch version    : 13.2.0.0.0
OUI version       : 13.2.0.0.0
Log file location : C:\Oracle\Middleware\Oracle_Home\cfgtoollogs\opatch\18310693_Jan_18_2015_16_25_03\apply2015-01-18_16-24-53PM_1.log


OPatch detects the Middleware Home as "C:\Oracle\Middleware\Oracle_Home"

Jan 18, 2015 4:25:03 PM oracle.sysman.oii.oiii.OiiiInstallAreaControl initAreaControl
INFO: Install area Control created with access level  0
Applying interim patch '18310693' to OH 'C:\Oracle\Middleware\Oracle_Home'
Verifying environment and performing prerequisite checks...
All checks passed.

Please shutdown Oracle instances running out of this ORACLE_HOME on the local system.
(Oracle Home = 'C:\Oracle\Middleware\Oracle_Home')


Is the local system ready for patching? [y|n]
y
User Responded with: Y
Backing up files...

Patching component oracle.integration.soainfra, 12.1.3.0.0...

Patching component oracle.integration.soainfra, 12.1.3.0.0...

Patching component oracle.soacommon.plugins, 12.1.3.0.0...

Patching component oracle.soacommon.plugins, 12.1.3.0.0...

Verifying the update...
Patch 18310693 successfully applied
Log file location: C:\Oracle\Middleware\Oracle_Home\cfgtoollogs\opatch\18310693_Jan_18_2015_16_25_03\apply2015-01-18_16-24-53PM_1.log

OPatch succeeded.

After this….start your server again and try your composite again. The result should be:

FlowInstanceTitle