Tuesday, May 27, 2008

Can you create a domain with upper case name?

Realized that you can not create domain with upper case, and if you do then you have login in BPELConsole in very weird way. I saw the meta-link and this issue been around for more than a year. I looked into exploded version of BPELConsole, it took me couple of min to fix it, and here is my hack:

Either you can get modified JSP files from here and dump it to %soasuite%/j2ee/oc4j_soa/applications/orabpel/console, or follow the steps described here:

1. %soasuite%/j2ee/oc4j_soa/applications/orabpel/console/index.jsp

Search for lines, with IBPELDomainHandle ch = l.lookupDomain(), and comment it out 2 lines. It is about line number 15 or 16.

Now if you login to BPEL console, you can see the Domain Picker jsp file and I thought it will just work fine, but I had to modify domainPicker jsp file as well to get thing done.

2. %soasuite%j2ee/oc4j_soa/applications/orabpel/console/domainPicker.jsp

a) Search for string called “alreadyAuthed.add( aDomainId )”, it will be about line number 39, and add following line of code

b) Need to change Java Script at the end of page:

c) Finally Change the submit button, and that’s all.

No need to bounce the server to see the magic! It feels like hacking is my business and consulting is byproduct.

Rule Engine Tricks

While working with Oracle Business Rules I found some tricks:

1) Enable Logging

Provide following properties in decisionservice.desc file in your bpel process:

<properties>
<property name="watchRules">true</property>
<property name="watchActivations">true</property>
<property name="watchFacts">true</property>
<property name="watchCompilations">true</property>
</properties>
You have to provide this right in <ruleEngineProvider> and right after the <repository> tag. If you have worked with Rule Engine SDK, then you may realize that it is not really providing all debugging information which you can see via ruleSession.executeFunction("watchFacts"). Well, be happy with what it provides, it is good enough. If you want to look at more information then look at my article on Custom Decision Service.

2) Additional Libraries

If your BPEL process is having decision service and your Rule is calling external Java program, then you will need to include those Jar files in to your path. The directory would be: decisionservices\DecisionService\war\WEB-INF\lib under your BPEL root directory.

3) RuleSet invoking other RuleSets

Hmm, this was cool one. If you have ruleSet and inside that ruleSet you are calling another ruleSet via pushRuleSet functioin, it just works fine in RuleAuthor, but decision service interface doesn't let you execute it. It throws exception something like "Rule Set xyz is undefined". Well, again if you are familiar with how Rule SDK works, then you can guess why this is the case. Developer of decision service probably loading only one rule set and that is what causing the issue.

Resolution: Rule function is quite different, if you execute rule function and if rule function calls multiple RuleSet that just works fine. When I created my custom decision service, I did the same for both RuleSet and Rule Functions. Therefore, for out-of-the box rule decision service, we have to create function interface in order to interact with multiple rule-sets.

4) Deploying to home container

As shown in below diagram, if you specify oc4j_soa while deploying decision service, it just works fine. If you specify home during creating Jdeveloper connection while deploying Decision service it throws following exception. Therefore, we have to use oc4j_soa while making Jdeveloper AS/Integration server connection.

[deployDecisionServices]
[deployDecisionServices] 08/05/14 18:20:26 Notification ==>application : rules_default_TestBPEL1_1_0_DecisionService is in failed state

[deployDecisionServices]

