Oracle Service Bus 11g, Using Custom Xpath functions

In the new Oracle Service Bus 11g, Oracle gives us new functionality for the use of custom xpath functions.
These functions we eventually can re-use in for example the xslt or xquery transformations.

For this we need :

  1. 1. XML Configuration file (osb-custom.xml)
  2. 2. Property file (optional, osb-custom.properties)
  3. 3. Custom Function Class (jar package)

All these files need to be stored at the next location

<OSB_HOME>/config/xpath-functions

1. XML Configuration file

Create a new XML configuration file. I made a copy of the default file, osb-built-in.xml, edit that one, and change the settings.

<?xml version="1.0" encoding="UTF-8"?>
<xpf:xpathFunctions xmlns:xpf="http://www.bea.com/wli/sb/xpath/config">
    <xpf:category id="%OSB_FUNCTIONS%">
        <xpf:function>
            <xpf:name>customConcat</xpf:name>
            <xpf:comment>%FUNC_CUSTOM_CONCAT_COMMENT%</xpf:comment>
            <xpf:namespaceURI>http://nl.iteye/osb/custom/functions/OsbUtils</xpf:namespaceURI>
            <xpf:className>nl.iteye.osb.custom.functions.OsbUtils</xpf:className>
            <xpf:method>java.lang.String customConcat(java.lang.String, java.lang.String)</xpf:method>
            <xpf:isDeterministic>false</xpf:isDeterministic>
            <xpf:scope>Pipeline</xpf:scope>
            <xpf:scope>SplitJoin</xpf:scope>
        </xpf:function>
    </xpf:category>
</xpf:xpathFunctions>

A few notes on this file.

  • category, the name of the category how it will appear in the IDE or Console
  • function:name,comments, the description of the function how it will appear in the IDE or Console
  • namespaceURI, the namespace which will be imported in for example the xquery to identify the custom function
  • className, the java implementation of our custom xpath function
  • method, the name of the method which we will be using for the implentation of the function
  • isDeterministic, A value of true or false declaring whether or not the function is deterministic, the XQuery standard recommends the function to be deterministic (see documentation for further information)
  • scope, i assume the scope of the OSB flow in which the function can be used

2. Property file

%OSB_FUNCTIONS%=Service Bus Functions
%FUNC_CUSTOM_CONCAT_COMMENT%=Returns the concat of the first and the second parameter

Not much in here,just a few placeholders for the descriptions

3. Custom Function Class

Create a new Java project in your favorite IDE. Create a new package and java class. For this demo i created a custom concat function which will concat parameter1 and parameter2 and return the result.

package nl.iteye.osb.custom.functions;       

public class OsbUtils {
    public OsbUtils() {
    }
    
    public static String customConcat(String firstParam, String secondParam) {
        return firstParam + " " + secondParam;
     }
}

The method needs to be defined as static.
Compile the code and create a jar archive and store this at the location mentioned in the top of the article.
After this we should have 3 extra files in this directory :

  • osb-custom.xml
  • osb-custom.properties
  • osb-custom.jar

Restart the server, so the Oracle Service Bus will load the custom classes we just created. Check the output of the console to see if don’t see any errors come by. Wrong configuration (wrong methodname,package, etc) will end up with a little stacktrace in here.

Testing

To test the custom xpath function, create a new Oracle Service Bus project in Eclipse.

Add new XML Schema

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/NewXMLSchema" xmlns:tns="http://www.example.org/NewXMLSchema" elementFormDefault="qualified">
    <element name="Input" type="tns:InputType"></element>
    <element name="Output" type="string"></element>

    <complexType name="InputType">
    	<sequence>
    		<element name="Name1" type="string"></element>
    		<element name="Name2" type="string"></element>
    	</sequence>
    </complexType>
</schema>

Add new XQuery Transformation
In the list of expression functions we will see our custom function (customConcat)

(:: pragma bea:global-element-parameter parameter="$input1" element="ns0:Input" location="NewXMLSchema.xsd" ::)
(:: pragma bea:global-element-return element="ns0:Output" location="NewXMLSchema.xsd" ::)

declare namespace ns0 = "http://www.example.org/NewXMLSchema";
declare namespace xf = "http://tempuri.org/OSB%20Project%201/InputToOutput/";

