In Soa Suite 11g we can not call the composite service directly from java. We need to copy the service in the composite, change its binding to adf and wire this service to the component. All the credits goes to Jay's Blog and Clemens, Great work.
The first step is to open the composite xml and find your service.
<?xml version="1.0" encoding="UTF-8" ?>
<!-- Generated by Oracle SOA Modeler version 1.0 at [8/25/09 3:01 PM]. -->
<composite name="Helloworld"
revision="1.0"
label="2009-08-25_15-01-51_078"
mode="active"
state="on"
xmlns="http://xmlns.oracle.com/sca/1.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:orawsp="http://schemas.oracle.com/ws/2006/01/policy"
xmlns:ui="http://xmlns.oracle.com/soa/designer/">
<import namespace="http://xmlns.oracle.com/HelloWorld/Helloworld/BPELProcess1"
location="BPELProcess1.wsdl" importType="wsdl"/>
<service name="bpelprocess1_client_ep" ui:wsdlLocation="BPELProcess1.wsdl">
<interface.wsdl interface="http://xmlns.oracle.com/HelloWorld/Helloworld/BPELProcess1#wsdl.interface(BPELProcess1)"/>
<binding.ws port="http://xmlns.oracle.com/HelloWorld/Helloworld/BPELProcess1#wsdl.endpoint(bpelprocess1_client_ep/BPELProcess1_pt)">
</binding.ws>
</service>
Copy this service and give it a unique name and now we need to add the binding.adf binding to this service instead of the binding.ws
<service name="bpelprocess1_client_ep" ui:wsdlLocation="BPELProcess1.wsdl">
<interface.wsdl interface="http://xmlns.oracle.com/HelloWorld/Helloworld/BPELProcess1#wsdl.interface(BPELProcess1)"/>
<binding.ws port="http://xmlns.oracle.com/HelloWorld/Helloworld/BPELProcess1#wsdl.endpoint(bpelprocess1_client_ep/BPELProcess1_pt)">
</binding.ws>
</service>
<service name="bpelprocess1_client_ep2" ui:wsdlLocation="BPELProcess1.wsdl">
<interface.wsdl interface="http://xmlns.oracle.com/HelloWorld/Helloworld/BPELProcess1#wsdl.interface(BPELProcess1)"/>
<binding.adf serviceName="{http://xmlns.oracle.com/HelloWorld/Helloworld/BPELProcess1}bpelprocess1_client_ep2"
registryName=""/>
</service>
Go back to the design mode and open the new adf binding service and select the same wsdl as your other service ( this will correct the serviceName ) and at last we need to wire the new service to the component
Now we only need to call this service from java
package nl.whitehorses.bpel.unit;
import java.util.Hashtable;
import java.util.UUID;
import java.util.List;
import javax.naming.Context;
import oracle.soa.management.facade.Locator;
import oracle.soa.management.facade.LocatorFactory;
import oracle.soa.management.facade.Composite;
import oracle.soa.management.facade.Service;
import oracle.soa.management.facade.CompositeInstance;
import oracle.soa.management.facade.ComponentInstance;
import oracle.fabric.common.NormalizedMessage;
import oracle.fabric.common.NormalizedMessageImpl;
import oracle.soa.management.util.CompositeInstanceFilter;
import oracle.soa.management.util.ComponentInstanceFilter;
import java.util.Map;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;
import org.w3c.dom.Element;
import java.io.*;
public class StartProcess {
public StartProcess() {
super();
Hashtable jndiProps = new Hashtable();
jndiProps.put(Context.PROVIDER_URL, "t3://localhost:8001/soa-infra");
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
jndiProps.put(Context.SECURITY_PRINCIPAL, "weblogic");
jndiProps.put(Context.SECURITY_CREDENTIALS, "weblogic1");
jndiProps.put("dedicated.connection", "true");
String inputPayload =
"<process xmlns=\"http://xmlns.oracle.com/HelloWorld/Helloworld/BPELProcess1\">\n" +
" <input>hello</input>\n" +
"</process>\n" ;
Locator locator = null;
try {
// connect to the soa server
locator = LocatorFactory.createLocator(jndiProps);
String compositeDN = "default/Helloworld!1.0";
// find composite
Composite composite = locator.lookupComposite("default/Helloworld!1.0");
System.out.println("Got Composite : "+ composite.toString());
// find exposed service of the composite
Service service = composite.getService("bpelprocess1_client_ep2");
System.out.println("Got serviceName : "+ service.toString());
// make the input request and add this to a operation of the service
NormalizedMessage input = new NormalizedMessageImpl();
String uuid = "uuid:" + UUID.randomUUID();
input.addProperty(NormalizedMessage.PROPERTY_CONVERSATION_ID,uuid);
// payload is the partname of the process operation
input.getPayload().put("payload",inputPayload);
// process is the operation of the employee service
NormalizedMessage res = null;
try {
res = service.request("process", input);
} catch(Exception e) {
e.printStackTrace();
}
Map payload = res.getPayload();
Element element = (Element)payload.get("payload");
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
transformer.setOutputProperty("indent", "yes");
StringWriter sw = new StringWriter();
StreamResult result = new StreamResult(sw);
DOMSource source = new DOMSource(element);
transformer.transform(source, result);
System.out.println("Result\n"+sw.toString());
System.out.println("instances");
CompositeInstanceFilter filter = new CompositeInstanceFilter();
filter.setMinCreationDate(new java.util.Date((System.currentTimeMillis() - 2000000)));
// get composite instances by filter ..
List<CompositeInstance> obInstances = composite.getInstances(filter);
// for each of the returned composite instances..
for (CompositeInstance instance : obInstances) {
System.out.println(" DN: " + instance.getCompositeDN() +
" Instance: " + instance.getId() +
" creation-date: " + instance.getCreationDate() +
" state (" + instance.getState() + "): " + getStateAsString(instance.getState())
);
// setup a component filter
ComponentInstanceFilter cInstanceFilter = new ComponentInstanceFilter();
// get child component instances ..
List<ComponentInstance> childComponentInstances = instance.getChildComponentInstances(cInstanceFilter);
// for each child component instance (e.g. a bpel process)
for (ComponentInstance cInstance : childComponentInstances) {
System.out.println(" -> componentinstance: " + cInstance.getComponentName() +
" type: " + cInstance.getServiceEngine().getEngineType() +
" state: " +getStateAsString(cInstance.getState())
);
System.out.println("State: "+cInstance.getNormalizedStateAsString() );
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private String getStateAsString(int state)
{
// note that this is dependent on wheter the composite state is captured or not
if (state == CompositeInstance.STATE_COMPLETED_SUCCESSFULLY)
return ("success");
else if (state == CompositeInstance.STATE_FAULTED)
return ("faulted");
else if (state == CompositeInstance.STATE_RECOVERY_REQUIRED)
return ("recovery required");
else if (state == CompositeInstance.STATE_RUNNING)
return ("running");
else if (state == CompositeInstance.STATE_STALE)
return ("stale");
else
return ("unknown");
}
public static void main(String[] args) {
StartProcess startUnitProcess = new StartProcess();
}
}

6 comments:
Just a couple of questions over this approach.
1) What is the best means to get rid of the hard coded URL you have on your code? This code can't go as such to production.
2) You have hard coded the composite revision id. What if the customer redeploys the composite with different revision id?
3) What is the advantage of this approach over JAX-WS Proxy?
Hi,
just use a property file or a context parameter in web.xml and this you can override with a deployment profile in weblogic deployment
you can leave the revision id away then it always uses the latest
it is fast because of the rmi and more secure because you have to authenticate
thanks
Thanks for the explanation.
For 3, do you have any numbers on how much could be the performance improvement over JAX-WS for this option?
Hi
just take a look at this rmi is always fast.
http://www.sosnoski.com/presents/cleansoap/results.html
thanks
Edwin,
Thanks for the Java exmaple. I'm new to the ADF area and have a related question. I'd like to create an ADF UI to show the exact same thing... Have the UI call and drive a payload into a SOAP or RMI Composite (Mediator or BPEL) in 11g. Any in-built capabilities on the ADF side to do this? Would you possibly have an example? Thanks
Hi,
Have the UI call and drive a payload into a SOAP or RMI Composite (Mediator or BPEL) in 11g. Any in-built capabilities on the ADF side to do this?
There are more ways to do this in ADF,
first is use ws datacontrol or if you are more a java developer then you can generate a ws proxy client and generate on the port client a java datacontrol.
or use this code and generate a java datacontrol on this class.
and when you have a datacontrol then you can drag and drop the method on the jsf page.
thanks Edwin
Post a Comment