[deployDecisionServices] Exception in thread "ConfigurableThreadImpl::" java.lang.NoClassDefFoundError: oracle/classloader/util/LocalizedText
[deployDecisionServices] at com.evermind.server.rmi.RMICall.EXCEPTION_ORIGINATES_FROM_THE_REMOTE_SERVER(RMICall.java:109)
[deployDecisionServices] at com.evermind.server.rmi.RMICall.throwRecordedException(RMICall.java:125)
[deployDecisionServices] at com.evermind.server.rmi.RMIClientConnection.obtainRemoteMethodResponse(RMIClientConnection.java:517)
[deployDecisionServices] at com.evermind.server.rmi.RMIClientConnection.invokeMethod(RMIClientConnection.java:461)
[deployDecisionServices] at com.evermind.server.rmi.RemoteInvocationHandler.invoke(RemoteInvocationHandler.java:63)
[deployDecisionServices] at com.evermind.server.rmi.RecoverableRemoteInvocationHandler.invoke(RecoverableRemoteInvocationHandler.java:28)
[deployDecisionServices] at com.evermind.server.ejb.StatefulSessionRemoteInvocationHandler.invoke(StatefulSessionRemoteInvocationHandler.java:31)
[deployDecisionServices] at __Proxy2.getEvents(Unknown Source)
[deployDecisionServices] at oracle.oc4j.admin.jmx.client.MBeanServerEjbRemoteSynchronizer.getEvents(MBeanServerEjbRemoteSynchronizer.java:530)
[deployDecisionServices] at oracle.oc4j.admin.jmx.client.CoreRemoteMBeanServer.getEvents(CoreRemoteMBeanServer.java:319)
[deployDecisionServices] at oracle.oc4j.admin.jmx.client.EventManager.run(EventManager.java:217)
[deployDecisionServices] at oracle.oc4j.admin.jmx.client.ThreadPool$ConfigurableThreadImpl.run(ThreadPool.java:303)

How to start Enterprise Manager

If you shutdown Enterprise Manager from Console or any other way here is the trick to start the Enterprise Manager:

soasuite/j2ee/home/config/default-web-site.xml
<application name="ascontrol" path="../../home/applications/ascontrol.ear" parent="system" start="true" />
<application name="javasso" path="../../home/applications/javasso.ear" parent="default" start="true" /> (not sure if it is required all the time)

soasuite/j2ee/home/config/server.xml
<web-app application="ascontrol" name="ascontrol" load-on-startup="true" root="/em" ohs-routing="true" />

Bounce the home container using following command

opmnctl restartproc process-type=home

Friday, May 23, 2008

Custom Decision Service

I am not very big fan of Decision Service which comes out of the box with Oracle BPEL. There are couple of issues I found

- It creates whole bunch JAXB classes in my bpel process, which are .java and .class files (I have to keep both of them, .class files are not generated during compilation of bpel process!)

- I can NOT change the created Decision Service, it is not like I can click on DB adapter and reconfigure it. It make my life extremely difficult when have to accommodate changes from client

- I can not call the service from ESB or other WS consumer, the decision service exposed takes millions of parameters which are not relevant to web service consumer (e.g. bpelInstanceId? why in the hell rule engine needs to know bpel instance id?)

- There is a decision service for each partner link! We have 20 BPEL processes making almost 30 different type of calls, that ends up in 30 decision services. That make my life impossible to manage.

- It is way too complicated to implement WSIF with the decision service.

I love the idea of BAM, where all Active Data cache operations are exposed as one service. I had very naive and romantic idea of implementing my custom decision service and talk to any type of rule set, rule function, do the connection pooling of rules via one web service interface. It can take any type of parameter and using Java reflection I can convert to right type and that's all I need. My client did buy this idea and I implemented very nice and generic Custom Decision Service.

1. Implemented POJO

- I implemented a small Java POJO service, which does takes configuration

e.g. RuleRepositoryType (webdav, files), File Repository Connection Information, WebDav Repository Connection Information, Whole bunch of debug flags which are supported by Rule Engine, Dictionary Name, Rule Function or Rule Set, Input types and output types.

2. Implemented EJB 3.0 and exposed as Web service via annotations

- Just created EJB 3.0 session facade on top of POJO so that it is container managed, I can easily expose as Web Service via Annotations, and for implementing Connection pool.

3. Implemented Connection Pooling in EJB

- I implemented custom connection pool of Rule Repository and Rule Dictionary. I initiate new Rule Session each time. I also noticed that pooling/caching Rule repository was not just good enough so I had to cache Rule Dictionary as well. Yeah, I implemented

4. WSIF Interface via annotations

