Powered By Blogger

Friday, August 26, 2011

Deploying ADF based human task form from JDev11g

How human task forms are generated in BPEL11g  is lot more different than  BPEL10g
In 11g for every task form you generate it will be generated as separate project under same application or in a different application.

When you deploy  task form as a separate application (outside of composite application deployment) we should deploy it from application name drop down list but not by right click on task form project and deploy.

If you try to  right click on task form project and deploy then you will see error messages like

In jdev
Caused by: java.lang.ClassNotFoundException: oracle.adf.library.webapp.ResourceServlet

in log file

There was a failure when processing annotations for application /apps/domains//servers/AdminServer/upload//app/ Please make sure that the annotations are valid. The error is oracle.adf.library.webapp.ResourceServlet



Thursday, April 14, 2011

exception on JaxRpc invoke: unknown prefix in QName literal: null

This small post is all about to discuss an error I got during run time of a BPEL process.
There may be a lot more reasons to see this error, but I would like to discuss one instance where I see this error.

If you see error, obscurely it says there is a problem in invoking other service.In my case my BPEL process bpel.xml  is referring to wrong url.

For example:

My bpel.xml is referring to

 <partnerLinkBinding name="BPELProcess1">
            wsdlLocation">http://host.domain.com:7778/orabpel/default/BPELProcess1/BPELProcess1?wsdl
 partnerLinkBinding>


What I observe here is connection could not reach  host.domain.com  and that caused this error.
When I replace  wsdl location with another wsdl for same process and different host, then it got executed.
There may be firewall which is restricting access to the box. So please be careful..


Wednesday, March 23, 2011

Configuring SAF JMS Resources

store and forward agents (SAF) in WLS is a mechanism by which WLS local JMS producers produces messages to remote JMS destinations. These remote JMS destination can be part of  other domain/machine/cluster.

Main steps involved are
  1. Create SAF agent
  2. Create SAF remote context
  3. Create SAF imported destination
  4. Configuring SAF  imported destination with remote Queues and Topics
 Create SAF agent
SAF agent is a component which  is responsible for storing and forwarding messages between local sending and remote receiving destinations
It stores messages locally when remote destination is not reachable and forwards it when remote destination is available.
We are trying to produce JMS messages to remote destination ; hence it is required
Provide appropriate values when creating SAF agent and make sure you select 'Sending Only' for agent type field.

Create SAF remote context
 SAF remote context holds connecting url and credential information to connect to remote WLS instance.
  1. Login to WLS console and navigate to Services> Messaging>JMS Modules, click on required JMS module<SOAJMSModule> on which you want to create this resource
  2. Click New button and select 'Remote SAF Context', click Next
  3. Specify required information and click OK
Note: URL format can be :// host:port, for example http://server1:8001

Create SAF imported destination

SAF imported destinations are collections of SAF queues and topics that locally represent JMS queues or topics on a remote server instance or cluster
  1. Login to WLS console and navigate to Services> Messaging>JMS Modules, click on required JMS module<SOAJMSModule> on which you want to create this resource
  2. Click New button and select 'SAF Imported Destination', click Next
  3. Provide any valid JNDI prefix, example safjms. and select remote SAF context created in previous step,click next
  4. Click Advanced Targeting and select one of subdeployments from list and make sure this resource is targeted to SAF agent created in 1st step.(To understand what we are doing here you need to understand JMS sub deployment mechanism in WLS)
  5. Click Finish
Configuring SAF  imported destination with remote Queue and Topics

 Now we have to associate remote JMS destinations with SAF imported destinations
  1. Click on created SAF imported destination
  2. Click on either Queues or Topics tab depending on type of resource you would like to access remotely
  3. Provide Remote JNDI name(This should exactly match the remote JMS destination JNDI) and click OK
  4. Now click on newly created resource and provide any valid local JNDI name for example saf.localjndi and click Save
Now you are ready to produce  messages to remote JMS destinations using local JMS producers

Note: Please use local JNDI prefix + local JNDI name to produce messages locally, in our case it becomes  safjms.saf.localjndi. To consume messages consumer has to use remote JNDI.





