Friday, August 10, 2012

Oracle SOA 11g – Local optimization for webservice calls


The property “oracle.webservices.local.optimization” instructs Composite to make the webservice calls via SOAP stack or not.
By default the value for the property “oracle.webservices.local.optimization” is true. If the value is true and composite invokes any other webservice on the same server/domain, it avoids soap overhead and calls natively.

There may be a situation that you want to invoke the services via Soap Stack and changing the value of “oracle.webservices.local.optimization” property to false will help us to do that.
We can set this property in Composite.xml for a specific partner link only that partner link invocation always happens via soap stack.
Open the Composite.xml in JDev and add the property - oracle.webservices.local.optimization to the corresponding partnerlink binding.


When the local optimization is true, the policies attached to the partnerlinks are also bypassed

Setting Timeouts for Oracle SOA Suite 11g




The five timeout settings in Oracle SOA Suite 11g:
  1. In the composite.xml of the composites calling the long running webservice and the composites calling these composites (and thus the whole chain of calling composites), set the webservice binding property for read timeout (and optional the connection timeout) in the reference declaration (value in milliseconds).                          
  1. ?
  2. For the BPEL timeout set property SyncMaxWaitTime (value in seconds) in the SOA Suite console (Oracle Fusion Middleware Control): In the navigation menu on the left expand the “SOA” folder and select item “soa-infra (soa_server1)” just below it. Then in the top of the details screen on the right expand the drop down menu “SOA Infrastructure” and select “SOA Administration” -> “BPEL Properties” . The “BPEL Service Engine Properties” screen opens. Click on link “More BPEL Configuration Properties…” at the bottom of this screen. Now the “Application Defined MBeans: BPELConfig:bpel” screen opens and finally you can edit the setting SyncMaxWaitTime (scroll down, setting #32 in list).
     
  3. Set timeouts in the soa EJB’s: Open the Weblogic console and click in the navigation menu on the left on “Deployments”. Expand “soa-infra” by clicking on [+] and expand node “EJBs” in the same way. Increase the “Transaction Timeout” (value in seconds) in the “Configuration” tab for the following EJB’s by clicking on them:
    • BPELEngineBean
    • BPELDeliveryBean
    • BPELActivityManagerBean
    • BPELServerManagerBean
    • BPELProcessManagerBean
    • BPELInstanceManagerBean
    • BPELFinderBean
  4. Increase the JTA timeout in the Weblogic console by selecting “soa_domain” in the navigation menu (top item) on the left. Then select tab “Configuration” and subtab “JTA”. The first setting is the “Timeout Seconds” (value in seconds).
     
  5. To solve “HeuristicMixedException” timeouts, set the “XA Transaction Timeout” of the soa jdbc connection to 0 seconds (means inherit) by expanding “Services” -> “JDBC” and select “Data Sources”. In the screen on the right select “SOADataSource” from the list and select tab “Configuration” and subtab “Transaction”. Enable setting “Use XA Datasource Interface” and setting “Set XA Transaction Timeout” and set setting “XA Transaction Timeout:” to 0 (inherit globale Weblogic transaction timeout).

Programmatically determining BPEL manual recovery status


BPEL processes can go to manual recovery. The two most common issues are: 1) an issue on the invoke of the process (BPEL server Out of Memory error for example), and 2) an issue with the callback on an asynchronous BPEL process.

BPEL process manager has a nice UI for looking at and managing these, but what if we need to be alerted when a process goes into one of these states? Well, BPEL PM doesn't have that capability, so we need to write our own. Another useful thing might be to always clear the processes, especially those that are in manual recovery for callback. Typically in that situation the callback failed, most often because the original calling process is no longer around to receive the callback.

In the article, we use JAVA API for finding processes in both invoke and callback manual recovery. For both cases, it will be necessary to get a reference to the Locator object via the BPEL Java API.

