Sunday, 10 November 2013

Oracle Service Bus : Using the Management Java API

Oracle Service Bus 11g
Using the Management Java API


In this post I will share some example Java code which uses the Oracle Service Bus Java API to manipulate OSB resources that have been deployed to a WebLogic Oracle Service Bus domain.

The initial reason I wanted to use the API was to fix some corruption in the OSB resource repository. The benefit of using the API in this situation is that allows you to access resources that the OSB console may not let you see or manipulate.

The full Java API doc for the API can be found in the Oracle Fusion Middleware documentation under the title “Oracle Fusion Middleware Java API Reference for Oracle Service Bus”. The direct URL for the Java API doc current version (11.1.1.7) is: http://docs.oracle.com/cd/E28280_01/apirefs.1111/e15033/toc.htm

I will only be showing a very small example of the functionality provided by the API. I encourage you to take a look at the API doc to get an idea of the full range of functionality it provides. The API allows you to do pretty much anything that could be done via the OSB console.

The trickiest part of using the API is determining what additional JAR libraries are required to use the API. This is not well documented and required a bit of investigation and trial and error by me. This is the resulting list of JAR libraries I came up with:

  • alsb.jar from /<middleware_home>/Oracle_OSB1/lib
  • com.bea.common.configfwk_1.7.0.0.jar from /<middleware_home>/Oracle_OSB1/modules
  • com.bea.core.management.jmx_1.4.2.0.jar from /<middleware_home>/modules
  • sb-kernel-api.jar from /<middleware_home>/Oracle_OSB1/lib
  • sb-kernel-impl.jar from /<middleware_home>/Oracle_OSB1/lib
  • wlfullclient.jar
These libraries are from an install of OSB 11.1.1.7. The version numbers of the libraries may change with other versions of OSB.

The wlfullclient.jar library is not provided by default in a WebLogic install and must be explicitly built by you from an existing WebLogic domain. It's easy to build and there are many posts on the internet describing how to build it. The basic steps are:
  1. cd /<middleware_home>/wlserver_10.3/server/lib
  2. java -jar wljarbulder.jar

I used Eclipse to build the code shown in this blog post, however you should be able to use any other Java IDE to achieve the same result.

There are five main steps to using the API:
  1. Establish a connection to the WebLogic JMX Management Bean running in a WebLogic instance.
  2. Create a new OSB change management session.
  3. Use the API to manipulate OSB resources.
  4. Commit the OSB change management session to save any changes we made.
  5. Close the JMX connection.

Here is the method that establishes the JMX connection:

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);
}

Here is the code that creates the OSB change management session:

// Connect to WebLogic JMX
conn = initConnection(host, port, username, password);

// Create the OSB change management session
MBeanServerConnection mbconn = conn.getMBeanServerConnection();
DomainRuntimeServiceMBean domainService = (DomainRuntimeServiceMBean) MBeanServerInvocationHandler
.newProxyInstance(mbconn, new ObjectName(
DomainRuntimeServiceMBean.OBJECT_NAME));
sm = (SessionManagementMBean) domainService.findService(
SessionManagementMBean.NAME, SessionManagementMBean.TYPE,
null);
sm.createSession(sessionName);

After creating the session we need to get a reference to one of the MBeans that are provided for OSB depending on what we want to do. To create and delete resources we can use the ALSBConfigurationMBean as below:

ALSBConfigurationMBean alsbSession = (ALSBConfigurationMBean) domainService
.findService(ALSBConfigurationMBean.NAME + "."
+ "mysession", ALSBConfigurationMBean.TYPE, null);

Some other MBean types that are also available are:
  • CommonServiceConfigurationMBean
  • BusinessServiceConfigurationMBean
  • ProxyServiceConfigurationMBean
  • ServiceDomainMBean
When specifying the resources that you want to manipulate, the API uses a “Ref” object. To create a Ref object you must specify the resource type and name. For example, if I wanted to create a Ref object to represent a Proxy Service named “GetAccountBalancePS” under the Project path “CoreBanking/AccountServices” I would use the following code:

// Construct Ref object
Ref ref = constructRef(“ProxyService”, “CoreBanking/AccountServices/GetAccountBalancePS”);

