Featured Posts

osb

Oracle Service Bus, processing Java Object Messages with JMS transport

A few releases back Oracle enhanced to JMS transport to be able to handle Java Objects in queues and topic. The JMS transport now has the option to either receive Java Objects in the OSB processes by retrieving them from a topic or queue, or storing the plain Java Objects.

First we need to create a new queue in Weblogic, in my case QueueuIn.

1. Create the java entity object

Create the next entity object

package nl.xenta.entities;

import java.io.Serializable;

public class Employee  implements Serializable {
	
	private static final long serialVersionUID = -5802550970297576366L;
	public String firstname;
	public String lastname;
	public Integer age;
	
	public String getFirstname() {
		return firstname;
	}
	public void setFirstname(String firstname) {
		this.firstname = firstname;
	}
	public String getLastname() {
		return lastname;
	}
	public void setLastname(String lastname) {
		this.lastname = lastname;
	}
	public Integer getAge() {
		return age;
	}
	public void setAge(Integer age) {
		this.age = age;
	}
}

Build it and generate a jar file from it.

2. Client to send Java Object Message

package nl.xenta.utilities;

import java.util.Hashtable;

import javax.jms.Message;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueReceiver;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;

import nl.xenta.entities.Employee;
import nl.xenta.entities.Person;
import nl.xenta.services.EmployeeService;

public class JmsHelper {

	public final static String JNDI_FACTORY = "weblogic.jndi.WLInitialContextFactory";
	public final static String JMS_FACTORY = "javax.jms.QueueConnectionFactory";
	public final static String QUEUE = "QueueIn";

	static QueueConnectionFactory factory;
	static QueueConnection qconnection;
	static QueueSession qsession;
	static QueueReceiver qreceiver;
	static Queue queue;
	static Context ctx;
	private boolean quit = false;

	/**
	 * @param args
	 * @throws Exception
	 */
	public static void sendMessage() throws Exception {
		QueueConnection queueCon = null;
		try {
			// get the initial context, refer to your app server docs for this
			Hashtable<String, String> ht = new Hashtable<String, String>();
			ht.put(Context.INITIAL_CONTEXT_FACTORY,
					"weblogic.jndi.WLInitialContextFactory");
			ht.put(Context.PROVIDER_URL, "t3://localhost:7001");
			Context ctx = new InitialContext(ht);

			// get the connection factory, and open a connection
			QueueConnectionFactory qcf = (QueueConnectionFactory) ctx
					.lookup("weblogic/jms/XAConnectionFactory");
			queueCon = qcf.createQueueConnection();

			// create queue session off the connection
			QueueSession queueSession = queueCon.createQueueSession(false,
					Session.AUTO_ACKNOWLEDGE);

			// get handle on queue, create a sender and send the message
			Queue queue = (Queue) ctx.lookup(QUEUE);
			QueueSender sender = queueSession.createSender(queue);

			// create employee object
			Employee emp = new Employee();
			emp.setAge(32);
			emp.setFirstname("Eric");
			emp.setLastname("Elzinga");

			// send java object to queue
			Message msg = queueSession.createObjectMessage(emp);
			sender.send(msg);

			System.out.println("Send Java Object Message");
		} finally {
			// close the queue connection
			if (queueCon != null) {
				queueCon.close();
			}
		}
	}
}

Execute the jms java client to create Employee object and store it on the QueueIn queue.
Go to the Weblogic Console to see if the message arrived in the QueueIn queue.

When we now click on the message it will give the next message

	Unable to view message, reason = java.lang.ClassNotFoundException: nl.xenta.entities.Employee

Copy the builded jar from step1 (the jar with the compiled Employee class in it) to the next location

	YOUR_MIDDLEWARE_HOME/user_projects/domains/osb_domain/lib

Restart Weblogic and try viewing the message in the console again.

Great, it worked. Now we can see a Employee object is stored in the queue.
Let’s go on with the OSB part.

3. Oracle Service Bus Proxy Service

  1. First copy the jar created in step 2 to our OSB project.
  2. Create a new Messaging Proxy Service
  3. Select ‘Java’ for Request Message Type
  4. Use jms protocol and configure the endpoint (use the just created queue)

    Select Queue for Destination Type

    Configure the Client Jar and browse to the jar file generated in step 2.

    If we skip this settings the proxyservice won’t be able to deserialize the java objects retrieved from the queue. Resulting in stacktraces like this

    ####<Aug 28, 2011 10:23:56 AM CEST> <Error> <OSB Kernel> <multimedia> <AdminServer> <[ACTIVE] ExecuteThread: '26' for queue: 'weblogic.kernel.Default (self-tuning)'> <<anonymous>> <BEA1-03E7A5A49D452A912D4B> <1bf9ba3a756c6ce8:6b05e983:1320f4d10ed:-8000-00000000000000bb> <1314519836078> <BEA-380003> <Exception on TransportManagerImpl.receiveMessage, com.bea.wli.sb.context.BindingLayerException: General runtime error: [JMSClientExceptions:055115]Error deserializing an object
    com.bea.wli.sb.context.BindingLayerException: General runtime error: [JMSClientExceptions:055115]Error deserializing an object
    
    Caused By: java.lang.ClassNotFoundException: nl.xenta.entities.Employee
    	at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    
  5. Create the Message Flow as defined in the picture and only add a log activity, which logs the body.

Deploy the process and use the JmsHelper client to create an Employee object and send it to the queue.
The proxy service will poll, get it out of the queue and basically does nothing with it except logging the body.
After the message is send, check the osb domain log file to see what’s in the $body variable.

<BEA-000000> < [PipelinePairNode1, PipelinePairNode1_request, stage2, REQUEST] ### debug logging $body ###: <soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <con:java-content ref="jcid:4c741db6:131dd1e4544:-7fc5" xmlns:con="http://www.bea.com/wli/sb/context"/>
</soapenv:Body>> 

The java object is retrieved from the queue and processed by the proxy service.
But when we look in the body we don’t see any ‘actual’ payload, only a java ref to the java object itself.

Let’s use a few java callouts to see how we can use the content of the java object.

4. Proxyservice, java callout, java (object) in, string out

Extend the java project from step1.
Create a new class (EmployeeService) with the next method (convertEmployeeToString) in it

package nl.xenta.services;

import java.io.File;
import java.io.IOException;

import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;

import nl.xenta.crm.employee.EmployeeDocument;
import nl.xenta.crm.employee.EmployeeType;
import nl.xenta.entities.Employee;
import nl.xenta.entities.Person;

public class EmployeeService {

	public static String convertEmployeeToString(Employee employee) {
		return employee.toString();
	}
}