declare function xf:InputToOutput($input1 as element(ns0:Input))
    as element(ns0:Output) {
        <ns0:Output>{ osbK3:customConcat($input1/ns0:Name1,$input1/ns0:Name2) }</ns0:Output>
};

declare variable $input1 as element(ns0:Input) external;

xf:InputToOutput($input1)

In the transformation i will map both the Name1 and Name2 to the input of the custom function, which will return the concat of both in output.

The easiest way to test the result is by running the XQuery on a connected server. Right mouseclick on the .xq file > Run As > Run on Server
The Oracle Service Bus Test Console will pop up.
Fill in the input data and execute.

And the result

Advertisements

Oracle Service Bus 11g, installation

Besides the new patchset for Oracle SOA Suite 11g, Oracle also released the new Oracle Service Bus 11g.
See Edwin his list for the new features.

Download the installer and unpack the files and move the files from Disk2 to Disk1, otherwise the installation won’t complete.





Select the middleware home and we will create the new Oracle Service Bus Home in there.

Configuration Wizard

See this (2.10 Oracle Service Bus Domain Configuration Scenarios) overview to decide what the best infrastructure scenario is for your case. Since it’s my development machine i choose to reuse the SOA Suite domain to extend it with the Oracle Service Bus components. For this i won’t need an extra Weblogic domain.

I selected the Single Domain, since it will be installed on my dev machine. For production Oracle advises to use the All Domain Topologies. In that case Oracle Service Bus will be running in a seperate managed server (just like soa_server1 and bam_server1).

By default the credentials for the SOA Suite Components are already configurated correctly, we only need to change the ‘OSB JMS Reporting Provider’ component.

And we’re done.

Oracle Service Bus Console
http://localhost:7001/sbconsole (new Weblogic login screen)

See also Edwin his blog on the new WSM functionality (policies).

EAI/Oracle Service Bus testing with Citrus Framework, part2

Before reading on, read my first article on the Citrus Framework.
In this second part of testing by use of the Citrus Framework i want to test a new scenario which was part of the middleware of my last customer.

Scenario

Some third party application stores messages on the Weblogic JMS queue in the middleware. My Oracle Service Bus project picks up the messages, does some transformation/enrichment/etc, and stores the data on the file share.
Storing the file on the filesystem is the trigger for starting a new process, but this will be out of scope for this article.

What we want to test is the blackbox which runs in the middleware. I want to be able to store the xml data file (fact 1), in the jms queue, and eventually read the file from filesystem (fact 2) and see if the response
matches my expected response defined in the Citrus Framework.

Requirements

See the requirements of the first article, what we need again are the inbound queues and the used connection factory. In the middleware we need a Oracle Service Bus flow.

Oracle Service Bus

The Oracle Service Bus project i want to test is a real basic one with only 2 resources.

  1. jms_ps – proxy service with service type ‘Any XML Service’ and jms protocol
    The flow consists of only a simple route action whichs routes the incoming message of the jms queue 1 on 1 to business service which stores the content on filesystem.
  2. file_bs – business service which stores the file on my local file system

Citrus configuration