Getting process manual recovery for inoke:



            String Buffer buf = new StringBuffer();

            WhereCondition where = new WhereCondition(buf.append(SQLDefs.IM_state).append( " = " ).append(IDeliveryConstants.STATE_UNRESOLVED ).toString() );

            IInvokeMetaData imd[] = locator.listInvokeMessages(where);

            String ids[] = new String[imd.length];
 
            // print out the partial process information
            // for processes in manual recovery status on invoke
            for (i = 0; i <>
            {
                 System.out.println("ConversationId=" +
                                     imd[i].getConversationId());
                 System.out.println("ProcessId=" +
                                    imd[i].getProcessId());
                 System.out.println("State=" + imd[i].getState());

                 ids[i] = imd[i].getConversationId();
            }

            // if we wanted to automatically recover these processes
            // we would uncomment the following line:
            // locator.lookupDomain().recoverInvokeMessages(ids);
For callbacks the code flow is the exact same. Instead of IInvokeMetaData, we get an array of ICallbackMetaData using the locator.listCallbackMessages(where) method. One other slight change is the where clause itself -- for callbacks the where clause should be built as:


WhereCondition where = new WhereCondition(buf.append(SQLDefs.DM_state).append( " = " ).append(
IDeliveryConstants.TYPE_callback_soap ).toString() );
The last change for callbacks is how they are recovered -- locator.lookupDomain.recoverCallbackMessages(ids)

Using the API's above you can see how we could build a custom notification process or an automatic or work flow based recovery method that does not involve the actual BPEL PM.


Oracle SOA 11g - Abort the running composite instances through JAVA API


The below code snippet will help us to abort the running instance of the particular composite, the filter condition can be changed accordingly to abort the running composite instances with different matching criteria.


try
{
String compositeName="GetDomainID";
Hashtable jndiProps = new Hashtable();
jndiProps.put(Context.PROVIDER_URL,"t3://soahost:soaport");
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
jndiProps.put(Context.SECURITY_PRINCIPAL,"weblogic");
jndiProps.put(Context.SECURITY_CREDENTIALS,"xxxxx");
jndiProps.put("dedicated.connection","true");
Locator locator = LocatorFactory.createLocator(jndiProps);
CompositeInstanceFilter filter =new CompositeInstanceFilter();
filter.setState(CompositeInstance.STATE_RUNNING);
filter.setCompositeName(compositeName);
// filter.setId("670002");
List compositeInstances = locator.getCompositeInstances(filter);
for(int i=0;i((CompositeInstance)compositeInstances.get(i)).abort();
}catch(Exception e)
{
e.printStackTrace();
}

Execution of this code will abort all the running instances of a specified composite.

Monitoring the JCA Adapter’s through WLST script – Oracle SOA 11g


Sometimes we may need to monitor the runtime performance of the JCA adapters, the monitoring is possible through EM console for limited details, the below WLST script will help us to monitor the required details of the JCA adapter (the scrip should be extended to monitor more details).

The below script can be used for monitoring only the DBAdapter’s and MQAdapter’s; the same can be extended to monitor other JCA Adapters (like FileAdapter) .

Before executing the script change the below condition according to your server name.

if server.getName().strip().startswith('S') | server.getName().strip().startswith('O')

The Adapters are only available in SOA and OSB servers so that I am filtering the other servers  based on the name(AdminServer or MS servers) .The exception will be thrown if we are trying to cd the MBean related to Adapters in others servers.

ResourceAdapterMonitor.py

def monitorDBAdapter(serverName):
    cd("ServerRuntimes/"+str(serverName)+"/ApplicationRuntimes/DbAdapter/ComponentRuntimes/DbAdapter/ConnectionPools")
    connectionPools = ls(returnMap='true')
    print '--------------------------------------------------------------------------------------'
    print 'DBAdapter Runtime details for '+ serverName
    print '                                                                                      '
    print '                                                                                      '
    print '--------------------------------------------------------------------------------------'

    print '%10s %13s %15s %18s' % ('Connection Pool', 'State', 'Current', 'Created')
    print '%10s %10s %24s %21s' % ('', '', 'Capacity', 'Connections')
    print '                                                                                      '
    print '--------------------------------------------------------------------------------------'
    for connectionPool in connectionPools:
       if connectionPool!='eis/DB/SOADemo':
          cd('/')
          cd("ServerRuntimes/"+str(serverName)+"/ApplicationRuntimes/DbAdapter/ComponentRuntimes/DbAdapter/ConnectionPools/"+str(connectionPool))
          print '%15s %15s %10s %20s' % (cmo.getName(), cmo.getState(), cmo.getCurrentCapacity(), cmo.getConnectionsCreatedTotalCount())

    print '                                                                                      '
    print '--------------------------------------------------------------------------------------'

def monitorMQAdapter(serverName):
    cd("ServerRuntimes/"+str(serverName)+"/ApplicationRuntimes/MQSeriesAdapter/ComponentRuntimes/MQSeriesAdapter/ConnectionPools")
    connectionPoolsMQ = ls(returnMap='true')
    print '--------------------------------------------------------------------------------------'
    print 'MQAdapter Runtime details for '+ serverName
    print '                                                                                      '
    print '                                                                                      '
    print '--------------------------------------------------------------------------------------'

    print '%15s %17s %15s %18s' % ('Connection Pool', 'State', 'Current', 'Created')
    print '%15s %15s %24s %21s' % ('', '', 'Capacity', 'Connections')
    print '                                                                                      '
    print '--------------------------------------------------------------------------------------'
    for connectionPoolMQ in connectionPoolsMQ:
          cd('/')
          cd("ServerRuntimes/"+str(serverName)+"/ApplicationRuntimes/MQSeriesAdapter/ComponentRuntimes/MQSeriesAdapter/ConnectionPools/")
          cd(connectionPoolMQ)
          print '%15s %20s %10s %20s' % (cmo.getName(), cmo.getState(), cmo.getCurrentCapacity(), cmo.getConnectionsCreatedTotalCount())

    print '                                                                                      '
    print '--------------------------------------------------------------------------------------'


def main():
      #connect(username, password, admurl)
      connect('weblogic','reuters123','t3://:)
      servers = cmo.getServers()
      domainRuntime()
      for server in servers:
         cd("/ServerLifeCycleRuntimes/" + server.getName())
         if cmo.getState() == 'RUNNING':  
            if server.getName().strip().startswith('S') | server.getName().strip().startswith('O') :
                 monitorDBAdapter(server.getName())
      for server in servers:
         cd('/')
         cd("/ServerLifeCycleRuntimes/" + server.getName())
         if cmo.getState() == 'RUNNING':  
            if server.getName().strip().startswith('S') | server.getName().strip().startswith('O') :
                 monitorMQAdapter(server.getName())   
      disconnect()
     
main()



Copy the script to the soa server and execute the below command

>   wlst.sh ResourceAdapterMonitor.py

O/P:
--------------------------------------------------------------------------------------
DBAdapter Runtime details for SOA1
--------------------------------------------------------------------------------------
Connection Pool         State         Current            Created
                                                    Capacity          Connections
--------------------------------------------------------------------------------------
  eis/DB/SOA             Running         22               1051
      eis/DB/Test           Running           2                  697
    eis/DB/Test1           Running           1                  130
--------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------
MQAdapter Runtime details for SOA1
------------------------------------------------------------------------------------------------------
Connection Pool                                       State          Current            Created
                                                                                  Capacity           Connections
------------------------------------------------------------------------------------------------------
eis/MQ/MQAdapter                                 Running          0                    0
eis/MQ/MQSeriesAdapterRemote            Running          2                   84
-------------------------------------------------------------------------------------------------------

Changing the reference endpoint of a Composite through JAVA – Oracle SOA 11g


The blog explain how to use the Java API to change the reference endpoint of a composite.

This update is not a cluster-aware; remember that you must repeat the same process for each managed server of your environment.

UpdateEndPoint .java

import java.util.*;
import javax.management.*;
import javax.management.openmbean.*;
import javax.management.remote.*;
import javax.naming.Context;

public class UpdateEndPoint {

    public static MBeanServerConnection getMbeanServerConnection(String host,int port,String userName,String password) throws Exception {
        String jndiroot = "/jndi/";
        MBeanServerConnection m_connection = null;
        try {
            Hashtable jndiProps = new Hashtable();
            jndiProps.put(Context.SECURITY_PRINCIPAL, userName);
            jndiProps.put(Context.SECURITY_CREDENTIALS, password);
            jndiProps.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES,"weblogic.management.remote");

            JMXServiceURL serviceURL =new JMXServiceURL("t3", host, port, jndiroot +"weblogic.management.mbeanservers.runtime");
            JMXConnector m_connector =JMXConnectorFactory.newJMXConnector(serviceURL, jndiProps);
            m_connector.connect();
            m_connection = m_connector.getMBeanServerConnection();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return m_connection;
    }

    private static CompositeDataSupport UpdateEndPointData(CompositeDataSupport cds,String[] keys,String[] newValues) throws Exception {
        Map items =new HashMap(cds.getCompositeType().keySet().size());

        for (String key : cds.getCompositeType().keySet()) {
            boolean matched = false;
            int i = 0;

            for (; i < keys.length; i++) {
                String searchKey = keys[i];

                if (searchKey.equalsIgnoreCase(key)) {
                    items.put(key, newValues[i]);
                    matched = true;
                    break;
                }
            }

                if (!matched) {                   
 
                         items.put(key, cds.get(key));                 
 
                 }
             }

        return new CompositeDataSupport(cds.getCompositeType(), items);
    }

    public static void updateEndPoint(String host, String port,String userName, String password,String compositeName,String revision, String referenceName, String endpoint) {

        String mBeanName =
            "oracle.soa.config:SCAComposite=\""+compositeName+"\""+",revision="+revision+",port=*,label=*,Application=*,name=WSBinding,SCAComposite.SCAReference="+referenceName+",j2eeType=SCAComposite.SCAReference.SCABinding,*";

        MBeanServerConnection mbsc;
        try {
            mbsc =getMbeanServerConnection(host, Integer.parseInt(port), userName, password);
            Set mbeans =mbsc.queryNames(new ObjectName(mBeanName), null);
            ObjectName mbean = (ObjectName)mbeans.iterator().next();
            javax.management.openmbean.CompositeData[] properties =(javax.management.openmbean.CompositeData[])mbsc.getAttribute(mbean, "Properties");
            boolean endpointFound = false;
            for (int i = 0; i < properties.length; i++) {
                CompositeDataSupport cds = (CompositeDataSupport)properties[i];        
 

                if ("endpointURI".equalsIgnoreCase((String)cds.get("name"))) {

                    properties[i] =UpdateEndPointData((CompositeDataSupport)properties[i],new String[] { "value" },new String[] { endpoint });
                    mbsc.setAttribute(mbean,new Attribute("Properties", properties));
                    endpointFound = true;
                    break;
                }
            }

            // Property not found, insert it
            if (!endpointFound) {
                CompositeDataSupport cds =UpdateEndPointData((CompositeDataSupport)properties[0],new String[] { "name", "value" },new String[] { "endpointURI",endpoint });
                CompositeData[] newPropertyArray =AppendEntry(properties, cds);
                mbsc.setAttribute(mbean,new Attribute("Properties", newPropertyArray));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static CompositeData[] AppendEntry(CompositeData[] properties,CompositeDataSupport endpointProperty) {
        CompositeData[] newArray =new CompositeData[properties.length + 1];
        for (int x = 0; x < properties.length; x++) {
            newArray[x] = properties[x];
        }
        newArray[properties.length] = endpointProperty;
        return newArray;
    }

    public static void main(String[] args) {        //updatePreference(host,post,username,password,compositeName,revision,,referenceParnerlink,enpoint);
  updateEndPoint("localhost", "8000", "weblogic", "password","InvokeServlet", "1.0","InvokeServletService","http://localhost:8080/EmployeeServlet/employeeservlet");
    }
}

Add the weblogic.jar file to the class.
Before executing the program, change the server details, Composite name, revision, reference name and the endpoint location accordingly.

Passing parameter to XSLT in SOA 11g


Not like SOA 10g, in SOA 11g the parameters can be directly added into the Transform activity from GUI.
The parameters can be of any schema element type; the XML Schema Simple types are not accepted.

Create a schema definition that will have the parameter definition e.g.
Here, I have defined the schema to pass the parameters startIndex and endIndex to the XSLT.





Create the variable (e.g. parameters) of required element type defined in the schema, in my case the element name is parameters.


Open the Transform activity and select the Input/output variables. Add the parameters variable in the source section, the first variable that is added becomes the source for the transformation activity. These additional variables become as parameters to the transform file.


The parameter can be accessed using the syntax: $parametername+ XPath expression for the node.





Correlating the request/response messages in MQ Series Adapter – Oracle SOA 11g


Mapping a response to a request in a request-reply interaction requires correlation.The MQ adapter provide the inbuilt options to correlate the request and response messages, there is no need of implementing the custom correlation to correlate the request and response messages.

Each MQSeries request message contains a message ID and a correlation ID. When an application receives a request message from Oracle BPEL PM, it checks for the correlation schema defined for the response message. Based on the correlation schema, the application generates the message ID and correlation ID of the response message. Based on the Message ID/Correlation ID the request/response messages will be correlated in the MQAdapter.

The below are the two patterns to correlate the request/response messages in MQ adapter.
·                     Get Message from MQ and Send Reply
·                     Send Message to MQ and Get Reply

Get Message from MQ and Send Reply:

MQ adapter gets a message from the inbound Queue and send a reply message to the outbound bound queue Synchronously/Asynchronously.
·                     Create a composite with synchronous/asynchronous BPEL process.
·                     Delete the default service created and add the MQ Adapter service



·                     Add the MQ JNDI name in the 3rd step of MQ adapter definition.

·                      Select the operation as Get message to MQ and Get Reply/Reports and the option name as Asynchronous/Synchronous in the 5th step.



·                      Select the Message Type as Normal and enter the request queue name as part 6th step.


·                     Enter the reply queue in the 7th step



·                     Configure the input/output schema s in 8th step


·                     Delete the default parnerlink in the BPEL and connect to the partner link created for the MQ.


·                     Delete and Recreate the input/output variables and complete the BPEL design as per the requirement.



·                     Double click on the receiveInput activity in the BPEL and select the properties tab.
·                     Select the messageid as the input for the property jca.mq.MQMD.MsgId – Create the messageid variable before as string type.


·                     Open the callbackclient activity and select the properties tab, add the messageid variable as the input to the property jca.mq.MQMD.MsgId


·                     Deploy the code and test.


 Send Message to MQ and Get Reply:
·                     Design the Composite and the BPEL process.









·                      Configure the MQ adapter as a reference by following the steps mentioned above.
·                     Make sure the Message Type selected as Normal in the 6th step




·                      Make sure the Message ID and the Correlation ID values selected as shown below in the 7th step.


·                     Deploy the composite and test.