The input Employee object will be the data from the queue and as response we just return the string value of the object.
Generate a jar archive from it and store it in your OSB project.

Add the java callout to your proxy service message flow and after it add the log activity.
The log activity will just log the value of $my_string_response.

Now trigger the process again by sending a message with the JmsHelper client and check the osb log file.

<BEA-000000> < [PipelinePairNode1, PipelinePairNode1_request, stage2, REQUEST] ### JMSObject_ps, logging string response after the java callout ###: Employee [firstname=Eric, lastname=Elzinga, age=32]> 

Read this for some extra information about the java callouts and their input and return types.
“The input and return types for Java callouts are not restricted. However, any return types other than primitives, Strings, or XmlObjects can only be passed (unmodified) to other Java callouts.”
In this example we get a String returned, so we can just retrieve the value of it in the message flow without sending it to another java callout.

5. Proxyservice, java (object) in, java (object) out

For this example i made a copy of the Employee object and named it Person. We will use the same Employee object as example1 for the input and return a Person object back to OSB and log this.

	public static Person convertEmployeeToPerson(Employee employee) {
		Person person = new Person();
		
		person.setFirstname(employee.firstname);
		person.setLastname(employee.lastname);
		person.setAge(employee.age);
		
		return person;
	}

<BEA-000000> < [PipelinePairNode1, PipelinePairNode1_request, stage2, REQUEST] ### JMSObject_ps, logging person response after the java callout ###: <con:java-content ref="jcid:4cd600ef:131e1eeb1b1:-7fca" xmlns:con="http://www.bea.com/wli/sb/context"/>> 

And again we get a java ref back, only this time a new ref id to a new object.
To be able to ‘use’ this object we can either send it to a new java callout or publish it to another queue.

6. Proxyservice, java (object) in, XmlObject out

See this blog on how to send the java object to a java callout and return a XmlObject back.
I added the XMLBeans resources (build.xml and libs) to the same project as mentioned in step1.

For this testcase we used the next method. It will receive the Employee object from the queue and return the xml(object) representation of it back to the OSB.

	public static XmlObject convertJavaToXml(Employee employee) throws Exception {
		EmployeeDocument empDoc = EmployeeDocument.Factory.newInstance();
		EmployeeType myEmp = empDoc.addNewEmployee();
		myEmp.setAge(32);
		myEmp.setFirstName("Eric");
		myEmp.setLastName("Elzinga");
			
		return myEmp;			
	}

Run the ant build script again and copy the jar to our OSB project.
In this jar we will find the Employee and Person entities, the generated XMLBeans artifacts and the static methods used for the java callout. I guess we could have splitted some of those in other archives, but for the simplicity of this article it’s fine like this.
The jar we used in the other cases won’t be needed anymore since all we need is in this new one.

Don’t forget to edit the proxyservice and change the Client Jar to the new jar.

And the java callout

<BEA-000000> < [PipelinePairNode1, PipelinePairNode1_request, stage2, REQUEST] ### JMSObject_ps, logging my_employee_xml response after the java callout ###: <emp:employee xmlns:emp="http://xenta.nl/crm/employee">
  <emp:FirstName>Eric</emp:FirstName>
  <emp:LastName>Elzinga</emp:LastName>
  <emp:Age>32</emp:Age>
</emp:employee>> 

With this final testcase we’re able to retrieve the java object from the queue, convert it to a xml representation and send it back to the proxy service.
In the message flow we’re now able to retrieve data from it by use of some xpath expression.

osb

Oracle Service Bus, java callouts with XmlObjects

In the Oracle Service Bus we can make use of java callouts to invoke plain java.
Basically there aren’t any restrictions on the the input and output parameters of the static methods.

There are 2 situations which will differ in the way we get the data returned back from the java callout, see this

Return primitives, Strings or XmlObjects from the java callout.
In this case we can just retrieve the data from the $body variable and execute xpath expressions on it to immediately get the value of the payload.

Return anything else
In this case we will get back a java ref identifier back from the java callout.
Executing xpath expressions on the $body will only give use a reference to the java object

<BEA-000000> < [PipelinePairNode1, PipelinePairNode1_request, stage2, REQUEST] ### debug logging $body ###: <soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <con:java-content ref="jcid:4c741db6:131dd1e4544:-7fc5" xmlns:con="http://www.bea.com/wli/sb/context"/>
</soapenv:Body>> 

To be able to use the data in the java object we can only pass it to other java callouts.

In this blog i will show an example of how to generate a XmlObject, mentioned as one of the return types in case 1.
If we’re able to generate this kind of object from the java callout, OSB will just be able to retrieve this in the $body variable and let us execute xpath expression on it.

1. Create a Java project in Eclipse