- I just followed http://chintanblog.blogspot.com/2007/12/although-wsif-seems-to-be-hack-to-plug.html to create WSIF on top of my EJB 3.0 session facade.

5. Performance Matrix

Test case: Used WebDav repository, Rule Function interface which executes more than 10 rule sets and creates whole bunch of external connection. It usually takes about 2 seconds to complete the Rule Session itself. I used about 10 threads and loop of 50 with 1 second delay in each (so total number of instances will be 500).

Default Decision Service over SOAP: I created sample BPEL process and created decision service with decide activity (which comes with jaxb java and classes, jar, ear, war, and so on...). Here were the results:

Average execution time: 3.1 second

Number of failures: 15

Custom Decision Service over SOAP: To be fair I didn't use WSIF interface. Calling my custom decision service over soap protocol. It is just like normal partner link.

Average execution time: 3.5 second

Number of failures: 10

Notes:

- Reason behind slowness is because of I am doing more reflection which is a bit expensive.

- Because of EJB and container managed stuff, I am getting less number of failures.

- Out-of-box decision service caches the Rule Connection where the custom decision service manages the entire pool which is shared across the enterprise. I believe if I test with 20 different BPEL processes with different pattern of calls, I will be far ahead in comparison with default decision service.

I am more than willing to get your feedback on this. I am not sure if I did right thing, but I believe I reduced (rather completely eliminated) overhead for managing far complex default decision service.

Thursday, May 22, 2008

ESB Display Older Instances

I used to have my own interceptor logging all required thing into the database, so never had to look at ESB console.

Issue 1 :

Recently when I was working on ESB console I realized that it displays only a day old instances! While looking into the database I saw all instances where there.

Yeah, of course the ESB client API was causing the issues. As mentioned in my earlier blogs, to debug ESB Console related issues, the best things is to use obtunnel to intercept all your request and then simple wingrep/grep to search for what you interested in.

The reason behind day old instance was easy to find:

File Name: %soasuite%/j2ee/oc4j_soa/applications/esb-dt/esb_console/esb/model/model.InstancesSearch.js

Where: Search for key word "InstanceSearchModel.prototype.init" about the line number: 150 in 10.1.3.1

Content:

Original:

InstanceSearchModel.prototype.init = function(serviceConfigROTID)
{
this._trackingSC = new TrackingSearchCriterion(serviceConfigROTID);
this._serviceEntityInfo = null; // ESBEntityInfo
this._status = "Any";
this._flowID = "";
this._timePeriod = 1;
this._timeUnit = "days";
this._timeZoneString = InstanceSearchModel.getTimezoneString(new Date(), false);
}

Basically InstanceSearchModel creates Rest Webservice request to ESB server, and timePeriod is configurable parameter to this object. Based on my observation, other javascript which are using InstanceSearchModel object are not passing this parameter, so default parameter will be used which is 1 day. I changed the default to 20 days and it showed 20 days worth of instances...

Modified:

InstanceSearchModel.prototype.init = function(serviceConfigROTID)
{
this._trackingSC = new TrackingSearchCriterion(serviceConfigROTID);
this._serviceEntityInfo = null; // ESBEntityInfo
this._status = "Any";
this._flowID = "";
this._timePeriod = 20;
this._timeUnit = "days";
this._timeZoneString = InstanceSearchModel.getTimezoneString(new Date(), false);
}

Issue 2 :

ESB has limitation on returning only 100 results. It was an amanzing experience to rip off the entire oraesb.jar and go through the hierachy of java files,

soasuite/j2ee/oc4j_soa/applications/esb-dt/esb_console/WEB-INF/web.xml
oraesb/oracle/tip/esb/configuration/servlet/CommandServlet.jad
oraesb/oracle/tip/esb/configuration/servlet/command/GetInstancesCommand.jad (xmlInstanceManager.getInstances)
oraesb/oracle/tip/esb/console/XMLInstanceManager.jad
oraesb/oracle/tip/esb/console/XMLInstanceManagerImpl.jad
oracle/tip/esb/monitor/manager/ActivityMessageStore.jad
oraesb/oracle/tip/esb/monitor/manager/database/DBActivityMessageStore.jad (InstanceListXMLBuilder)
oraesb/oracle/tip/esb/monitor/manager/database/InstanceListXMLBuilder.jad
oraesb/oracle/tip/esb/monitor/manager/database/FilterParser.jad (String s = RepositoryFactory.getRepository("RUNTIME").getESBParameter("MaxInstanceCount"))

