Wednesday, February 23, 2011

Invoking SOA Composite via EJB Service

Scenario - Invoke a composite via EJB passing a complex payload.

My payload is as follows -




I create a synchronous BPEL process that accepts inputOrder as input/output.

all the BPEL process does is Assign In 2 Out.




I then create an EJB Service (Generate Java interface from WSDL)






Wire together



Review the classes that have been created.




Make InputOrder and OrderType serializable

public class InputOrder implements Serializable{
public class OrderType implements Serializable{

Change the interface (BPELOrderProcess) to get rid of Holder dependency (I had
serialization issues with javax.xml.ws.Holder)

public void process(@WebParam(targetNamespace="http://www.example.org",
partName="payload", name="inputOrder", mode=Mode.INOUT)
bpelorderprocess.complexpayloadejbservice.complexpayloadejbservice_app.com.oracle.xmlns.InputOrder payload);
}

Deploy to SOA Server

Check the JNDI tree using the WLS console to see if our EJB is visible.




Create the EJB Client - I did this in the same project to save time -



Actual Code -

public class MyEJBClient {
public static void main(String [] args) throws Throwable {
try {
final Context context = getInitialContext();

Proxy proxy = (Proxy)context.lookup("ejb/BPELOrderProcessService");

// preparing the method to be called on the remote EJB
Method method =
BPELOrderProcess.class.getDeclaredMethod("process", new Class[] {InputOrder.class});
InputOrder id = new InputOrder();
id.setKey(12345);
id.setCustName("NiallC");

OrderType ot = new OrderType();
ot.setComments("Good Customer");
ot.setProduct("Oracle SOA Suite 11g");
ot.setProductGroup("FMW");
ot.setProductKey(new Long(12345));

id.setOrder(ot);

InvocationHandler handler = Proxy.getInvocationHandler(proxy);
InputOrder response = (InputOrder)handler.invoke(proxy, method, new Object[] { id });
} catch (Exception ex) {
ex.printStackTrace();
}
}

private static Context getInitialContext() throws NamingException {
Hashtable env = new Hashtable();
// WebLogic Server 10.x connection details
env.put( Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory" );
env.put(Context.PROVIDER_URL, "t3://localhost:7001");
return new InitialContext( env );
}
}

Add the Weblgic Thin Client Library to the project

Run the client

Check the instance in em



Thursday, February 10, 2011

Part 2: Getting Component instance state...

Leading on from the previous post - I've kicked off the process, now I want to check on the instance state.

Again, a big thanks to Edwin -

http://biemond.blogspot.com/2009/11/invoking-soa-suite-11g-service-from.html

I added the following to my client Java class -

public String checkInstanceState(String uuid){

//
// connect to soa and find composite
//
Hashtable jndiProps = new Hashtable();
jndiProps.put(Context.PROVIDER_URL, "t3://localhost:7001/soa-infra");
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
jndiProps.put(Context.SECURITY_PRINCIPAL, "weblogic");
jndiProps.put(Context.SECURITY_CREDENTIALS, "welcome1");
jndiProps.put("dedicated.connection", "true");

Locator locator = null;

try{
locator = LocatorFactory.createLocator(jndiProps);
Composite composite = locator.lookupComposite("default/InvokeDirectBinding!1.0");
CompositeInstanceFilter filter = new CompositeInstanceFilter();
filter.setConversationId(uuid);

List cis = composite.getInstances(filter);
// for each of the returned composite instances..
for (CompositeInstance instance : cis) {
System.out.println(" DN: " + instance.getCompositeDN() +"\n" +
" Instance: " + instance.getId() +"\n" +
" creation-date: " + instance.getCreationDate() +"\n" +
" state (" + instance.getState() + "): " + getStateAsString(instance.getState()) );
}

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


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 ("STATE_COMPLETED_SUCCESSFULLY");
else if (state == CompositeInstance.STATE_FAULTED)
return ("STATE_FAULTED");
else if (state == CompositeInstance.STATE_RECOVERY_REQUIRED)
return ("STATE_RECOVERY_REQUIRED");
else if (state == CompositeInstance.STATE_RUNNING)
return ("STATE_RUNNING");
else if (state == CompositeInstance.STATE_STALE)
return ("STATE_STALE");
else
return ("STATE_UNKNOWN");


}

I also had to add the JRF Runtime library -




I then invoked a new instance -



tested the new code ...

Wednesday, February 9, 2011

Invoking SOA Suite 11g Composite via Direct Binding

Scenario: I want to invoke a SOA Composite (essentially an Async BPEL process) via Direct Binding.

My starting point for this was Edwin's blog (which I can highly recommend!!!)-
http://biemond.blogspot.com/2009/11/calling-soa-suite-direct-binding.html

However, I had issues with namespaces in my complex payload, requiring me to switch to the Oracle XML parser --> thus this post!



I'm using the following xsd for my payload.




Step 1 - Create a SOA Composite that includes an async BPEL process with input/output types set to the order defined above. Do not expose as a SOAP Service.



Step 2 - Add a Direct Binding to the Exposed Services lane and point to the WSDL of the BPEL process.



Step 3 - Add an Assign (Input 2 Output) to the BPEL process.




Step 4 - Wire the Direct Binding to the BPEL Process.
In the BPEL designer, delete the processorders_client partner link and use the Direct Binding instead.



Step 5 - Deploy and go to http://localhost:7001/soa-infra






Step 6 - Create a new project in your JDev app e.g.
InvokeDirectBinding-Client and add the following libraries to it.



Step 7 - Add a Java class to the project and cut and paste in the following code. Then test. Note the use of the Oracle XML parser here, I had some issues with the default one... Thanks Silviu / Santosh for the tip.

package invokedirectbin;

import java.io.StringReader;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.UUID;

import javax.naming.Context;

import oracle.soa.api.JNDIDirectConnectionFactory;
import oracle.soa.api.PayloadFactory;
import oracle.soa.api.XMLMessageFactory;
import oracle.soa.api.invocation.DirectConnection;
import oracle.soa.api.invocation.DirectConnectionFactory;
import oracle.soa.api.message.Message;
import oracle.soa.api.message.Payload;
import oracle.soa.management.facade.Locator;

import oracle.xml.parser.v2.DOMParser;
import oracle.xml.parser.v2.XMLPrintDriver;

import org.w3c.dom.Element;

import org.xml.sax.InputSource;

public class InvokeComposite {
public InvokeComposite() {
super();
}

public void StartAsyncViaDirectBinding(){
//
// create a direct connection to the composite
//
Hashtable jndiProps = new Hashtable();
jndiProps.put(Context.PROVIDER_URL, "t3://localhost:7001/soa-infra");
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
jndiProps.put(Context.SECURITY_PRINCIPAL, "weblogic");
jndiProps.put(Context.SECURITY_CREDENTIALS, "welcome1");
jndiProps.put("dedicated.connection", "true");

Locator locator = null;
try {
DirectConnectionFactory factory = JNDIDirectConnectionFactory.newInstance();
String serviceAddress = "soadirect:/default/InvokeDirectBinding!1.0/DirectBinding2ProcessOrders";
DirectConnection dc = factory.createConnection(serviceAddress,jndiProps);

// Sample payload from em is as follows -

//
//
//
//
//
//
//
//
//
//
//
//
//
//

//

//


String inputPayload =
"\n" +
"RenateC\n" +
"rc@localhost\n" +
"123456\n" +
"iPad\n" +
"100\n" +
"500\n" +
"none\n" +
"50000\n" +
"pending\n" +
"none\n" +
"
\n";
System.out.println("Input = " +"\n" + inputPayload);
//
// parse using the Oracle XML parser.
// Thanks Silviu!
oracle.xml.parser.v2.DOMParser op = new DOMParser();
op.parse(new InputSource(new StringReader(inputPayload)));

// just a print to check it
XMLPrintDriver pd = new XMLPrintDriver(System.out);
pd.setFormatPrettyPrint(true);
pd.printDocument(op.getDocument());

Map partData = new HashMap();
partData.put("payload", op.getDocument().getDocumentElement());

// Create the Message and pass in the payload
Payload payload = PayloadFactory.createXMLPayload(partData);

Message request = XMLMessageFactory.getInstance().createMessage();
request.setPayload(payload);

// Define conversation ID
String uuid = "uuid:" + UUID.randomUUID();
System.out.println("uuid = "+ uuid);
request.setProperty(request.CONVERSATION_ID, uuid);

// Invoke...
dc.post("process", request);

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

}

}

Payload displayed incorrectly above so here it is again -


Anyway the source code is available at
https://docs.google.com/leaf?id=0B7YrnfO7h717ODIyNDU2MWQtOTJlOC00NTBkLWE5OTItOWRiMGM0ZGI4OTc1&hl=en&authkey=CIWLqqwL








Tuesday, February 1, 2011

Weblogic classloader analysis tool

Nice feature of the latest wls release.

Pick any app (e.g. em) and look at it's classloader details -



Monday, January 31, 2011

RCU issue on SOA 11.1.1.4 on XE

just to let you know I hit the following issue when running rcu as sys/sysdba on XE.

after running rcu, I logged into sqlplus as sys/sysdba and checked the object status with

select object_name, object_type from dba_objects where status='INVALID';

The following objects were listed -
------------------------------------------
package body mds_internal_common
package body mds_internal_shredded
package body mds_internal_utils

procedure purge_runtime_with_timeout
procedure purge_b2b_instances_down
--------------------------------------
I ran utlrp.sql to recompile and re-checked.

the 3 mds packages were still listed as INVALID.

I then logged on as DEV_MDS and re-compiled the 3 packages successfully.

The main problem was that, according to the RCU utility, everything had completed successfully. The errors were only highlighted when I attempted to start wls.

However, after fixing the DB issues, I could re-start wls successfully.

Naturally I didn't read the note on the otn download page -

If you want to use XE you can set the RCU_JDBC_TRIM_BLOCKS environment variable to TRUE *prior* to running RCU. As a reminder as to support level, when running RCU against XE you will receive a warning stating that the database version is not supported by Oracle.

Wednesday, January 26, 2011

SOA Suite 11.1.1.4 - soa composer not active by default

I did a developer install of SOA Suite 11.1.1.4.
Everything is up and running on the AdminServer.

I then test /soa/composer and see that it doesn't work ootb.

I check in the wls console and see that the composer app has been installed but is
not active.

So just, target it to the AdminServer and start it.

Tuesday, January 25, 2011

Setting up shared folders on Oracle SOA Virtual Box

Greetings from South Africa!


Scenario:

I'm using VirtualBox 4.x with the SOA image created with a 3.x version.
Shared folders don't work ootb.
Essentially you have to re-install the "new" version of VirtualBox Additions -

Thanks to the colleagues here in my workshop for the support!

Steps
I set up a shared folder as follows –



I install Guest Additions



You might get a pop-up prompting you to do a Force Unmount - so do it!

Open a Terminal window in /media

You should see a directory VBoxAdditions...



do an su root (password -oracle)



Now we need to add the user oracle to the group vboxsf

System --> Administration --> Users and Groups





Re-start the image

Open a Terminal window in /media



Yet another way - from my colleague Lawrence -

From the Oracle VM VirtualBox select the VM and go to Settings>Shared Folders
Add a share folder with a logical name like Share -> C:\VM\Share
Boot up the VM
As root
mkdir /mnt/share (share can be anything you want)
mount -t vboxsf Share /mnt/share

Note that the "Share" is from the is the logical name, and "share" is the directory that you are mounting. After this you can access everything in the /mnt/share directory. The mount command must be repeated when you want to use it.