We will be using XML Beans to generate the java artifacts based on a Employee schema definition.
These artificats we will be using in our static method to generate the Employee java objects which represents our Employee entity definition from the xsd schema.
Read this and this to get a quickstart on XML Beans.

  1. In Eclipse we will create a new java project with a dependency on the Apache XML Beans library.
    I copied the ORACLE_MIDDLEWARE_HOME\modules\com.bea.core.xml.xmlbeans_2.1.0.0_2-5-1.jar to my lib folder in the project.
    Add the same file as build dependency (libraries) in the project properties.

  2. Create a schemas folder in the root and add the Employee.xsd to it

    <?xml version="1.0" encoding="UTF-8"?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:emp="http://xenta.nl/crm/employee" targetNamespace="http://xenta.nl/crm/employee" elementFormDefault="qualified" attributeFormDefault="unqualified">
    	<xs:element name="employee" type="emp:EmployeeType">
    		<xs:annotation>
    			<xs:documentation>Employee entity</xs:documentation>
    		</xs:annotation>
    	</xs:element>
    	<xs:complexType name="EmployeeType">
    		<xs:sequence>
    			<xs:element name="FirstName" type="xs:string"/>
    			<xs:element name="LastName" type="xs:string"/>
    			<xs:element name="Age" type="xs:int"/>
    		</xs:sequence>
    	</xs:complexType>
    </xs:schema>
    
  3. Create a build.xml in the root of the project. I used the one mentioned in the quickstart articles and edited it a bit.

    	<?xml version="1.0" encoding="UTF-8"?>
    	<project name="XMLBeansDemo" default="build">
    		<property environment="env"/>
    
    		<path id="Any.path">
    			<path refid="xmlbeans.path"/>
    			<fileset dir="build/lib" includes="*.jar"/>
    			<pathelement path="build/classes"/>
    		</path>
    
    		<target name="init">
    			<property name="xmlbeans.home" value="e:\osb_workspace\EmployeeXmlBeans\"/>    	
    			
    			<echo message="xmlbeans.home: ${xmlbeans.home}"/>
    
    			<!-- check for xbean.jar from binary distribution -->
    
    			<available
    				property="xmlbeans.lib"
    				value="${xmlbeans.home}/lib"
    				file="${xmlbeans.home}/lib/com.bea.core.xml.xmlbeans_2.1.0.0_2-5-1.jar" />
    
    			<fail message="Set XMLBEANS_HOME in your environment."
    				unless="xmlbeans.lib"/>
    
    			<echo message="xmlbeans.lib: ${xmlbeans.lib}"/>
    		
    			<path id="xmlbeans.path">
    				<fileset dir="${xmlbeans.lib}" includes="*.jar"/>
    			</path>
    
    			<taskdef name="xmlbean"
    				classname="org.apache.xmlbeans.impl.tool.XMLBean"
    				classpathref="xmlbeans.path"/>
    		</target>
    
    		<!-- ========================== clean ==== -->
    
    		<target name="clean">
    			<delete dir="build"/>
    		</target>
    
    		<!-- ========================== build ==== -->
    
    		<target name="build" depends="init,schemas.jar,Any.classes">
    		</target>
    
    		<target name="schemas.check">
    			<uptodate property="schemas.notRequired"
    				targetfile="build/lib/EmployeeXmlBeans.jar">
    				<srcfiles dir="schemas" includes="**/*.xsd"/>        	
    			</uptodate>
    		</target>
    
    		<target name="schemas.jar" depends="init,schemas.check"
    			unless="schemas.notRequired">
    			<mkdir dir="build/lib"/>
    			<xmlbean schema="schemas"
    				destfile="build/lib/EmployeeXmlBeans.jar"
    				srcgendir="src"
    				classpathref="xmlbeans.path"
    				source="1.5"
    				javasource="1.5"
    				debug="on"
    				/>
    		</target>
    
    		<target name="Any.classes" depends="init">
    			<mkdir dir="build/classes"/>
    
    			<javac srcdir="src"
    				destdir="build/classes"
    				classpathref="Any.path"
    				debug="on"
    				source="1.5"            
    				/>
    		</target>
    
    		<!-- ========================== run ==== -->
    
    		<target name="run" depends="init,build">
    			<echo message="============================== running Any"/>
    			<java
    				classname="org.apache.xmlbeans.samples.anytype.Any"
    				classpathref="Any.path"
    				fork="true">
    				<arg line="xml/any.xml"/>        	
    			</java>
    		</target>
    
    		<!-- ========================== test ==== -->
    
    		<target name="test" depends="init,build">
    			<echo message="============================== testing Any"/>
    			<java
    				classname="org.apache.xmlbeans.samples.anytype.AnyTest"
    				classpathref="Any.path"
    				fork="true">
    				<arg line="xml/any.xml"/>
    			</java>
    		</target>
    
    	</project>
    
    

    Run the ant build script. Based on the xml namespace of the Employee xsd object it will generate the same package structure for the java objects.
    Verify if it generated the next list of objects

    • nl.xenta.crm.employee.EmployeeDocument
    • nl.xenta.crm.employee.EmployeeType
    • nl.xenta.crm.employee.impl.EmployeeDocumentImpl
    • nl.xenta.crm.employee.impl.EmployeeDocumentImpl

    And if it also generated the file EmployeeXmlBeans.jar in the lib folder.

  4. Next we need to create a static method which will make use of the generated classes.
    Create the next class in the same project

    package nl.xenta.services;
    
    import org.apache.xmlbeans.XmlObject;
    
    import nl.xenta.crm.employee.EmployeeDocument;
    import nl.xenta.crm.employee.EmployeeType;
    import nl.xenta.entities.Employee;
    import nl.xenta.entities.Person;
    
    public class EmployeeService {
    
    	/**
    	 * Retrieve an employee record based on an employee id and return a XmlObject
    	 * 
    	 * @param empId
    	 * 
    	 * @return Employee XmlObject
    	 */
    	public static XmlObject retrieveEmployee(String empId) {
    		EmployeeDocument empDoc = EmployeeDocument.Factory.newInstance();
    		EmployeeType myEmp = empDoc.addNewEmployee();
    		myEmp.setAge(32);
    		myEmp.setFirstName("Eric");
    		myEmp.setLastName("Elzinga");
    			
    		return myEmp;		
    	}
    }
    
  5. Run the ant build again and this time copy the EmployeeXmlBeans.jar file to your OSB project and refresh the project in Eclipse.
  6. Add the java callout to your proxy service message flow and see the response
  7. Test the proxyservice and see the response in the logging.

    <BEA-000000> < [PipelinePairNode1, PipelinePairNode1_request, RetrieveEmployee, REQUEST] ### debug, logging my_employee_xml_object ###: <emp:employee xmlns:emp="http://xenta.nl/crm/employee">
      <emp:FirstName>Eric</emp:FirstName>
      <emp:LastName>Elzinga</emp:LastName>
      <emp:Age>32</emp:Age>
    </emp:employee>> 
    
    1. Now we’re able to retrieve data from the variable just by using the xpath expressions and re-use it in the rest of the message flow.

osb

Oracle Service Bus, Implementing Aggregator pattern by use of Split-Join

One of the patterns mentioned on the eai patterns site is the so called Aggregator pattern.

“Use a stateful filter, an Aggregator, to collect and store individual messages until a complete set of related messages has been received. Then, the Aggregator publishes a single message distilled from the individual messages”

We will be using this pattern in our next use case.

Use case

On the Oracle Service Bus we will implement the EmployeeService with an operation called ‘getEmployee’.
When we call this operation and supply an input parameters of the EmployeeNumber, we want to receive the next set of information

  • EmployeeDetails
  • AddressDetails
  • ContactDetails

In a real life scenario we could have the next situation

On the Oracle Service Bus we want to supply our clients 1 interface to be able to retrieve Employee information. The interface definition will define Employee details, addresses and contact details.

The process will receive the Employee Number, and by use of parallel invocation it will :

  • send a request to system1 which will supply us the Employee details
  • send a request to system2 which will suppy us the Employee addresses
  • send a request to system3 which will supply us the Employee contact details

Every system invocation will be a synchronous call and will get a response back from every one of them.
After having received the last of the 3 responses the parallel invocation is done. In the process flow we now need to aggregate the responses and transform these into one response which will get routed back to the client caller.

The client caller will not know what backend systems will get invoked to retrieve data. It will only receive one message response according to our defined interface on the service bus.

Enough talk, let’s see what we need in the Oracle Service Bus to implement this.

Backend systems