First we need to config src/citrus/resources/citrus-context.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:citrus="http://www.citrusframework.org/schema/config"
       xmlns:citrus-ws="http://www.citrusframework.org/schema/ws/config"
       xmlns:citrus-http="http://www.citrusframework.org/schema/http/config"
       xmlns:context="http://www.springframework.org/schema/context"
	   xmlns:si="http://www.springframework.org/schema/integration"
	   xmlns:file="http://www.springframework.org/schema/integration/file"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	   http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
	   http://www.springframework.org/schema/integration/file http://www.springframework.org/schema/integration/file/spring-integration-file-2.0.xsd
       http://www.citrusframework.org/schema/config http://www.citrusframework.org/schema/config/citrus-config-1.1.xsd">

	<!-- Common settings -->
	<bean id="schemaRepository" class="com.consol.citrus.xml.XsdSchemaRepository">
		<property name="schemas">
			<list>
				<bean class="org.springframework.xml.xsd.SimpleXsdSchema">
					<property name="xsd" value="classpath:com/consol/citrus/samples/greeting/schema/greeting.xsd"/>
				</bean>
			</list>
		</property>
	</bean>	   

	<bean class="com.consol.citrus.variable.GlobalVariables">
		<property name="variables">
			<map>
				<entry key="project.name" value="Citrus Greeting sample"/>
			</map>
		</property>
	</bean>	

	<bean class="com.consol.citrus.aop.StoreMessageInterceptorAspect"/>	   

	<bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate">
		<property name="environment">
			<props>
				<prop key="java.naming.factory.initial">weblogic.jndi.WLInitialContextFactory</prop>
				<prop key="java.naming.provider.url">t3://localhost:7001</prop>
			</props>
		</property>
	</bean>	

	<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiTemplate">
			<ref bean="jndiTemplate" />
		</property>
		<property name="jndiName">
			<value>TestCF</value>
		</property>
	</bean>	

	<bean id="jmsDestinationResolver" class="org.springframework.jms.support.destination.JndiDestinationResolver">
		<property name="jndiTemplate">
			<ref bean="jndiTemplate" />
		</property>
		<property name="cache">
			<value>true</value>
		</property>
	</bean>

	<bean id="sendGreeting" class="com.consol.citrus.jms.JmsMessageSender">
		<property name="destinationName" value="citrus_queue_in"/>
		<property name="connectionFactory">
			<ref bean="connectionFactory" />
		</property>
		<property name="destinationResolver">
			<ref bean="jmsDestinationResolver" />
		</property>
	</bean>

	<file:inbound-channel-adapter id="fileAdapter" directory="file://e:/temp/files_out" channel="fileInputChannel">
		<si:poller max-messages-per-poll="100">
			<si:interval-trigger time-unit="MILLISECONDS" interval="1" />
		</si:poller>
	</file:inbound-channel-adapter>
	
	<si:channel id="fileInputChannel">
		<si:queue capacity="25"/>
		<si:interceptors>
			<bean class="org.springframework.integration.transformer.MessageTransformingChannelInterceptor">
				<constructor-arg>
					<bean class="org.springframework.integration.file.transformer.FileToStringTransformer"/>
				</constructor-arg>
			</bean>
		</si:interceptors>
	</si:channel>

	<citrus:message-channel-receiver id="fileInputChannelReceiver"
                                    channel="fileInputChannel"
                                    receive-timeout="5000"/>	

	<!-- TestSuite definition -->
	<bean name="citrus-samples-greeting" class="com.consol.citrus.TestSuite"/>
</beans>

Again we use the ‘sendGreeting’ bean to send the message to the jms queue. For Citrus to be able to do his actions on the messages he needs to get the message from a MessageChannel.
When the file gets stored on filesystem the ‘inbound-channel-adapter’ will poll for the file and puts it on the ‘fileInputChannel’ messagechannel, eventually citrus will pick up the message from this channel.

Documentation of Citrus doesn’t give you any hints on how to integrate the file-protocol. Since Citrus makes use of Spring Integration we can easily adopt the file support from this framework and add it to the Citrus context file.
The following changes are needed on the citrus-context.xml file

  • Addition of the integration namespaces/schemalocations
  • Addition of the (file) inbound-channel-adapter
  • Addition of the channel for the file
  • Citrus Message channel polling on the file input channel
  • Copy the Spring Integration File jar to the libs folder. I used ‘org.springframework.integration.file-1.0.3.RELEASE.jar’ from the Spring Integration framework

A few notes on the fileInputChannel.
If we would just add

<si:channel id="fileInputChannel">

, Citrus will give us the next error :

[citrus] Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'fileInputChannelReceiver': Initialization of bean failed; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert property value of type [org.springframework.integration.channel.DirectChannel] to required type 
[org.springframework.integration.channel.PollableChannel] for property 'channel'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [org.springframework.integration.channel.DirectChannel] 
to required type [org.springframework.integration.channel.PollableChannel] for property 'channel': no matching editors or conversion strategy found

So Citrus expects some other type of channel. Adding

<si:queue capacity="25"/>

, will fix this problem.