Wednesday, March 16, 2011

DEV_MDS.MDS_INTERNAL_SHREDDED has errors



This article is about to discuss an issue I faced during starting of SOA11.1.1.4 server on top of XE database.

After installing SOA 11.1.1.4 on top of XE database and when I start admin server I started seeing below error message.
One more indication which confirms this issue is when we create a connection in Jdev we can not see any MDS  partitions to connect to the server.

Circumstance: When SOA 11.1.1.4 is installed on XE database and when we start admin server/managed server


This error is specific to XE db

Error
Caused By: oracle.mds.exception.MDSExceptionList: MDS-01329: unable to load element "persistence-config"


MDS-01370: MetadataStore configuration for metadata-store-usage "soa-infra-store" is invalid.
ORA-04063: package body "DEV_MDS.MDS_INTERNAL_SHREDDED" has errors

ORA-06508: PL/SQL: could not find program unit being called: "DEV_MDS.MDS_INTERNAL_SHREDDED"

If you try to compile above procedure and if error is

Error(1): PLS-00753: malformed or corrupted wrapped unit, then you can simply apply below solution

Solution:
1) Use RCU to drop the SOA Suite schemas and tablespaces


2) Set the environmental variable RCU_JDBC_TRIM_BLOCKS=TRUE and then run RCU again to re-create the SOA Suite schemas and tablespaces


Friday, March 11, 2011

OSB 11g "Test Console" service is not running

We use OSB test console application to test Proxy/Business services before moving them to production.
When we install OSB for production mode then there is a separate 'osb_server1' managed server is installed.
Starting this server is mandatory to use 'test console'.
If you start working on designing OSB services without starting 'osb_server1' then all your changes are partially activated. You can check this on OSB console.

So when you 'click test console' before starting osb_server1 we see an error like

Error Accessing Test Configuration
"Test Console" service is not running. Contact administrator to start this service.
 
Solution to this is starting osb_server1.
If you still see error, then follow below step too.

Try setting the Admin server listen address to a specific valid address, such as localhost.
In the Oracle WebLogic Server Console, go to Environment > Servers > admin_server_name  > Configuration > General to set the Listen Address.
 
If OSB server is installed for development mode, then you will not have this problem.

Tuesday, February 22, 2011

Java API to manipulate BPEL 10g processes

Once BPEL processes are deployed onto servers then they are available in two forms to be invoked
  • As a webservice through WSDL/SOAP interface
  • Java component
In this article we see basics behind java client to inoke BPEL processes.

Oracle provide java api, also called as 'Java Business Delegates' API to manipulate deployed BPEL processes.This functionality is provided as part of below jars.
  • orabpel.jar 
  • orabpel-common.jar
  • oracle_http_client
  • orabpel-boot
Major steps involved in using this API are
  1. Add appropriate Oracle BPEL jar files to your java client application classpath.
  2. Get the handle to com.oracle.bpel.client.Locator object
  3. Build com.oracle.bpel.client.util.WhereCondition object to form a query to be executed against SOA data source
  4. Get tha handle to  com.oracle.bpel.client.dispatch.IDeliveryService object from the reference of Locator object
  5. Build com.oracle.bpel.client.NormalizedMessage to create input message
  6. Call appropriate method  (deliveryService.request(..)/deliveryService.post(...)) to perform BPEL invocation
 Note that only 1st nd 2nd  steps are mandatory and remaining steps are optional and required depending on tasks you perform on BPM engine.

If you take a task of deleting a bpel process from BPEL domain then following code provides necessary steps

try{

com.oracle.bpel.client.IInstanceHandle instance;

com.oracle.bpel.client.IInstanceHandle[] instances;

String instanceKey = null;

//processInstanceId is a BPEL variable holding process_instance_id to be deleted

instanceKey =(java.lang.String)getVariableData("processInstanceId ");

Locator locator = new Locator("default", "welcome1");
// Set the whereclause

WhereCondition cond1 = new WhereCondition( "cikey = ?" );

WhereCondition cond2 = new WhereCondition( "process_id = ?" );

//set query parameters
cond1.setLong(1,Long.parseLong(instanceKey));
cond2.setString(1,"BPELProcess2");

//I am converting cond1 to process_id= ? and cikey = ?
cond1.prepend("and").prepend(cond2);
// Perform the query using the Locator

instances =locator.listInstances(cond1);
instance = instances[0];

instance.delete(); // deletes instance trace  from data source
//instance.abort(); // terminates instance trace  from data source
//instance.cancel(); // canceles instance trace  from data source
addAuditTrailEntry("BPELProcess2 instance deleted: "+instanceKey);
}catch(Exception e){
addAuditTrailEntry(e.getMessage());
}