In a real world situation we could have 3 different backend systems which will all supply diffent parts of the Employee data object. For our case we will use just 1 webservice with different operations which will get invoked as different services.
Create a new Webservice project in Eclipse and add a new webservice to see.

package nl.xenta.services;

import nl.xenta.entities.Address;
import nl.xenta.entities.ContactDetail;
import nl.xenta.entities.Employee;

public interface EmployeeService {

	public Employee getEmployeeDetails(String employeeNumber);

	public Address getEmployeeAddress(String employeeNumber);

	public ContactDetail getContactDetail(String employeeNumber);

}
package nl.xenta.services;

import javax.jws.*;

import nl.xenta.entities.Address;
import nl.xenta.entities.Employee;
import nl.xenta.entities.ContactDetail;

@WebService
public class EmployeeServiceImpl implements EmployeeService {

	/* (non-Javadoc)
	 * @see nl.xenta.services.EmployeeService#getEmployeeDetails(java.lang.String)
	 */
	@WebMethod
	public Employee getEmployeeDetails(@WebParam(name="employeeNumber") String employeeNumber) {
		Employee emp = new Employee();
		emp.setFirstname("Eric");
		emp.setLastname("Elzinga");
		emp.setId(100);
		
		return emp;
	}
	
	/* (non-Javadoc)
	 * @see nl.xenta.services.EmployeeService#getEmployeeAddress(java.lang.String)
	 */
	@WebMethod
	public Address getEmployeeAddress(@WebParam(name="employeeNumber") String employeeNumber) {
		Address address = new Address();
		address.setCity("Utrecht");
		address.setCountry("The Netherlands");
		address.setPostalCode("1413JK");
		
		return address;
	}
	
	/* (non-Javadoc)
	 * @see nl.xenta.services.EmployeeService#getContactDetail(java.lang.String)
	 */
	@WebMethod
	public ContactDetail getContactDetail(@WebParam(name="employeeNumber") String employeeNumber) {		
		ContactDetail contact = new ContactDetail();
		contact.setType("mobile");
		contact.setValue("+31(6)24562772");		
				
		return contact;		
	}	
}

package nl.xenta.entities;

public class Address {
	
	private String street;
	private String postalCode;
	private String city;
	private String country;
	
	public String getStreet() {
		return street;
	}
	public void setStreet(String street) {
		this.street = street;
	}
	public String getPostalCode() {
		return postalCode;
	}
	public void setPostalCode(String postalCode) {
		this.postalCode = postalCode;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public String getCountry() {
		return country;
	}
	public void setCountry(String country) {
		this.country = country;
	}
}
package nl.xenta.entities;

public class ContactDetail {
	
	String type;
	String value;
	public String getType() {
		return type;
	}
	public void setType(String type) {
		this.type = type;
	}
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
}
package nl.xenta.entities;

public class Employee {
	
	private int id;
	private String firstname;
	private String lastname;
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getFirstname() {
		return firstname;
	}
	public void setFirstname(String firstname) {
		this.firstname = firstname;
	}
	public String getLastname() {
		return lastname;
	}
	public void setLastname(String lastname) {
		this.lastname = lastname;
	}
}

Deploy the service
The simulated backend systems are ready to supply data.

Oracle Service Bus resources

We need to next list of resources in the Oracle Service Bus to be able to implement the process.

  • wsdl + xsd of the deployed EmployeeService java webservice
  • business services for every third party service
  • split-join for the aggregation
  • business service representing the split-join
  • proxy service which routes to the split-join business service

Wsdl and xsd

Import the wsdl from the wsdl endpoint shown in the Weblogic Console

Business services for every third party service

Since we have just 1 webservice representing all the third parties we don’t really need to create separate business services for every party. To simulate the real scenario we still create 3 separate business services, all based on the same wsdl, but in the routing we will just use different operations.
So create the next set of business services all based on the same EmployeeService wsdl (which we imported in the step before).

