Issue Soa Suite 12.1.3 Context of the same RID xxxxxx already present in this family

Lately in our production environment we saw that when some of our services where called in rapid succession, some of them failed. Under normal load we never had issues but under bigger load we saw the following error in our BPEL instances:

Failure in Oracle WSM Agent, category= security, function=agent.function.client, stage=fault due to RuntimeException.
java.lang.IllegalArgumentException: Context of the same RID, 0:1:4 already present in this family, f42da30f-5c89-49d9-a4fd-bd2b7e80644e-00154a3f.

Bug

It also seemed that those faults where creating stuck threads and after a while making our managed servers unstable and unreachable. After some digging around we found that there was a patch for it. See Sporadic error during invocation of a SOA composite, ‘Context of the same RID, xxxxxx already present in this family’ (Doc ID 2150992.1). It was released since june 2016 but it seems it was never put into a bundle patch somewhere. After applying the patch the errors where replaced by warnings:

Sep 13, 2017 11:48:22 AM CEST Warning oracle.dms.context BEA-000000 Duplicate RID detected. Multiple tasks are attempting to execute with the same exec-ctx identifier 9f31c77a-4bee-4f57-a970-9275a6577bcb-00030ae5,0:1:4. Will use the unrooted identifier 9f31c77a-4bee-4f57-a970-9275a6577bcb-00030ae5,1:32171 for this task.

and we had no more stuck threads and all our instances where running fine again.

Add client certificate for outgoing OSB call

Simple use case……you want to connect to a customer system over the internet. The customers system has an API but requires 2-way SSL. This means we have to send a client certificate along to make sure the SSL handshake can be completed. If your server has already a server certificate installed, it will send this one along by default but the customers system won’t accept it as it is different then what it trusts. In the next section, I will explain how to add a client certificate to an outgoing OSB call.

SSL

Let’s say I want to connect to my favourite climbing shop www.mountaingear.com as they have a nice backend api to take orders. The guys from mountaingear.com created a certificate for me to send along with the call.

First I am going to generate a keystore with a private key in it, to simulate the certificate which the third party gave to me.

keytool -genkey -keyalg RSA -alias climber -keystore keystore.jks -storepass password -validity 360 -keysize 2048

If I open the created JKS using keystore explorer I see a keypair we just created.

MyCertificate

Copy the jks to my OracleHome say ORACLE_HOME/keystores.

The next thing we have to do is to create an PrivateKeyInfrastructure Provider. Go to weblogic console and then:

  • Security Realms
  • myrealm
  • Providers
  • Credential Mapping
  • New –> Set your name here. Mine is MountainGearPKIProvider. Set the type to PKICredentialMapper. Click OK to finish.

PKIProvider

Restart the Admin server for the changes to take effect.

When the admin server has restarted we are going to configure the PrivateKeyInfrastructure Provider we just created. Go to weblogic console and then:

  • Security Realms
  • myrealm
  • Providers
  • Credential Mapping
  • MountainGearPKIProvider
  • Provider Specific –> KeystoreType = JKS, Keystore File Name = The location of your just created jks…mine is G:\Oracle\Middleware\OracleHome\keystore\MountainGear.jks, KeyStorePassphrase = password, Confirm KeyStorePassphrase = password. Click Save to finish
    • PKIProviderConfiguration

      Restart the Admin server again for the changes to take effect.

      After this, go to the SBConsole and start a new session. In a project, create a folder which will hold the ServiceKeyProvider. Mine will be in my Accounts project. Create a ServiceKeyProvider in this new folder and select using SSL Client Authentication the right certificate. Set the password, save it and activate it.

      ServiceKeyProvider

      The reason why we do this in the OSB console is that it cannot resolve the PKIProvider in JDeveloper. The only work around is to create it on the server and then export your project and import it into JDev. After you have done this, you can see your ServiceKeyProvider.

      The last step now is to make sure it is send along with a flow. The only thing we have to do, to accomplish this is to select the proxy service and go to the Security tab. Here you can select the Service Key Provider.

      ProxyService

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

SOA Suite 12C : Patch to fix the JDev business rule component performance

A while back I did a post about the business rule engine. See here. In the end of the post I added some considerations. One was the very annoying performance of the business rule component in JDev when using decision tables. If you were editing them, the memory usage started growing and after 5 minutes JDev would crash. Also editing large decision tables was very slow. The worst part back then was that the export and import to excel was also broken.

performance

A while back there was a fix for that but recently we found out that another JDev ADF patch major increases the usability of decision tables.

We applied the next 3 patches but the last one really did the job.

  • Performance Patch (23754944)
  • Bundle Patch 161018 (20163149)
  • JDev ADF Security Patch (23754311)

Don’t forget to start JDev with the -clean parameter once to get a fresh start.

So next time when you start pulling out your hairs when editing a large decision table…..think OPatch 23754311!

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

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.

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.