Running the sample again will give us the next error :

   [citrus] Caused by: org.w3c.dom.ls.LSException: Content is not allowed in prolog.
   [citrus]     at org.apache.xerces.parsers.DOMParserImpl.parse(Unknown Source)
   [citrus]     at com.consol.citrus.util.XMLUtils.parseMessagePayload(XMLUtils.java:333)
   [citrus]     at com.consol.citrus.validation.DefaultXMLMessageValidator.validateXMLSchema(DefaultXMLMessageValidator.java:300)
   [citrus]     at com.consol.citrus.validation.DefaultXMLMessageValidator.validateMessage(DefaultXMLMessageValidator.java:98)
   [citrus]     ... 54 more
   [citrus] Caused by: ::::1:1:0:Content is not allowed in prolog.
   [citrus]     at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
   [citrus]     at org.apache.xerces.impl.XMLErrorReporter.reportError(Unknown Source)
   [citrus]     at org.apache.xerces.impl.XMLScanner.reportFatalError(Unknown Source)
   [citrus]     at org.apache.xerces.impl.XMLDocumentScannerImpl$PrologDispatcher.dispatch(Unknown Source)
   [citrus]     at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
   [citrus]     at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
   [citrus]     at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
   [citrus]     at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
   [citrus]     ... 58 more   

The inbound-adapter passes on the file 1 on 1 to the file channel. Since the channel expects a string instead of a file object we need to transform this file-object to a string-object. Spring Framework gives us a default Transformer for this.
To intercept the File-object before it gets stored on the MessageChannel we can add an ‘interceptor’, as argument to the call of the interceptor we define the ‘FileToStringTransformer’.

Secondly we need to config src/citrus/tests/com/consol/citrus/samples/greeting/jms/GreetingJmsTest.xml

<?xml version="1.0" encoding="UTF-8"?>
<spring:beans xmlns="http://www.citrusframework.org/schema/testcase" xmlns:spring="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.citrusframework.org/schema/testcase http://www.citrusframework.org/schema/testcase/citrus-testcase.xsd">
	<testcase name="GreetingJmsTest">
		<meta-info>
			<author>Eric Elzinga</author>
			<creationdate>2010-03-25</creationdate>
			<status>FINAL</status>
			<last-updated-by>Eric Elzinga</last-updated-by>
			<last-updated-on>2010-03-28T00:00:00</last-updated-on>
		</meta-info>

		<variables>
			<variable name="correlationId" value="citrus:randomNumber(10)"></variable>
			<variable name="user" value="Christoph"></variable>
		</variables>

		<actions>
			<send with="receiveGreeting">
			<message>
				<resource file="classpath:xmlData/greeting_request.xml" />
			</message>
			<header>
				<element name="Operation" value="sayHello"/>
				<element name="CorrelationId" value="${correlationId}"/>
			</header>
		</send>

		<receive with="fileAdapter">
		<selector>
			<value>CorrelationId = '${correlationId}'</value>
		</selector>
		<message>
		  <resource file="classpath:xmlData/greeting_response.xml" />
		  <ignore path="//tns:GreetingRequestMessage/tns:Text" />
		</message>
		<header>
			<element name="Operation" value="sayHello"/>
			<element name="CorrelationId" value="${correlationId}"/>
		</header>
	</receive>
</actions>
</testcase>
</spring:beans>

Only change in here compaired to part1 is the

<receive with="fileInputChannelReceiver">

Now run the test again and see if the framework matches the generated file on filesystem with the payload we configurated.
Since i don’t do any transformations in the middleware the request payload should match the response payload.

ant citrus.run.tests

..and see the results

   [citrus] 19047  INFO  port.LoggingReporter| TEST FINISHED: GreetingJmsTest
   [citrus] 19047  INFO  port.LoggingReporter| ------------------------------------------------------------------------
   [citrus] 19063  INFO  port.LoggingReporter| FINISH TESTSUITE citrus-samples-greeting
   [citrus] 19063  INFO  port.LoggingReporter| ------------------------------------------------------------------------
   [citrus] 19063  INFO  port.LoggingReporter| ________________________________________________________________________
   [citrus] 19063  INFO  port.LoggingReporter|
   [citrus] 19079  INFO  port.LoggingReporter| CITRUS TEST RESULTS
   [citrus] 19079  INFO  port.LoggingReporter|
   [citrus] 19079  INFO  port.LoggingReporter|  GreetingJmsTest ............................................... SUCCESS
   [citrus] 19079  INFO  port.LoggingReporter|
   [citrus] 19079  INFO  port.LoggingReporter| Total number of tests: 1
   [citrus] 19079  INFO  port.LoggingReporter| Skipped: 0 (0.0%)
   [citrus] 19079  INFO  port.LoggingReporter| Failed:  0 (0.0%)
   [citrus] 19079  INFO  port.LoggingReporter| Success: 1 (100.0%)