  • AddressDetails.biz
  • ContactDetails.biz
  • EmployeeDetails.biz

Split-join

Create a new wsdl for the interface of the split-join. This wsdl will only represent the getEmployee operation. Name the wsdl CRM_EmployeeService.wsdl.

<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is Oracle JAX-WS 2.1.5. --><!-- Generated by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is Oracle JAX-WS 2.1.5. --><definitions name="EmployeeServiceService" targetNamespace="http://services.xenta.nl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://services.xenta.nl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/">
	<types>
		<xsd:schema>
			<xsd:import namespace="http://services.xenta.nl/" schemaLocation="EmployeeService.xsd"/>
		</xsd:schema>
	</types>
	<message name="getEmployee">
		<part name="parameters" element="tns:getEmployee"/>
	</message>
	<message name="getEmployeeResponse">
		<part name="parameters" element="tns:getEmployeeResponse"/>
	</message>
	<portType name="CRM_EmployeeService">
		<operation name="getEmployee">
			<input message="tns:getEmployee"/>
			<output message="tns:getEmployeeResponse"/>
		</operation>
	</portType>
	<binding name="EmployeeServicePortBinding" type="tns:CRM_EmployeeService">
		<soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
		<operation name="getEmployee">
			<soap:operation soapAction=""/>
			<input>
				<soap:body use="literal"/>
			</input>
			<output>
				<soap:body use="literal"/>
			</output>
		</operation>
	</binding>
	<service name="EmployeeServiceService">
		<port name="EmployeeServicePort" binding="tns:EmployeeServicePortBinding">
			<soap:address location="http://192.168.178.28:7001/EmployeeService/EmployeeServiceService"/>
		</port>
	</service>
</definitions>
<?xml version="1.0" encoding="UTF-8"?>
<!-- Published by JAX-WS RI at http://jax-ws.dev.java.net. RI's version is Oracle JAX-WS 2.1.5. -->
<xs:schema xmlns:tns="http://services.xenta.nl/" xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://services.xenta.nl/" version="1.0">
	<xs:element name="getEmployee" type="tns:getEmployee"/>
	<xs:element name="getEmployeeResponse" type="tns:getEmployeeResponse"/>
	<xs:complexType name="getEmployee">
		<xs:sequence>
			<xs:element name="employeeNumber" type="xs:string" minOccurs="0"/>
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="getEmployeeResponse">
		<xs:sequence>
			<xs:element name="EmployeeDetails" type="tns:employeeDetailType" minOccurs="0"/>
			<xs:element name="AddressDetails" type="tns:contactDetailType" minOccurs="0"/>
			<xs:element name="ContactDetails" type="tns:addressDetailType" minOccurs="0"/>
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="contactDetailType">
		<xs:sequence>
			<xs:element name="type" type="xs:string" minOccurs="0"/>
			<xs:element name="value" type="xs:string" minOccurs="0"/>
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="employeeDetailType">
		<xs:sequence>
			<xs:element name="firstname" type="xs:string" minOccurs="0"/>
			<xs:element name="id" type="xs:int"/>
			<xs:element name="lastname" type="xs:string" minOccurs="0"/>
		</xs:sequence>
	</xs:complexType>
	<xs:complexType name="addressDetailType">
		<xs:sequence>
			<xs:element name="city" type="xs:string" minOccurs="0"/>
			<xs:element name="country" type="xs:string" minOccurs="0"/>
			<xs:element name="postalCode" type="xs:string" minOccurs="0"/>
			<xs:element name="street" type="xs:string" minOccurs="0"/>
		</xs:sequence>
	</xs:complexType>
</xs:schema>

Create a new split join (File | New | Split-Join) and name it EmployeeSplitJoin.

By default it will generate for us the variables request and response.

Add a Parallel activity between Receive and Reply.
Add an extra Branch to the Parallel activity.
In every Scope and a Invoke Service activity.
Select the first Invoke Service in the first Scope and configure it.
On the Operation tab, browse to the first business service, AddressDetails.

On the Input Variable tab, select for Message Variable the option Create Message Variable.

Name the variable EmployeeAddressRequest and define it as Global Variable

Do the same for the Output Variable tab and name the variable EmployeeAddressResponse.

In every Scope add an assign before every Invoke Service activity.

With these assigns we’re mapping the inputparameter of our process (employeeNumber) to the input of our business service (backend service).

Repeat these steps (add scope, add assign, add invoke service, configure input/output of invoke service) for every invocation of our business services.
We should end up with the next set of branches.

The parallel invocation of our backend services is ready. Now we need to aggregate the responses of all the services. Create a new xquery transformation which will receive 3 inputparameters, one for every response of our backend service. The result of the transformation will be a message according to our proxy service interface (getEmployee).


After the Parallel activity add an Assign. Click the expression and go to the XQuery Resources tab and browse to the ServicesToAggregatedResponse xquery. Bind all the input parameters as defined in the image below.

For the Variable select response.parameters.

Our split-join part of the process is done. The process flow should look a bit like this :

To be able the call the split-join flow we need to generate a business out of it. Right click on the EmployeeSplitJoin.flow and go to File | Oracle Service Bus | Generate Business Service, name it EmployeeSplitJoin.

ProxyService

Create a new http soap proxy service based on the CRM_EmployeeService wsdl. In the proxyservice route to the ‘EmployeeSplitJoin’ business service. Since the interface of our split-join is the same as our proxy service (same wsdl) we can just use the passthrough, no transformation is needed.
Deploy the project and and test the service

Conclusion

Instead of using the split-join we can also use several service call outs in our process. Downside on this approach is all the invokes will be waiting on each other to come back with response (sequential). With the split-join approach we can parallel invoke all the services an aggregate the results. In case of services which need to give a low response time and still need to retrieve data from multiple backend systems we can’t model the flow with sequential invocations, split-join would then be an approach to take.

Besides that static split-join i used for my case we can also use the dynamic apporach in which we loop over reoccuring elements in the payload, process them parallel an aggregate the results.
Edwin showed this approach in his blog.

download : OracleServiceBusAggregator

open source

JAXB and how to work around duplicate variables

For our current adf project we’re generating webservice proxy clients against the wsdls of our OSB services.
In one of the services we had the next xsd construction :

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
	<xs:complexType name="EmployeeType">
		<xs:annotation>
			<xs:documentation xml:lang="nl">XML Represenation of the Employee domain object</xs:documentation>
		</xs:annotation>
		<xs:sequence>
			<xs:element name="id" type="xs:int" minOccurs="0">
				<xs:annotation>
					<xs:appinfo>
						<jxb:property name="idElement" xmlns:jxb="http://java.sun.com/xml/ns/jaxb"/>
					</xs:appinfo>
				</xs:annotation>			
			</xs:element>
			<xs:element name="firstname" type="xs:string"/>
			<xs:element name="lastname" type="xs:string"/>
			<xs:element name="birthdate" type="xs:date"/>
		</xs:sequence>
		<xs:attribute name="id" type="xs:int"/>
	</xs:complexType>
</xs:schema>

The object contains both an id-element and an id-attribute.
When trying to generate the Webservice proxy against the wsdl containing this definition, JDeveloper will generate the next error :
Error creating model from wsdl “file:/EmployeeService.wsdl”: The following location is relevant to the above errorProperty “Id” is already defined. Use to resolve this conflict.
JAXB tries to generate the java representation of this schema and will (try to) generate a java class in which it will generate 2 variables with the name of ‘id’.

The wizard also comes with the solution on how we could implement the fix for this.
Change the schema to :

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified" <b>xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0"</b>>
	<xs:complexType name="EmployeeType">
		<xs:annotation>
			<xs:documentation xml:lang="nl">XML Represenation of the Employee domain object</xs:documentation>
		</xs:annotation>
		<xs:sequence>
			<xs:element name="id" type="xs:int" minOccurs="0">
				<xs:annotation><b>
					<xs:appinfo>
						<jaxb:property name="idElement"/>
					</xs:appinfo>
					</b>
				</xs:annotation>			
			</xs:element>
			<xs:element name="firstname" type="xs:string"/>
			<xs:element name="lastname" type="xs:string"/>
			<xs:element name="birthdate" type="xs:date"/>
		</xs:sequence>
		<xs:attribute name="id" type="xs:int"/>
	</xs:complexType>
</xs:schema>

We added a few things.

  • add xmlns:jaxb=”http://java.sun.com/xml/ns/jaxb” jaxb:version=”2.0 to the schema-tag
  • add the xs:appinfo-element (and childs) to the “xs:element name=”id” element

or make use of an external binding file

<jxb:bindings version="1.0" 
  xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema">
		<jxb:bindings node=".//xs:element[@name='id']">
			<jxb:property name="idElement"/>
		</jxb:bindings>
</jxb:bindings>

With this property we can force jaxb to generate a variable idElement instead of the id-element. So no duplicates on variable-name will get generated.
This will result in the next java code fragment :

public class EmployeeType {