Bingo! Finally I found the last file which was reading the parameter from ESB parameter table, now it was piece of cake!

I added, insert into esb_parameter (PARAM_NAME, PARAM_VALUE) values ( 'MaxInstanceCount', '1000' ); in ORAESB schema, and bounced the server and it started working like magic!

Tuesday, May 13, 2008

MQ Adapter Anatomy

Recently I had chance to work with MQ Adapter, and it was pretty nice experience and I pretty much tried all different types of settings supported by MQAdapter. Here I would like to share something.

If you religiously follow the document: http://download.oracle.com/docs/cd/B32110_01/web.1013/b28956.pdf then there is not much value I will be adding, but still you might find something useful and accumulated information.

1) Different Settings

Now let's take a look at each parameter:
  • Scheme: Three types of scheme

    1. dynamic : use max connections, if all are in use, then give new one and don't worry about maxConnections limit

    2. fixed: use max connections, if all are in use, then throw exception for new request

    3. fixed_wait: use max connections, if all are in use, then do fixed amount of wait for newly requested connection

    • Best practice is to use fixed_wait with higher timeout so that we can restrict the number of connection

  • minConnections/maxConnections/initial-capacity: Decided number of connections and initial connections during start up.

  • waitTimeout : This is the timeout used during fixed_wait scheme for new requests

  • inactivity-timeout-check: When to check for expired or inactive connections. Supported values are "never","periodic","piggyback" (when a new connection is fetched), and "all" (periodically and when a new connection is fetched).

    • We kept it “all” as we don’t want to keep connections idle longer than certain time period.

  • inactivity-timeout: The desired connection timeout, in seconds, as a positive integer, or 0 for connections to never expire. Negative values are disallowed.

    • We have kept it 60 seconds.

2) "Garbage Collector" - clean up routine

Basically three parameters are used to configure for releasing the idle connection held by OC4J connection pool.

  • inactivity-timeout-check: has to be "all" or "piggyback", all is desired if you want to periodically run clean up routine.

  • inactivity-timeout: The desired connection timeout, in seconds, as a positive integer, or 0 for connections to never expire. Negative values are disallowed.

  • Server.xml (taskmanager-granularity): When inactivity-timeout-check is configured to be periodic, this value specify how specified how frequently we want to run the periodic recycling routine.

Here is sample server.xml entry:

3) Different Level of Caching and Related Errors

Actually, after setting 1 and 2, connections were still not getting cleared, and we were able to see on MQ server side (using Tivoli) that connections are not getting closed. We found from Oracle product managers, that Adapter itself manages cache for MQ (or any type of) connections.

We need to provide, cacheConnections=false property in BPEL Partnerlink or ESB end point property. After that ESB and BPEL releases connection nicely and clean up routine described in No 2, works great and cleans up all idle connections.

4) Inbound and Outbound MQ adapter

Another finding I found was, difference between inbound and outbound adapters. If you have MQ outbound adapter with "cacheConnections=false", it releases connection right after completing the unit of work, and connection is available to OC4J connection pool. But if you have MQ inbound adapter with "cacheConnections=false", it still holds the connection. Probably it is because of continuous polling.

I have not tried it with changing the polling frequency to see if connection get releasesd.

Friday, May 9, 2008

Big News - Resigned Oracle

Joined on Nov 29, 2005 and finally completed my last day at Oracle today. Feel pretty sad and same time very exciting to face new challenges by my self. Now I am becoming independent consultant in Oracle SOA space and without any expert's support.

I am may be putting my career at risk but as we all know: The biggest risk in life is not to take one!