If you take a task of recovering BPEL call back messages then following code provides necessary steps

package bpelrecovery;

import com.oracle.bpel.client.*;
import com.oracle.bpel.client.util.SQLDefs;
import com.oracle.bpel.client.util.WhereCondition;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import javax.naming.Context;

public class bpelrecovery {
public bpelrecovery() {

}

public static void main(String[] args) {
bpelrecovery recover = new bpelrecovery();

String rtc = "";
try{

rtc = recover.doRecover();
}
catch (Exception e){
e.printStackTrace();

}
}
private void recoverCallbackMessages(List messages)

throws Exception
{
String messageGuids[] = new String[messages.size()];
for(int i = 0; i < messages.size(); i++)
{

ICallbackMetaData callbackMetadata = (ICallbackMetaData)messages.get(i);

String messageGuid = callbackMetadata.getMessageGUID();

messageGuids[i] = messageGuid;

System.err.println((new StringBuilder()).

append("recovering callback message =").

append(messageGuids[i]).append(" process[").

append(callbackMetadata.getProcessId()).append("(").

append(callbackMetadata.getRevisionTag()).

append(")] domain [").

append(callbackMetadata.getDomainId()).

append("]").toString());
}

Locator locator = getLocator();

IBPELDomainHandle domainHandle = locator.lookupDomain();

domainHandle.recoverCallbackMessages(messageGuids);

System.out.println("Complete RECOVER");
}

public String doRecover() throws Exception{

WhereCondition where = null;
// Connect to domain "default"

try{

System.out.println("doRecover() instantiating locator...");

Locator locator =(Locator) getLocator();

System.out.println("doRecover() instantiated locator for domain " +

locator.lookupDomain().getDomainId());

// look for Invoke messages in need of recovery

StringBuffer buf1 = new StringBuffer();

where = new WhereCondition(buf1.append(SQLDefs.IM_state).append( " = "

).append(IDeliveryConstants.STATE_UNRESOLVED ).toString() );

System.out.println("doRecover() instantiating IInvokeMetaData... with where = "+ where.getClause());

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

System.out.println("doRecover() instantiated IInvokeMetaData");
// iterate thru the list

List l1 = new ArrayList();

for (Object o:imd1){

l1.add(o);
}

// See how many INVOKES are in the recovery zone

System.out.println("doRecover() instantiated IInvokeMetaData size = " +l1.size());

// look for Callback messages in need of recovery

StringBuffer buf = new StringBuffer();

where = new WhereCondition(buf.append(SQLDefs.DM_state).append( " = "

).append(IDeliveryConstants.TYPE_callback_soap ).append(" and ").

append(SQLDefs.DM_conv_id).append(" = ").append("\'MD5{54017bc3a7bfc4f7f50381287ff28bc7}\'")

.append(SQLDefs.DM_process_id).append(" = ").append("\'BPELProcess3\'")

.append(" and ").append("ROWNUM").append(" < ").append("30").toString() );

System.out.println("doRecover() instantiating ICallbackMetaData... with where = "+

where.getClause());

ICallbackMetaData imd[] = locator.listCallbackMessages(where);

System.out.println("doRecover() instantiated ICallbackMetaData");

//
// recover
//

List l = new ArrayList();
for (Object o:imd){
l.add(o);
}

recoverCallbackMessages(l);
}
catch (Exception e){
e.printStackTrace();
}
return "done";

}
public Locator getLocator(){
System.out.println("getLocator() start");
Locator locator = null;

// set JNDI properties for BPEL lookup

String jndiProviderUrl = "opmn:ormi://127.0.0.1:6003:oc4j_soa/orabpel";
String jndiFactory = "com.evermind.server.rmi.RMIInitialContextFactory";
String jndiUsername = "oc4jadmin";
String jndiPassword = "welcome1";
Hashtable jndi = new Hashtable();

jndi.put(Context.PROVIDER_URL, jndiProviderUrl);
jndi.put(Context.INITIAL_CONTEXT_FACTORY, jndiFactory);
jndi.put(Context.SECURITY_PRINCIPAL, jndiUsername);
jndi.put(Context.SECURITY_CREDENTIALS, jndiPassword);
jndi.put("dedicated.connection", "true");

try{
System.out.println("getLocator() instantiating locator...");
locator = new Locator("default", jndi);
System.out.println("getLocator() instantiated locator@" +locator);
}
catch (Exception e){
System.out.println("getLocator() error");
e.printStackTrace();
}
return locator;
}
}