    @XmlElement(name = "id")
    protected BigInteger idElement;
    protected String firstname;
	protected String lastname;
	protected XMLGregorianCalendar birthdate;
    @XmlAttribute
    protected BigInteger id;

No duplicates in variables, since it generated idElement and id.

osb

Oracle Service Bus, how to verify Result Caching is active

Oracle Service Bus has a feature now for a while which gives us the option to switch on Result Caching on services.
Result Caching is based on Oracle Coherence, an in-memory data grid.

Basically what it does is cache the results from the calls to the business services. Which means on a second call to the service, OSB will first verify if the data, identified by a xpath-expression is in the cache. If it is, i will be retrieved from the cache, if it isn’t the call to the physical endpoint of the service will be made.

To be able to identify the data in the cache you need to configure the result caching on the business service, add the identifying ‘Cache Token Expression (XPath)’ and configure the expiration of the data item in the cache. This one can be handled by the default of the OSB, based on a duration or based on a XPath expression on the request/response message.
For a good overview read this part of the Administrators Guide.

Preparation

For this scenario we re-used the almighty Hello World Webservice again.

  1. imported the wsdl + xsd resources in your osb project
  2. Create a new http business service based on the wsdl
  3. Create a new proxy service based on the business service

Our testscenario is ready, let’s get on.

To be able to verify if the result cache is getting used or not we need to enable Monitoring on our proxy and business service.
Either open them in the plain text editor and look for

    <ser:monitoring isEnabled="true">
      <ser:aggregationInterval>10</ser:aggregationInterval>
    </ser:monitoring>

Switch isEnabled to true.
Or enable the monitoring after deployment in the SBConsole.

Deploy the service.

By default we haven’t enabled the Result Cache. So when we would call the proxy service it will passthrough to the business service and do the ‘real’ call to the webservice.
When we repeat this, every time again, the proxy service will just do the ‘real’ call to the webservice over and over again.

Let’s setup a testcase in SoapUI to do a little loadtest against the proxy service interface

SoapUI

Create a new SoapUI project, based on the wsdl endpoint of our OSB proxy service. Enable the creating of the TestSuite too.

Create a new TestSuite and enable the ‘Generate LoadTest’ option.

Double click the LoadTest 1, and check a few settings.

  • Threads => 1
  • Limit => 20 Total Runs

Our simple loadtest is ready. Based on 1 thread it will fire off 20 requests to our proxy service which eventually will invoke our Hello World business service.

Oracle Service Bus service statistics.
By enabling the Monitoring on our services Oracle Service Bus will collect and and gives us a Statistics overview in the console of the service.
Go to the Service Bus Console > Operations. Select the ‘Service Health’ tab at the top.
By default it will look a bit like this :

Testcase1

Go back to SoapUI and change the request payload of our sayHello teststep.

Start the loadtest

.. and the results of the loadtest, 20 calls to the proxy service.

Now go back to the SBConsole and look at the statistics again.

Both the proxy service and the business service received 20 messages, like we expected since we haven’t done anything yet with result caching.

Testcase2

Enabling Result Caching.
Go to the SBConsole > Operations > Global Settings and enable Result Caching

We can enable the Result Caching on the business service either in Eclipse or in the Console.
Since we need to add some XPath expressions it’s easier to do it in Eclipse itself.
Open the business service and go to the ‘Message Handling’ tab.