For a Business Service we would use “BusinessService” as the first parameter above.
For Projects or Folders we should use the predefined values Ref.PROJECT_REF and Ref.FOLDER_REF. For example:

// Construct Ref object
Ref ref = constructRef(Ref.PROJECT_REF, “CoreBanking”);

// Construct Ref object
Ref ref = constructRef(Ref.FOLDER_REF, “CoreBanking/AccountServices”);

After we have manipulated the resources we activate or discard the change session:

sm.activateSession(sessionName, statusmsg);

sm.discardSession(sessionName);

If we activate the session we can provide a comment just like we would do if we used the OSB console.

I have provided the full code for two example scenarios below:
  1. Enable/Disable a Business Service or Proxy Service.
  2. Delete a Project or Folder.
I hope you find these example useful.

Enable/Disable Business or Proxy Service

/**
 *
 */
package osbservicestatusupdate;
import com.bea.wli.config.Ref;
import com.bea.wli.sb.management.configuration.*;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Hashtable;
import javax.management.*;
import javax.management.remote.*;
import javax.naming.Context;
import weblogic.management.jmx.MBeanServerInvocationHandler;
import weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean;
public class OSBServiceStatusUpdate {
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);
}
private static Ref constructRef(String refType, String serviceuri) {
Ref ref = null;
String[] uriData = serviceuri.split("/");
ref = new Ref(refType, uriData);
return ref;
}
public static String changeProxyServiceStatus(String servicetype,
boolean status, String serviceURI, String host, int port,
String username, String password) {
JMXConnector conn = null;
SessionManagementMBean sm = null;
String sessionName = "mysession";
String statusmsg = "";
try {
conn = initConnection(host, port, username, password);
MBeanServerConnection mbconn = conn.getMBeanServerConnection();
DomainRuntimeServiceMBean domainService = (DomainRuntimeServiceMBean) MBeanServerInvocationHandler
.newProxyInstance(mbconn, new ObjectName(
DomainRuntimeServiceMBean.OBJECT_NAME));
sm = (SessionManagementMBean) domainService.findService(
SessionManagementMBean.NAME, SessionManagementMBean.TYPE,
null);
sm.createSession(sessionName);
ALSBConfigurationMBean alsbSession = (ALSBConfigurationMBean) domainService
.findService(ALSBConfigurationMBean.NAME + "."
+ "mysession", ALSBConfigurationMBean.TYPE, null);
if (servicetype.equals("ProxyService")) {
Ref ref = constructRef("ProxyService", serviceURI);
ProxyServiceConfigurationMBean proxyConfigMBean = (ProxyServiceConfigurationMBean) domainService
.findService(ProxyServiceConfigurationMBean.NAME + "."
+ sessionName,
ProxyServiceConfigurationMBean.TYPE, null);
if (status) {
proxyConfigMBean.enableService(ref);
statusmsg = "Enabled the Service : " + serviceURI;
} else {
proxyConfigMBean.disableService(ref);
statusmsg = "Disabled the Service : " + serviceURI;
}
} else if (servicetype.equals("BusinessService")) {
Ref ref = constructRef("BusinessService", serviceURI);
BusinessServiceConfigurationMBean businessConfigMBean = (BusinessServiceConfigurationMBean) domainService
.findService(BusinessServiceConfigurationMBean.NAME
+ "." + sessionName,
BusinessServiceConfigurationMBean.TYPE, null);
if (status) {
businessConfigMBean.enableService(ref);
statusmsg = "Enabled the Service : " + serviceURI;
} else {
businessConfigMBean.disableService(ref);
statusmsg = "Disabled the Service : " + serviceURI;
}
}
sm.activateSession(sessionName, statusmsg);
conn.close();
} catch (Exception ex) {
if (null != sm) {
try {
sm.discardSession(sessionName);
} catch (Exception e) {
System.out.println("able to discard the session");
}
}
statusmsg = "Not able to perform the operation";
ex.printStackTrace();
} finally {
if (null != conn)
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return statusmsg;
}
public static void main(String[] args) {
// changeProxyServiceStatus(servicetype, status, serviceURI, host, port,
// username, password)
System.out.println(changeProxyServiceStatus("ProxyService", true,
"CoreBanking/AccountServices/GetAccountBalancePS", "localhost", 7001,
"weblogic", "welcome1"));
}
}