Conclusion

I hope this gave you good overview on how to implement integration tests with the Citrus Framework. For me it’s an ideal way to test my Oracle Service Bus flows.
How do you guys think about it ? Or do you use other frameworks for testing?

Oracle Service Bus, invoke asynchronous webservices

In this blog i will give a short overview on how to invoke asynchronous webservices from the Oracle Service Bus, and route the callback from the service back to some other endpoint (service) on the bus.
The flow we will create will look like this

Asynchronous webservice
To communicate from the Oracle Service Bus to an asynchronous webservice i used this (http://www.ewernli.com/web/guest/12) tutorial to get a service up and running on my glassfish.
After deployment the service (wsdl) will be available at : http://localhost:8080/AsyncTestImplService/AsyncTestImpl?WSDL
In this example the response (callback) is mocked in SoapUI.

Let’s test the service first in SoapUI.

In the top left you will see the request payload of the service, and at the top right the response of it (acknowledge).
At the bottom left you will see the mockservice running which will capture the callback from the service.
The response we will get back from the mock is :

<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
	<S:Header>
		<RelatesTo xmlns="http://schemas.xmlsoap.org/ws/2003/03/addressing">ws:uniqueAddress</RelatesTo>
	</S:Header>
	<S:Body>
		<ns2:response xmlns:ns2="http://ewe.org/">
			<arg0>hello you [http://127.0.0.1:7777/]</arg0>
		</ns2:response>
	</S:Body>
</S:Envelope>

In our scenario will will not be mocking the callback, but route it back to an other resource on the service bus. In this case a new proxy service which will deal with the callback response.

Oracle Service Bus
For this scenario we will need the next list of resources

  • requestps – start endpoint of the osb flow, based on the wsdl of the the service deployed in the glassfish.
  • requestbs – service based on the endpoint of the service running in the glassfish (this will eventually execute the service logica)
  • responseps – any soap service which will receive the callback of the asynchronous service call.
  • responsebs – any soap service with jms endpoint, which will put the received callback in the queue.
  • testwsdl – the imported wsdl of the service running in the glassfish
  • XMLSchema_738301149 – generated xsd used by the imported wsdl

We will start with a call to the requestps service.

This service will route the request 1 on 1 to the requestbs. The requestbs is a wsdl-based http service based on the wsdl of the asynchronous webservice, with ‘http://127.0.0.1:8080/AsyncTestImplService/AsyncTestImpl
‘ as endpoint (glassfish). To inform this service where to deliver the callback response we need to just edit the soap-header which we will send to the service.

The flow of the requestps will look like this :

The route will look like this :

In the assign we will assign this to the header variable :

<soap-env:Header xmlns:ns1="http://schemas.xmlsoap.org/ws/2003/03/addressing">
	<ns1:MessageID>ws:uniqueAddress</ns1:MessageID>
	<ns1:ReplyTo>
		<ns1:Address>http://localhost:7001/AsyncTest/invoke/responseps</ns1:Address>
	 </ns1:ReplyTo>
 </soap-env:Header>

In here we will assign the address to which the service can reply the callback. In our case this will be a new endpoint on the service bus (resource responseps).
This doens’t have to be a static xml payload.

The responseps proxy service will receive the callback. This proxy service is an any soap proxy service and will receive the whole soap-envelope of the callback.

This service will route 1 on 1 to the responsebs.
This is a any soap business service with jms transport (endpoint jms://localhost:7001/TestCF/TestQueue). So the whole soap-envelope will be stored in the TestQueue queue.
In weblogic we created both the TestCF connection factory and the TestQueue queue.

Test the flow
Go to the sbconsole and use the testconsole of the requestps to invoke the service on the bus

And the response of the invoke :

We received back an empty sayHelloResponse. This is because we will receive the callback on the responseps resource on the bus.
Now go the queue to see the content :

It looks like the flow ended correctly. We invoked a service on the bus, this service routed the request to the asynchronous webservice running in glassfish. This service came back with a callback and this call is routed on the service bus to the queue which resists in weblogic.

SoapUI
Create a new project in SoapUI based on the wsdl of the requestps resource on the bus (endpoint http://localhost:7001/AsyncTest/invoke/testps/?WSDL).
Request payload

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ewe="http://ewe.org/">
   <soapenv:Header/>
   <soapenv:Body>
      <ewe:sayHello>
         <!--Optional:-->
         <arg0>eric</arg0>
      </ewe:sayHello>
   </soapenv:Body>
</soapenv:Envelope>

Response

<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
   <S:Body>
      <ns2:sayHelloResponse xmlns:ns2="http://ewe.org/"/>
   </S:Body>
</S:Envelope>

And the payload in the queue

<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
	<S:Header>
		<RelatesTo xmlns="http://schemas.xmlsoap.org/ws/2003/03/addressing">ws:uniqueAddress</RelatesTo>
	</S:Header>
	<S:Body>
		<ns2:response xmlns:ns2="http://ewe.org/">
			<arg0>hello you [http://localhost:7001/AsyncTest/invoke/responseps]</arg0>
		</ns2:response>
	</S:Body>
</S:Envelope>

Resources
sbconfig.jar (export of oracle service bus resources)

Oracle Service Bus, file transport, get filename from url

In Oracle Service Bus it’s relative easy to get the filename which has been processed by the proxy service.
On the $inbound context variable we can use the next xpath expression to get file uri

$inbound/ctx:transport/ctx:request/tp:headers/file:fileName

this will give us :

<file:fileName xmlns:file="http://www.bea.com/wli/sb/transports/file">c:\temp\testfile\1263968456285_test.xml</file:fileName>

Now i was struckling a bit on how to get just the filename from this url.
Since i couldn’t find any instring function in the bea xqueury function list i couldn’t use any construction like (without the sql commands)

select substr('/tmp/testfile/test.xml',instr('/tmp/testfile/test.xml','/',-1)+1)
from dual;

In this case the function tokenize can be used :

tokenize($inbound/ctx:transport/ctx:request/tp:headers/file:fileName, "/")[last()]

this will give me the last token in the list which is split up by the “/” sign, with as result “test.xml”.

In case your running it on a windows environment don’t forget to escape the backslash

tokenize($inbound/ctx:transport/ctx:request/tp:headers/file:fileName, "\\")[last()]

Jumpstart for Oracle Service Bus Development

The article which i wrote together with Ronald van Luttikhuizen is posted on the OTN site.
My first one for OTN and i’m proud of it.
otn
If you still have any questions about it or other related subjects, i will be happy to help you.

link :

Jumpstart for Oracle Service Bus Development

Oracle Service Bus, JMS Request/Response pattern

Inspired by the article of Edwin about JMS Request Reply Interaction Pattern in Soa Suite 11g, i will show a little example of what functionality Oracle Service Bus supplies to implement the jms request/response (reply) pattern.
The solution is quiet simple.

Create the wls resources

  • Create JMS Server, MyJMSServer
  • Create JMS Modules, MyJMSResources
  • Create a Connection Factory, MyConnectionFactory
  • Create 2 queues, MyQueueIn (request message), MyQueueOut (response message)

wls_resources

Create the osb resource

  • Create a new proxy service, JMSRequestResponsePS
  • ps_1
    ps_2
    For the Endpoint URi, insert the url to In-queue
    ps_3
    Check the ‘Is Response Required’ option.
    We will use JMSCorrelationID for the Response Correlation Pattern.
    For the Response URI, insert the url to the Out-queue
    ps_4

Testing
Now test the flow by insert a little xml message in the MyQueueIn queue, wait a few seconds and check the MyQueueOut queue.
Only thing what’s left is to fill in the message flow of the proxy service and add some logica.