  1. Enable Result Caching
  2. Add a ‘Cache Token Expression’ (used to see if the data is already in the cache)
  3. And optional add an Expiration Time

By enabling this configuration we setup the next situation.
Result Caching is active, when ever a request arrives through a proxy service to the business service result caching will get triggered. It retrieves that data by use of the XPath expression and check if it’s already or still availabe in the cache.
If the data isn’t available in the cache, the data will get stored in the cache and the real call to the webservice will be done.
If the data is available in the cache, the data will get retrieved from the cache and there won’t be any call to the webservice.

Eventually the retrieved data will be returned to the response pipe of the proxy service, back to the client caller.

Deploy the osb project and go back the SBConsole, to the Statistics.
First we need to reset the statistics to see the difference on the numbers between the situation in which we didn’t use the result caching.

Go back to the SoapUI project and start the loadtest again.

And for the last time go back the SBConsole to the statistics.

Again 20 messages arrived at the proxy service. On the first call the data won’t be in the cache so the ‘real’ call to the webservice will be done.
The next call will contain the same message payload (since we’re using the same message in our SoapUI test), so the XPath expression will evaluate to true, which means the data can be retrieved from the cache. And this continues till message #20.

So eventually from the 20 calls we made to the proxy service, only 1 will really do the webservice call at the backend, and the other 19 calls will retrieve data from the cache.

I hope it’s a bit clear now how the result caching works in the Oracle Service Bus, how to configure it and eventually how to be able to see if the cache is really active.

Uncategorized, weblogic

Weblogic, QBrowser and topics

Besides using the Weblogic Console to add subscribers (durable) to our topics we can also use QBrowser to browse queues and topics on your Weblogic Server.
Download the tool here, configurate the .bat/.sh so all the correct versions of the jar are included or create the Weblogic Full Client (http://download.oracle.com/docs/cd/E12840_01/wls/docs103/client/t3.html).

Connect to your Weblogic instance.

You will get an overview of all your queues and topic, and also our MyTopic.

Click on the topic to add a subscription to the topic.

We haven’t created a Local Store yet, so select the default ‘Not Copy to local store’, we will do that later on.
Create a message on topic by your testclient (or in my case, my OSB process) and watch QBrowser again, to see the message coming in.

So we’re able to add a subscriber on the topic to read the messages.
When we go back to the Weblogic Console and check the Durable Durable Subscribers tab, we still see only 1 subscriber, the one we created in this blog.
QBrowser created a non-durable subscriber for us on the topic.

Let’s do a little test.

Unsubscribe from the topic

Send again the message from the client and click ‘resume subscribe’.
The just sended message isn’t stored in the topic. This because we used a non-durable subscriber on the topic, so in case of a disconnect the messages won’t get persisted.

Local Store

QBrowser also gives the option to define ‘Local Store’.
Create a new Local Store by clicking on it

Add the Local Store to the topic

Trigger your client again (or in my case the OSB process) to send a new message.
The message arrives again the QBrowser in the list of messages of the topic and on filesystem QBrowser stored a new zip-archive at the defined location of the Local Store (d:\tmp\temp_store\ID323778.1308261513812.0_TextMessage.zip in my case)

The zip contains the next files:

JMSHeaders.txt

"JMSMessageID",String=<@begin-@string@>ID:<323778.1308261513812.0><@end-@string@>
"JMSDestination",String=<@begin-@string@>MyTopic : Topic<@end-@string@>
"JMSReplyTo",String=<@begin-@string@><@end-@string@>
"JMSCorrelationID",String=<@begin-@string@>null<@end-@string@>
"JMSDeliverMode",Int="2"
"JMSPriority",Int="4"
"JMSExpiration",Long="0"
"JMSType",String=<@begin-@string@>null<@end-@string@>
"JMSRedelivered",Boolean="false"
"JMSTimestamp",Long="1308261513812"

textbodysize

70

TextMessageBody.txt

<?xml version="1.0" encoding="UTF-8"?>
<test>my second payload</test>

UserProperties.txt

"JMSXDeliveryCount",Int="1"

With this functionality you will be able to store all the incoming messages on the topic on filesystem.

So far the short overview of the possibilities in QBrowser when using topics.

weblogic

Weblogic, topics and (non)-durable subscribers

For one of my testcases i implemented a simple process in the Oracle Service Bus which stores messages on a Weblogic topic.
This blog will not contain any rocket science, just a quick overview on how to deal with topics and subscribers in Weblogic.

In case of storing messages on Weblogic queues you can just browse in the Weblogic Console and look into the messages

To be able to look at the message available in a topic we need to first subscribe to the topic.

  1. Create a new JMS Server
  2. Create a new JMS Module
  3. Create a new Topic (MyTopic) in the new JMS Module
  4. Create a new Durable Subscriber on the topic
    Go to the Topic > Monitoring > Durable Subscribers

    By default there won’t be any subscribers available for our just created topic.
    Create a new Durable Subscriber (MyTopicSubscriber)

    No messages available in the topic.

  5. Send messages to the topic
    For this i created a simple OSB service which stores the messages in the topic (jms transport, endpoint jms://localhost:7001/weblogic.jms.XAConnectionFactory/MyTopic)
    Trigger the process and use some test payload data
  6. Check the Durable Subscriber overview again

    Click show messages to view the content

    Durable topics are topics which persistence every incoming message for a durable consumer. Each durable consumer will receive his own copy of the mesage.

    Situation 1:
    We add a non-durable consumer on the topic.
    We send 10 messages to the topic, at message 5, we stop the non-durable subscriber and we continue sending the message till the last mesage.
    We start the non-durable subscriber again. Now it will not receive message 5 till 10 because it isn’t durable. So the messages won’t be received

    Situation 2:
    We add a durable subscriber on the topic.
    We send 10 messages to the topic, at message 5, we stop the durable subscriber and we continue sending the message till the last mesage.
    We start the non-durable consumer again. Now it will receive message all the persisted messages and the new incoming messages again.

    See this clear explanation on the Active MQ site about Durable queues and topic.

    So the JMS Provider itself knows when using a durable topic subscription what its subscriber are identified by combination of ClientID and the durable subscriber name.
    It knows what messages got delivered and which aren’t. When the subscriber goes down the JMS providers knows which messages to keep available for the subscriber for delivery. The subscriber connects again and receives those messages.
    In case of a non-durable subscriber those messages would have been lost.

books

Book Review : WS-BPEL 2.0 for SOA Composite Applications with Oracle SOA Suite 11g

Already read this book a while ago, but never had the time to do a short review on it.
After reading ‘Oracle SOA Suite 11g R1 Developer’s Guide’ i was still hoping to read some new refreshing information.

BPEL 2.0 is fairly new for me. Read about the specs, but never had much of a chance to get in touch with it for development purpose.
The book mentions most of the “what’s new changes” spread around in several chapters in the book. I would rather have some sort of short overview in the book what mentions me what’s new in this version of BPEL, how did we do it in BPEL 1.0. Like this the reader will have a better overview of what BPEL 2.0 will give him for extra functionality.

The ‘Oracle SOA Suite 11g R1 Developer’s Guide‘ book was more of a global overview book with not a lot of in-dept information.
From this point of view this book gives use more in-dept information and more ‘advanced’ information about the possibilities of BPEL (1.0/2.0) in conjunction with the SOA Suite, so they’re both complementary.

Since i have a strong background both on OSB en SOA Suite, i’m always looking for some sort of best practice on what to model in SOA Suite and what to model in the OSB.
The authors added a nice chapter on the Oracle Service Bus and the use of the Oracle Registry. Too bad they didn’t add some extra information to the debat to decide where to technically implement which components of your business process. But i can imagine this would also be out of scope for this book.

To finish off the book the authors give us 2 chapters to show the possiblities the Oracle products give us to connect BPEL with BPMN.
Chapter 10 gives discusses the round-tripping of BPEL to BPMN and back by use of the BPA Suite product and the Oracle SOA Suite.
And chapter 11 shows us how to integrate the composite applications with BPMN processes by use of the BPM Suite. Again a well explained example, so the reader gets a good overview on the integration of the BPMN process into your composite.

Chapters

The first Chapter (Introduction to BPEL and SOA) gives us a overview of both concepts, which standards are available and are getting used in the products.
Chapter 2 (Service Composition with BPEL) starts with ‘beginners’ information about the available BPEL activities. The following chapters like (Advanced BPEL, BPEL Extensions, Entity Variables, Master Detail processes) will discuss the more advanced topics on BPEL (both activities defined by the standard and the oracle-specific implementations).
Chapter 8 (Monitoring BPEL Processes with BAM), chapter 9 (BPEL with Oracle Service BUs and Service Registry) and the chapters 10 (BPMN to BPEL Round-tripping with BPA Suite and SOA Suite) en 11 (Integration BPEL with BPMN using BPM Suite) all discuss the intergration with other products of the Oracle portfolio. All well explained and with examples. So for the reader it’s nice to see how easily one can integrate with the other products.

Overall it was a good read. It gave me a bit of advanced and in-dept information, good examples (easily to follow by just clicking what is mention in it).
Looking at the title of the book i would expect more of the BPEL 2.0 part. It doesn’t get much highlighted in the book, although a lot of the new specs are mention through the whole book, so you really need to read the specs to see what is changed in the 2.0 definitons.
Although i do just read the content of the ‘Appendix A’ on the Packt site (WS-BPEL 2.0 Syntax Reference), nice list of the available functions.
See this link.

A while back i also followed a 3day BPMN training on the Oracle BPMN Suite, so the BPMN chapters (especially the last one) were a nice rephrase on what we learned on the training.

Content

Table of Contents

  • Preface
  • Chapter 1: Introduction to BPEL and SOA
  • Chapter 2: Service Composition with BPEL
  • Chapter 3: Advanced BPEL
  • Chapter 4: Using BPEL with Oracle SOA Suite 11g
  • Chapter 5: BPEL Extensions, Dynamic Parallel Flow, Dynamic Partner Links, Notification Service, Java Embedding, and Fault Management Framework
  • Chapter 6: Entity Variables, Master and Detail Processes, Security, and Business Events in BPEL
  • Chapter 7: Human Interactions in BPEL
  • Chapter 8: Monitoring BPEL Processes with BAM
  • Chapter 9: BPEL with Oracle Service Bus and Service Registry
  • Chapter 10: BPMN to BPEL Round-tripping with BPA Suite and SOA Suite
  • Chapter 11: Integrating BPEL with BPMN using BPM Suite
  • Appendix A
  • Appendix B
  • Index

Product Details

  • Language : English
  • Paperback : 616 pages [ 235mm x 191mm ]
  • Release Date : September 2010
  • ISBN : 1847197949
  • ISBN 13 : 978-1-847197-94-8
  • Author(s) : Matjaz B. Juric, Marcel Krizevnik

weblogic

Oracle Weblogic, resetting datasources

In our OSB services we make a lot of use of jca database adapters calling stored procedures.
After changing the package structure in the database (adding new procedures) we get the next stacktrace (partly in Dutch)

Invoke JCA outbound service failed with application error, exception: com.bea.wli.sb.transports.jca.JCATransportException: oracle.tip.adapter.sa.api.JCABindingException: oracle.tip.adapter.sa.impl.fw.ext.org.collaxa.thirdparty.apache.wsif.WSIFException: servicebus:/WSDL/EmailService/BusinessService/retrieveMail/retrieveMail [ retrieveMail retrieveMail_ptt::retrieveMail (InputParameters,OutputParameters) ] - WSIF JCA Execute of operation 'retrieveMail' failed due to: Fout bij oproep opgeslagen procedure.
Fout bij een poging de EML.EMAIL.RETRIEVE_MAIL API voor te bereiden en uit te voeren.
Er is een fout opgetreden bij het voorbereiden en uitvoeren van de EML.EMAIL.RETRIEVE_MAIL API. Oorzaak: java.sql.SQLSyntaxErrorException: ORA-00902: Ongeldig gegevenstype.

; nested exception is: 
 BINDING.JCA-11811
Fout bij oproep opgeslagen procedure.
Fout bij een poging de EML.EMAIL.RETRIEVE_MAIL API voor te bereiden en uit te voeren.
Er is een fout opgetreden bij het voorbereiden en uitvoeren van de EML.EMAIL.RETRIEVE_MAIL API. Oorzaak: java.sql.SQLSyntaxErrorException: ORA-00902: Ongeldig gegevenstype.

Controleer of de API is gedefinieerd in de database en of de parameters overeenkomen met de handtekening van de API.  Deze uitzondering wordt niet als opnieuw te proberen beschouwd, blijkbaar wegens een fout in het model.  Als u de fout in plaats daarvan wilt classificeren als opnieuw te proberen, voegt u de eigenschap nonRetriableErrorCodes met waarde "-902" toe aan de implementatiedescriptor (dat wil zeggen weblogic-ra.xml).  Om automatisch een nieuwe poging te doen stelt u de volgende composite.xml-eigenschappen voor deze aanroep in: jca.retry.interval, jca.retry.count en jca.retry.backoff. Alle eigenschappen zijn gehele getallen.

com.bea.wli.sb.transports.jca.JCATransportException: oracle.tip.adapter.sa.api.JCABindingException: oracle.tip.adapter.sa.impl.fw.ext.org.collaxa.thirdparty.apache.wsif.WSIFException: servicebus:/WSDL/EmailService/BusinessService/retrieveMail/retrieveMail  [ retrieveMail_ptt::retrieveMail(InputParameters,OutputParameters) ] - WSIF JCA Execute of operation 'retrieveMail' failed due to: Fout bij oproep opgeslagen procedure.
Fout bij een poging de EML.EMAIL.RETRIEVE_MAIL API voor te bereiden en uit te voeren.
Er is een fout opgetreden bij het voorbereiden en uitvoeren van de EML.EMAIL.RETRIEVE_MAIL API. Oorzaak: java.sql.SQLSyntaxErrorException: ORA-00902: Ongeldig gegevenstype.

 at com.bea.wli.sb.transports.jca.binding.JCATransportOutboundOperationBindingServiceImpl.invoke(JCATransportOutboundOperationBindingServiceImpl.java:155)
 at com.bea.wli.sb.transports.jca.JCATransportEndpoint.sendRequestResponse(JCATransportEndpoint.java:209)
 at com.bea.wli.sb.transports.jca.JCATransportEndpoint.send(JCATransportEndpoint.java:170)
 at com.bea.wli.sb.transports.jca.JCATransportProvider.sendMessageAsync(JCATransportProvider.java:598)
.....

 at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:457)
 at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:405)
 at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:889)
 at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:476)
 at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:204)
 at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:540)
 at oracle.jdbc.driver.T4CCallableStatement.doOall8(T4CCallableStatement.java:213)
 at oracle.jdbc.driver.T4CCallableStatement.executeForRows(T4CCallableStatement.java:1075)
 at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1466)
 at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3752)
 at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3937)
 at oracle.jdbc.driver.OracleCallableStatement.execute(OracleCallableStatement.java:9259)
 at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1535)
 at weblogic.jdbc.wrapper.PreparedStatement.execute(PreparedStatement.java:99)
 at oracle.tip.adapter.db.sp.AbstractStoredProcedure.execute(AbstractStoredProcedure.java:123)
 ... 151 more