Wednesday, January 26, 2011

Reopening completed workflow human task

Usecase: Sometimes we may come across a situation where we wanted to re-open the completed workflow human task.

Implementation steps:
  • Capture the token and taskid attributes of completed human task. You can get these task attributes from 'initiateTaskResponseMessage'  outputVariable which will be created in INVOKE activity of human task service

  • Drag and drop database adapter after human task RECEIVE activity and execute delete operation from orabpel.wftask and orabpel.wfroutingslip where taskid = 'Already captured Taskid'
  • Drag and drop invoke activity and link it to TaskServcie partnerlink service and select 'reinitiate Task' operation


  • Drag an Assign activity before last INVOKE and assign previously stored Taskid, token and 'ASSIGNED'  literal value to Taskid,token and state fields of  Invoke_1_reinitiateTask_InputVariable respectively
  • Compile and deploy

Removing unwanted namespace nodes from BPEL XML data

Use case- We have a requirement where we wanted to remove certain kinds of names space nodes from BPEL XML data and write it to file location.

Implementation steps:
  • Assume that we declare string variable- tmp in BPEL which holds the xml containing name space nodes  to be deleted
    
     
      
       
      

   


  • We also  declare another string variable - encStr in BPEL which holds transformed xml data
  • Java embedding activity with below code


     
try {       
addAuditTrailEntry("Try Block");    
String outputString = null;        
outputString = (java.lang.String)getVariableData("tmp");        
outputString = outputString.replaceAll("xmlns=\"http://xmlns.modeln.com/ApplicationObjects/MCOCheckAck/V1\"", "");            
outputString = outputString.replaceAll("xmlns:ns0=\"http://xmlns.modeln.com/ApplicationObjects/MCOCheckAck/V1\"", "");          
outputString = outputString.replaceAll("ns0:", "");
outputString = outputString.replaceAll(" xmlns=\"\"", "");     
addAuditTrailEntry("outputString"+outputString);     
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();     
DocumentBuilder db = dbf.newDocumentBuilder();     
org.w3c.dom.Document originalDoc = db.parse(new ByteArrayInputStream(outputString.getBytes()));     
         DOMSource domSource = new DOMSource(originalDoc);     
         StringWriter writer = new StringWriter();    
         addAuditTrailEntry("writer"+writer);    
         StreamResult result = new StreamResult(writer);    
         addAuditTrailEntry("result"+result);    
         TransformerFactory tf = TransformerFactory.newInstance();     
         Transformer transformer = tf.newTransformer();     
         transformer.transform(domSource, result);    
         addAuditTrailEntry("domSource"+domSource);    
         addAuditTrailEntry("result"+result);    
      
String encoded = Base64Encoder.encode(writer.toString());       
setVariableData("encStr",encoded);     
} catch(Exception ex) {       
ex.printStackTrace();       
}

Create a file adapter partner link with ‘Schema is Opaque ’ option




  • Next assign encStr variable to file invoke activity input variable
  • Add an invoke activity to invoke file adapter to write transformed xml
Disadvantages of this approach


We can not see transformed payload in audit trail of BPEL console because of binary format but if we check file write location you can see XML payload without name space nodes.