Delete a Project or Folder

/**
 * 
 */
package osbservicestatusupdate;

import com.bea.wli.config.Ref;
import com.bea.wli.sb.management.configuration.*;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Collection;
import javax.management.*;
import javax.management.remote.*;

import javax.naming.Context;
import weblogic.management.jmx.MBeanServerInvocationHandler;
import weblogic.management.mbeanservers.domainruntime.DomainRuntimeServiceMBean;

public class OSBResourceDelete {
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);
}

private static Ref constructRef(String refType, String serviceuri) {
Ref ref = null;
String[] uriData = serviceuri.split("/");
ref = new Ref(refType, uriData);
return ref;
}

public static String deleteResource(String servicetype,
String serviceURI, String host, int port,
String username, String password) {
JMXConnector conn = null;
SessionManagementMBean sm = null;
String sessionName = "mysession";
String statusmsg = "";
try {
conn = initConnection(host, port, username, password);
MBeanServerConnection mbconn = conn.getMBeanServerConnection();
DomainRuntimeServiceMBean domainService = (DomainRuntimeServiceMBean) MBeanServerInvocationHandler
.newProxyInstance(mbconn, new ObjectName(
DomainRuntimeServiceMBean.OBJECT_NAME));
sm = (SessionManagementMBean) domainService.findService(
SessionManagementMBean.NAME, SessionManagementMBean.TYPE,
null);
sm.createSession(sessionName);
ALSBConfigurationMBean alsbSession = (ALSBConfigurationMBean) domainService
.findService(ALSBConfigurationMBean.NAME + "."
+ "mysession", ALSBConfigurationMBean.TYPE, null);

// Construct Ref object
Ref ref = constructRef(servicetype, serviceURI);
// Check if resource exists
boolean resExists = false;
resExists = alsbSession.exists(ref);
System.out.println("Resource '" + serviceURI + "' " + (resExists ? "exists." : "does not exist."));
// Delete the resource
if (resExists) {
ArrayList<Ref> refs = new ArrayList<Ref>();
refs.add(ref);
System.out.println("Deleting " + servicetype + " " + serviceURI);
alsbSession.delete(refs);
sm.activateSession(sessionName, statusmsg);
} else {
sm.discardSession(sessionName);
}
conn.close();
} catch (Exception ex) {
if (null != sm) {
try {
sm.discardSession(sessionName);
} catch (Exception e) {
System.out.println("Not able to discard the session");

}
}
statusmsg = "Not able to perform the operation";
ex.printStackTrace();
} finally {
if (null != conn)
try {
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}

return statusmsg;
}

public static void main(String[] args) {
// changeProxyServiceStatus(servicetype, status, serviceURI, host, port,
// username, password)
System.out.println(deleteResource(Ref.PROJECT_REF,
"Test", "localhost", 7001,
"weblogic", "welcome1"));

}
}






Tuesday, 23 July 2013

Oracle API Gateway : Authenticating with REST parameters

Oracle API Gateway 11gR2
Authenticating with REST parameters


This example will show you how to build an Oracle API Gateway 11gR2 policy that performs authentication using credentials that are passed as REST parameters. The example REST request that we will be using is:


In the above REST request the credentials we wish to authenticate are passed in the 'username' and 'password' parameters. Our policy will extract the credentials from the REST request and check them against an authentication store. It will then return the result of the authentication in a JSON message. For this example we will use the OAG Local Authentication store, however the same policy will work with an LDAP authentication store just by specifying the appropriate authentication store in the Attribute Authentication filter.

Here is how our policy will look once completed.


