Monday, March 31, 2008

ESB read-only Console

I know this functionality is supported out of the box, but there are some special touches added by me, and thought to share with everybody.

To create ESB read-only user account:

- Create user in EM with ascontrol_monitor, and that's all is required for creating read-only account for ESB read-only.

Now if I login to ESB console using esbreadonly user, everything works fine. There are some gotchas here:

- You can delete any service using esbreadonly user!

- Sometime you want to enhance functionality, e.g. not all readonly user should have access to routing rules, etc...

I published the article for BPEL Read-only Console , it was fairly easy because BPEL read-only console are all JSP and I used Servlet filter to achieve that functionality. Now ESB console is all Java Script underneath. From directory names I can see it is Picasa framework, not sure how that works, but debugging JS is hell lot of time unless you have good editor.

Disable Delete button for Readonly Users:

The best way to debug Javascript is just to use wingrep and find the pattern which you are looking for. For disabling DELETE button, here is the trick:

- open %soasuite%/j2ee/oc4j_soa/applications/esb-dt/esb_console/esb/commands/controller.ServiceNavigator.js

- Search for following two entry (it should be about 399 or 400 line in the file:

var a=ActionController[gActionDeleteService];
a.enable();

- Add following line of code below the a.enable(); line:

/* cshah changes : added code to disable delete button */
if(!isAdminUser()) {
a.disable();
}

That's all and DELETE button will be disabled for non-admin users.

Enhance functionality for ESB console, disable tabs e.g. Routing Rules

- open %soasuite%/j2ee/oc4j_soa/applications/esb-dt/esb_console/esb/commands/controller.ESBController.js

- Search for following two entry (it should be about 614 and 615 line in the file:

tabmodel.enableTab(TabModel.TAB_RTNGRULES_IDX);
tabmodel.enableTab(TabModel.TAB_TACKINGFLDS_IDX);

- Add the following line of code right below tabmodel.enableTab(TabModel.TAB_TACKINGFLDS_IDX);

/* cshah -- disable routing rules if the user is not admin */
if(!isAdminUser()) {
tabmodel.hideTab(TabModel.TAB_RTNGRULES_IDX);
}

This will remove Routing Rules tabs for read-only (non-admin) users.

Thursday, January 10, 2008

OWSM Offline Agents

Per architecture OWSM Agents intercepts the requerst, calls the policy manager to retrieve the policy and then executes those policy where agent is installed. It introduces lot of traffic on policy manager. Policies are stored in database and policy manager is single point of contant for them.

Although we can break this dependency by offline agent installation, we can export all the policy from database as an XML file and provide that XML file to OWSM agent during the time of installation. In this case, owsm agents will look into the file, and wouldn't contact policy manager. We can update this file and policies at run time without bouncing the server.

Here are steps I followed:

Step 1: Create a client agent using OWSM ccore User Interface and defined the policies as I would for any other client agent.

Step 2: I expored those policies to an XML file using "save" button:

Step 3: Now it is time to install this agent with policy file already exported. Client agent installation is explained pretty well in http://www.oracle.com/technology/obe/fusion_middleware/owsm/index.html , but here I will just provide required informaiton to make offline.

I provided following agent.properties and then used "wsmadmin installAgent" to install the client agent.

agent.componentType=OC4JClientInterceptor
agent.containerType=OC4J
agent.containerVersion=10.1.3
client.home=d:/soasuite/j2ee/oc4j_soa
agent.component.id=C0003007
agent.policymanager.enabled=false
agent.policySet.file=D:/temp/owsm/OfflineAgentPolicySet.xml

Here I had to provide the policy file and disable the policy manger.

Step 4: Final testing: After this, I just create two BPEL process Calle and Caller to test my client agent, and it worked simply great. Upon changing the file name my client agent didn't work and upon updating the file client agent picked up new changes. It worked..

You can download agent.properties, policy file and test code from here.

OWSM Client Agents

It took me a while to configure all client agents, here is some information I would like to share. OWSM supports 3 types of client agents (http://download.oracle.com/docs/cd/E10291_01/doc.1013/e10298.pdf page 6-6):

- J2EE Client Agents: Configured when Servlet/EJB makes call to WebService and web service clients are maintained by Container

- J2SE Client Agent: Configured when Stand-Alone Java is making call to WebService.

- WSIF Client Agent: To leverage the WSIF framework used by ESB and BPEL. Configured when ESB/BPEL making outbound call to webservice.

Client agent intercepts the outbound requests and executes the policies defined by policy manager.

WSIF Client Agent: It is very well explained at Oracle OBE: http://www.oracle.com/technology/obe/fusion_middleware/owsm/index.html

J2SE Client Agent: Here are the steps I followed to create J2SE client agent.

Step 1: I created BPEL webservice called HelloBPELAgentTestingCalle. Deployed that process to BPEL PM and secured it using Server Agent which requires WSSE authentication information.

Step 2: I copy the WSDL link and created J2EE webservice proxy from JDeveloper.

It creates pretty much all code required to invoke the webservice, although I had to add couple of lines of code to test the way I wanted:

I tried to create fake security token from wizard (and also per documentation), I created HelloBPELAgentTestingCalleBinding_Stub.xml and put that file in src and also under src/../proxy/runtime directory. The content of this file is very well explained in WSIF client agent.

Now after putting all libraries in classpath as mentioned in document: client.home/owsm/lib/extlib, ORACLE_HOME/owsm/lib/cfluent-log4j.jar, JDBC jar file, ORACLE_HOME/jlib/orai18n.jar, ORACLE_HOME/jlib/ojmisc.jar

Now if I execute the client using JDeveloper, I can see that it is executing the client agent before it goes to real service.

J2EE client agent:

I tried to create J2EE client by creating Web Service proxy mentioned earlier and then wrapping it up in servlet or JSF page.

I found out that if I have to follow http://download.oracle.com/docs/cd/B31017_01/web.1013/b28974/j2eewsclient.htm to create webservice client and then follow the document http://download.oracle.com/docs/cd/E10291_01/doc.1013/e10298.pdf for configuring my war or jar file. I believe that's too much work and per my personal experience I would avoid recommeding such complicated way to client.

I went for little easy solution, although I my client agent will not be managed by container, but I can get same functionality served. I used my J2SE client which _stub.xml file and all other good stuff. I created Servlet wrapper around it and deployed to application server, things works just fine....

In a nutshell, you can use J2SE client approach and still deploy to container. It will serve the the purpose but won't be managed by container.

You can download the code here for WSIF, J2SE and J2EE client agent over here.

Wednesday, January 9, 2008

OWSM Field Level Encryption

I had chance to work on OWSM agents and different type of encryption. Here I would like to present the solution for OWSM field level encryption. I already had encryption/decryptioin example working for full payload, so here I will just provide tricks on how to configure OWSM for field level encryption.

It is basically doing XPATH encryptiong, as described in http://download.oracle.com/docs/cd/E10291_01/doc.1013/e10299/policy_steps.htm#sthref612.

Step 1.

I created a BPEL process called DemoOWSMFieldLevelEncryption which pretty much returns the input string. Here is how it looks like:

I have input payload with SSN number in it, which I am interested in encrypting:

Please note down the namespace, it is used when we encrypt the message.
Step 2:

Just for testing purpose I registered that service in OWSM gateway, and start creating policies for the service as shown below:

If we look at the XML encrypt in more detail :

Here I am using existing utility to create JKS files. Interesting thing to note down is:

Encrypted Content: XPATH

Encrypt XPATH: /soap:Envelope/soap:Body/ns1:DemoFieldLevelEncryptionProcessRequest/ns1:SSN
Encrypt namespaces: soap=http://schemas.xmlsoap.org/soap/envelope/,ns1=http://xmlns.oracle.com/DemoFieldLevelEncryption

As you can see, I am using soap and ns1 namespaces in my XPATH, so I have to define them in namespaces section as comma seperated values.

If we look into XML decrypt, it remains pretty much the same. XML encrypt of body/header/envelope or xpath doesn't change XML decrption part.

I created LOG before and after each policy step as part of best practices.

Step 3:

Now time for testing. I used OWSM test page to test my registered service and used Execution Logs to check if messages are getting encrypted and then decrypted back to the original content. Here is what I saw:

First log (SSN is encrypted)

Second Log: SSN is decrypted back to the original value

It seems like it is encrypting and decrypting field level variables. Source code can be downloaded at here.

Monday, December 31, 2007

BPEL Client API

I had chance to work on both BPEL and ESB client APIs, and I found very little documentation on BPEL Client API, that made me write this BLOG entry.

BPEL Client API:

Everything we can do in BPELConsole, we can do through BPEL client API as well. BPEL client API is JAR file shipped with SOASuite, I imporeted that JAR file and I could manage my BPEL domain using stand alone Java program which calls this client APIs. Here is the usecase we had to implement: Activating and Deactivating a BPEL process using stand-alone Java program or Servlet.

Here is what I started with:

Here we can see the establishConnection, which takes oc4j server name, port, username and port to connect with BPEL server. I have couple of test service to list all domains, list all services in a domain. I have high-lighted startService and endService which has logic for activating and deactivating the service.

I had to include all libraries from, bpel/lib, opmn/lib and j2ee/home/lib. Once I included these libraries, I was able to run this Java program and activate/deactivate the process successfully.

BPEL Client API source code can be downloaded from here.

ESB Client API:

I found ESB Client API are extreamly well explained and documented, so I avoided repeating that information.

Oracle BPEL Header Interceptor

I saw that BPEL interceptor has been only documented as header handler, I found it can do much more than just handling Headers. It is perfect interceptor and works just like Servlet Filter. It is sensitive part of code, because interceptor is called synchronously from main BPEL process. Any uncatched exception or time consuming delays in interceptor code will be propagated to main BPEL process.

OK, let's look at how to implement it:

We can register two different interceptor, one for request and one for response. I pretty much copied the initial part from documentation and enhance it for 10.1.3.x SOASuite. I created CustomHeaderHandler which implements HeaderHandler, and then I created two different classes InboundHandler and OutboundHandler which extends CustomHeaderHandler.

CustomHeaderHandler:

Here we can see invoke operation with Parternlink, Header, CallProperties. I have also written dumpProperties method which will dump all the properties from Map.

Here is InBound and OutBound interceptor which merely just calls CustomHedaerHandler's invoke method:

InboundHandler

OutboundHandler

I compiled all three classes and put it in bpel/system/classes directory and restarted SOASuite. I created couple of BPEL Processes to test my interceptors, I put following lines of code in bpel.xml to activate the interceptors:
Now if I look into soasuite/opmn/log/default_group~oc4j_soa~default_group~1.log, I can see the intercepted log:
Source code can be downloaded at here.

Thursday, December 27, 2007

It is all about JMX

It is all about JMX

I worked on JMX stuff on OC4J lately, and found information are scattered at many places. Thought of writing blog to combine information which might be useful.

- Simple MBean registered in Stand-Alone JVM, and monitered using JConsole

- Simple MBean registration to stand-alone OC4J, Stand-Alone OC4J MBean Browser, Stand-Alone OC4J MBean Client

- Simple MBean registration to cluster OC4J, OC4J Cluster MBean Browser, Cluster OC4J MBean Client

- Monitor OC4J MBeans using JConsole

1. Stand-Alone JVM

As per MBean spec, we need to define interface which is suffixed by MBean. I created interface called HelloServiceMBean and implemented called HelloService.

Here getMessage and setMessage will expose my message as an attribute to the MBean and printMessage will be exposed as an operation to MBean. To register this MBean in stand-alone JVM, I wrote another class which register this MBean in JVM and I could manage it using JConsole MBean Browser.
I compiled those classes using JDeveloper and executed through following command line:

cd D:projectsJMXSamplesSampleJMXclasses

java -Dcom.sun.management.jmxremote jmx.trial.SimpleAgent

On second window, I started JConsole using: %JAVA_HOME%jdkbinJConsole, and I can see my MBean with Attributes and Operations. I can invoke any operation but I am not able to change any attribute using JConsole. Not sure why I am not able to change any attribute value using JConsole, it works just fine with OC4J MBean Browser.

2. MBean with Stand-Alone OC4J

There are two options we can try, Registering JAR (static registration) file to OC4J using deployment descriptor, and registering MBean from servlet (dyanmic registration). For current Blog entry, I will use deploying through descriptor.

I used the same project which I used for Stand-Alone JVM. I created 3 artifacts in my JDeveloper project:

- Created EJB-JAR deployment profile for jar file called: helloservicejar.deploy

- Created EAR deployment profile: helloservice.deploy (had dependency on helloservicejar.deploy)

- Created OC4J deployment descriptor called - orien-application.xml

I deployed this ear file in stand-alone OC4J, I can see my application and MBean Browser right in EM console. (We can also register this Jar file in j2ee/config/application.xml file then we don't need to have orien-application.xml and ear file.)

Here I can change attribute values and invoke operation without any issues. I used java client to test MBeans deployed on OC4J.

Here getMBeanConnection method is pretty generic, it will get us connection based on the URL specified. printAllMBeans will iterate through all available MBeans and prints all MBeans. The testStandAlone() method does, invocation of method, get attribute and set attribute.

I had to put following libraries in my classpath in order to execute my client:

J2EE
j2eehomelibjmx_remote_api.jar
j2eehomelibjmxcluster.jar
j2eehomelibjmxri.jar
j2eehomelibadminclient.jar
j2eehomeoc4jclient.jar
opmnlib all six jar files.

3. MBean with Cluster OC4J

Registration as JAR: Registration through JAR in Cluster is pretty much similar as registering in Stand-Alone. I use JDeveloper to deploy my EAR file in Cluster Group. I created a group called default_group and registered all my OC4J instances in that group.

Dynamic Registration: Through servlet or POJO residing in container, I could register only to specific container. It looks like, all instances has to do the same to achieve cluster level MBeans deployment.

For testing purpose, I manually deployed a JAR on OC4J group. Here is little introduction about Cluster MBean:

Cluster MBean is actually a proxy to the OC4J group. Client (Java/Browser) can get hold on Cluster MBean, and pass the specific MBean and it's method/attribute as paraemter. Cluster MBean takes care of invoking those method across cluster. Cluster MBean knows about all OC4J instances through OC4J group configured in EM. For each OC4J group there will be one Cluster MBean proxy.

OC4J Cluster MBean Browser: following are the screen shots which explains how did I use cluster MBean browser for getAttribute, I can use it for setAttribute or invoke operation exactly the same way.

Upon invoking the operation I get following return values.

Now to test through Java code, it is pretty much the same concept:

We can see that I got access to Cluster MBean which is "ias:j2eeType=J2EEServerGroup,name=default_group', and after that I am just invoking method of that proxy same as MBean browser. Here tricky part is method signatures, OC4J MBean browser is able to know all those signature through reflection but in my code I had to provide those signature before hand.

4. Monitor OC4J MBeans using JConsole

Basically by adding few libraries to JConsole, you can use it to browse OC4J MBeans. Here is the thing I used to start my JConsole:

set ORACLE_HOME=d:soasuite

jconsole -J-Dcom.sun.management.jmxremote.ssl=false -J-Dcom.sun.management.jmxremote.authenticate=true -J-Djmx.remote.protocol.provider.pkgs=oracle.oc4j.admin.jmx.remote -J-Djava.class.path=;%JAVA_HOME%libjconsole.jar;%JAVA_HOME%libtools.jar;%ORACLE_HOME%j2eehomelibadminclient.jar;%ORACLE_HOME%j2eehomeoc4jclient.jar;%ORACLE_HOME%j2eehomelibjavax77.jar

Upon the window, I added the same URLs which I used in my Java program, I can use any of the following URLs:

STAND_ALONE_OC4J_URL (service:jmx:rmi://localhost:23791/oc4j)
SOASUITE_HOME_URL (service:jmx:rmi:///opmn://mycomputer:6003/home)
SOASUITE_OC4J_SOA_URL (service:jmx:rmi:///opmn://mycomputer:6003/oc4j_soa)
SOASUITE_CLUSTER_URL (service:jmx:rmi:///opmn://localhost:6003/cluster)

And it works great except one weird exception on DOS prompt.

Source code for all can be downloaded over here.