Edwin already blogged about how to refresh the datasources in Weblogic by use of wlst and ant.
If you want to refresh the datasource manually in the console do the next.

Go to the Weblogic Console > datasources and select your datasource.
Go to the tab ‘Control’, select the servers to which the datasource is targetted and click ‘Reset’.

Thanks go out to my colleague Arnaud for the tip.

weblogic

Weblogic jdbc resource out of sync

For some development task we added a jdbc resource needed for one of our business services which was based on the database adapter.
For a test we added environment settings for let’s say development1, but later on we needed to switch this setup to development2.
Easy task by just editting the jdbc resource setup in the console, change the settings and go (or restart the server and go).
But in both cases the resource kept pointing to the development1 environment.

The config for the jdbc resource is getting stored over here :

<ORACLE_MIDDLEWARE_HOME>/user_projects/domain/osb_domain/config/config.xml

Locate the ‘jdbc-system-resource’ tag for your jdbc resource

  <jdbc-system-resource>
    <name>myDS</name>
    <target>MyTarget</target>
    <descriptor-file-name>jdbc/myDS-5623-jdbc.xml</descriptor-file-name>
  </jdbc-system-resource>

Now navigate to the file mentioned in the descriptor-file-name tag. In here the credentials and connection info are getting stored.
This file was for some reason out of sync with the data showed in the Weblogic Console.

Delete the jdbc resource from the console, and see if the config.xml and the corresponding file in the jdbc directory are getting removed.
Re-add the jdbc resource in the console, and check the file again to see if the correct info is getting stored.

Or try the change the settings in the file itself and do a restart.

Page 3 of 1112345...10...Last »