Before continuing with this example, make sure the OAG Node Manager and Gateway Instance have been started.
  • Start the OAG Policy Studio and click on the Admin Node Manager link to start editing policies.
  • On the next screen click on the Gateway or Group and then click Edit Active Configuration.
  • Navigate to the Policy Library and click on Add Policy.
  • Enter a name and description for the policy.


  • Click on the Attributes folder in the design palette on the right and drag an 'Extract REST Request Attributes' filter onto the policy editor canvas.

  • Right-click on the filter and select 'Set as Start'.

  • Next add a 'Copy/Modify Attributes' filter to set the OAG authentication attributes: 'authentication.subject.id' and 'authentication.subject.password'. The 'Copy/Modify Attributes' filter is in the Authentication folder of the design palette.

Click the 'Add' button to add the following mappings:

'http.querystring.username' to 'authentication.subject.id'


'http.querystring.password' to 'authentication.subject.password'



  • Next add an 'Attribute Authentication' filter to perform the authentication. The 'Attribute Authentication' filter is in the Authentication folder of the design palette.

  • Next add two 'SET Message' filters from the Conversion folder of the design palette. We must provide the correct JSON response message for a successful and unsuccessful authentication.



  • At this point we can also link the actions together into a Success / Failure Path by clicking on the Success / Failure Path tools and clicking on the filters in the order we want them applied.
  • We need to add a Relative Path to the policy to define when it will be triggered. This is the URL path that the service will be available on. Click on the Add Relative Path tool at the bottom of the policy editor and enter the relative path you wish this policy to apply.
  • Now we need to deploy the policy. Click on the Deploy icon at the top right of the Policy Studio window to deploy the policy. Once successfully deployed the service will be available at http://localhost:8080/RESTParamsAuth.
An example request to this service looks like this:


An example response from this service looks like this:
{
    "LoginResponse": {
        "result": "OK"
    }
}
That's it! I hope this example provides a useful starting point for exploring authentication using the Oracle API Gateway.


Thursday, 6 September 2012

Installing Oracle Complex Event Processing 11g on Fedora 16

This is just a quick guide on how to install Oracle Complex Event Processing 11g on Fedora 16 64-bit. I will cover installation of OCEP itself (a breeze) and Eclipse 3.6.2 and the OCEP Eclipse plug-in. My first attempts at installing, while superficially successful, resulted in some stability problems with Eclipse. After a bit of fiddling around I finally figured out how to get a stable environment.

For 64-bit Linux you will need to download the following:
  • ofm_ocep_linux_11.1.1.6.0_64_disk1_1of1.zip (Oracle Complex Event Processing 11g for 64-bit Linux)
  • eclipse-java-helios-SR2-linux-gtk-x86_64.tar.gz (Eclipse Helios 3.6.2 SR2 for 64-bit Linux)
  • Any recent release of Sun JDK 1.6 for 64-bit Linux (I used JDK 1.6.0_27)

Installing Oracle Complex Event Processing 11g

After downloading the installer zip file, unzip it. The zip archive contains a single executable named ofm_ocep_linux_11.1.1.6.0_64_disk1_1of1.bin. Change the permissions of the file to be executable (chmod a+x) and then execute it to start the OCEP graphical installer:
./ofm_ocep_linux_11.1.1.6.0_64_disk1_1of1.bin
If you would prefer to install in text-mode, add the following option when starting the installer:
-mode=console
Proceed with the installation as per normal. It's a very simple install. Remember to select the Custom Install option if you would like the OCEP samples installed as well.

Installing Eclipse Helios 3.6.2

Follow the normal procedure for installing Eclipse - just unzip it where you want it installed.

After installing eclipse, edit the eclipse.ini file and add the following lines:
-vm
/opt/jdk1.6.0_27/bin/java
* Amend the above to reflect the location of where you installed the Sun JDK.

Adding this option into the eclipse.ini file was the key for me to get a stable Eclipse. Without this setting Eclipse was Segfaulting on me frequently - often on startup. (Note the segfaults occurred when I used the default OpenJDK Java installed in Fedora. Strangely enough this didn't seem to be an issue when using the same OpenJDK in a 32-bit Oracle Enterprise Linux VM.)

Start Eclipse and install the OCEP plugin by going into the Help - Install New Software menu option in eclipse. The OCEP Eclipse plugin is in the ocep_11.1/eclipse-update-site directory under where you installed OCEP.

That's all. With luck you now have a stable and functional installation of Oracle Complex Event Processing 11g.