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.


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.


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"
       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">
				<bean class="org.springframework.xml.xsd.SimpleXsdSchema">
					<property name="xsd" value="classpath:com/consol/citrus/samples/greeting/schema/greeting.xsd"/>

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

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

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

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

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

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

	<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:channel id="fileInputChannel">
		<si:queue capacity="25"/>
			<bean class="org.springframework.integration.transformer.MessageTransformingChannelInterceptor">
					<bean class="org.springframework.integration.file.transformer.FileToStringTransformer"/>

	<citrus:message-channel-receiver id="fileInputChannelReceiver"

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

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">
			<author>Eric Elzinga</author>
			<last-updated-by>Eric Elzinga</last-updated-by>

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

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

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

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%)


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?


About Eric Elzinga
Eric Elzinga I'm an integration consultant located in The Netherlands. Mainly doing projects based on Oracle integration stacks (Oracle SOA Suite/Oracle Service Bus (OSB)), Java development, and opensource integration products.

10 Responses to EAI/Oracle Service Bus testing with Citrus Framework, part2

  1. Great post! I think it is a very good sample for the handshake between Citrus and Spring Integration adapters. With this test setup Citrus can use all Spring Integration adapter implementations, which is great! I will definitely add more descriptions to the Citrus reference documentation, promised 🙂 Thank you for the article!

  2. Pingback: When mapping params in an SSIS Exec SQL Task, should the "Paramater Name" be 0 when direction is ReturnValue?

  3. Luke says:

    It looks very useful for a developer to make automated message based tests. But it’s a bit complex with XML and Java for most testers to develop or maintain. What are opinions about similar tools that driven from a GUI? There are a few out there but GH Tester is one that I am familiar with. It would be very interesting to hear peoples opinions about the pros and cons of the two different approaches given that their goals and broad functionality are very similar – message based automated testing of diverse interfaces.

    • Eric Elzinga says:

      I agree it’s a bit to technical for the average tester. I’m not familiar with the tools used by the testers itself, but i don’t think there is one best way to go on those. It depends on the profile of your testers to see what technical implementation or methodology they use. Does GH gives you the opportunity to maintain already build testcases from the developers, or do you need to create them all by yourself, from scratch

  4. Pingback: EAI/Oracle Service Bus testing with Citrus Framework, part2 | Oracle .. Java .. OpenSource .. SOA

  5. Hi Eric,

    great article, I am going to try to adopt this today. Well I was looking for some integrated test framework with feature to create reports and also with some web GUI so it will be usable by testers. But I was not successful too much in my search. Citrus is definitely one of the ways I like but will require more development (but can be done) to built reporting and web management over it. For now even this way is enough so thank you for this tutorial. As soon as it is already about 3 years when you published this, have you improve the way of testing OSB at all, I am not talking about SoapUI or Hermes JMS, etc. I am looking for some framework usable also by testers.

    If I will not focus on open source area I was able to find CA Lisa Suite which is presented as tool to provide testing cases of components running on OSB, so I will try to contact the representative and will see once they will provide me with the demo.

    Thank you again Eric.


    • Eric Elzinga says:

      Hi Ladislav,

      For functional integration tests we currently only use soapui. We don’t test just the to be tested component but query also connected systems to verify if the processflow got executed in a valid way.
      Besides soapui we don’t use any other frameworks (besides LoadUI for loadtesting).

  6. Nits says:

    Reblogged this on Nitin's Oracle Fusion Middleware and SOA World and commented:
    Part 2 of the OSB testing framework

  7. Pingback: Confluence: Enterprise SOA

  8. Pingback: Testing Oracle Service Bus components | Nitin's Oracle Fusion Middleware and SOA World

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: