Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Tutorial

...

using Axis 1.4 with Apache Camel

Info
titleRemoved from distribution

This example has been removed from Camel 2.9 onwards. Apache Axis 1.4 is a very old and unsupported framework. We encourage users to use CXF instead of Axis.

Table of Contents

Prerequisites

This tutorial uses Maven 2 to setup the Camel project and for dependencies for artifacts.

Distribution

This sample is distributed with the Camel 1.5 distribution as examples/camel-example-axis.

Introduction

Apache Axis is/was widely used as a webservice framework. So in line with some of the other tutorials to demonstrate how Camel is not an invasive framework but is flexible and integrates well with existing solution.

...

  • Maven 2.0.9
  • Apache Camel 1.45.0
  • Apache Axis 1.4
  • Spring 2.5.5

Setting up the project to run Axis

This first part is about getting the project up to speed with Axis. We are not touching Camel or Spring at this time.

Maven 2

Axis dependencies is available for maven 2 so we configure our pom.xml as:

...

Code Block
xml
xml
<!-- to compile with 1.5 -->
	<plugin>
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-compiler-plugin</artifactId>
		<configuration>
			<source>1.5</source>
			<target>1.5</target>
		</configuration>
	</plugin>

            <plugin>
               <groupId>org.codehaus.mojo</groupId>
               <artifactId>axistools-maven-plugin</artifactId>
               <configuration>
	          <sourceDirectory>src/main/resources/</sourceDirectory>
                  <packageSpace>com.mycompany.myschema</packageSpace>
                  <testCases>false</testCases>
                  <serverSide>true</serverSide>
                  <subPackageByFileName>false</subPackageByFileName>
               </configuration>
               <executions>
                 <execution>
                   <goals>
                     <goal>wsdl2java</goal>
                   </goals>
                 </execution>
               </executions>
            </plugin>

wsdl

We use the same .wsdl file as the Tutorial-Example-ReportIncident and copy it to src/main/webapp/WEB-INF/wsdl

Code Block
xml
xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:tns="http://reportincident.example.camel.apache.org"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
	targetNamespace="http://reportincident.example.camel.apache.org">

	<!-- Type definitions for input- and output parameters for webservice -->
	<wsdl:types>
	<xs:schema targetNamespace="http://reportincident.example.camel.apache.org">
			<xs:element name="inputReportIncident">
				<xs:complexType>
					<xs:sequence>
						<xs:element type="xs:string"  name="incidentId"/>
						<xs:element type="xs:string"  name="incidentDate"/>
						<xs:element type="xs:string"  name="givenName"/>
						<xs:element type="xs:string"  name="familyName"/>
						<xs:element type="xs:string"  name="summary"/>
						<xs:element type="xs:string"  name="details"/>
						<xs:element type="xs:string"  name="email"/>
						<xs:element type="xs:string"  name="phone"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element name="outputReportIncident">
				<xs:complexType>
					<xs:sequence>
						<xs:element type="xs:string" name="code"/>
					</xs:sequence>
				</xs:complexType>
			</xs:element>
		</xs:schema>
	</wsdl:types>

	<!-- Message definitions for input and output -->
	<wsdl:message name="inputReportIncident">
		<wsdl:part name="parameters" element="tns:inputReportIncident"/>
	</wsdl:message>
	<wsdl:message name="outputReportIncident">
		<wsdl:part name="parameters" element="tns:outputReportIncident"/>
	</wsdl:message>

	<!-- Port (interface) definitions -->
	<wsdl:portType name="ReportIncidentEndpoint">
		<wsdl:operation name="ReportIncident">
			<wsdl:input message="tns:inputReportIncident"/>
			<wsdl:output message="tns:outputReportIncident"/>
		</wsdl:operation>
	</wsdl:portType>

	<!-- Port bindings to transports and encoding - HTTP, document literal encoding is used -->
	<wsdl:binding name="ReportIncidentBinding" type="tns:ReportIncidentEndpoint">
		<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
		<wsdl:operation name="ReportIncident">
			<soap:operation
				soapAction="http://reportincident.example.camel.apache.org/ReportIncident"
				style="document"/>
			<wsdl:input>
				<soap:body parts="parameters" use="literal"/>
			</wsdl:input>
			<wsdl:output>
				<soap:body parts="parameters" use="literal"/>
			</wsdl:output>
		</wsdl:operation>
	</wsdl:binding>

	<!-- Service definition -->
	<wsdl:service name="ReportIncidentService">
		<wsdl:port name="ReportIncidentPort" binding="tns:ReportIncidentBinding">
			<soap:address location="http://reportincident.example.camel.apache.org"/>
		</wsdl:port>
	</wsdl:service>

</wsdl:definitions>

Configuring Axis

Okay we are now setup for the contract first development and can generate the source file. For now we are still only using standard Axis and not Spring nor Camel. We still need to setup Axis as a web application so we configure the web.xml in src/main/webapp/WEB-INF/web.xml as:

...

Code Block
xml
xml
<parameter name="className" value="org.apache.camel.example.axis.AxisReportIncidentService"/>

Running the Example

Now we are ready to run our example for the first time, so we use Jetty as the quick web container using its maven command:

...

Then we can hit the web browser and enter this URL: http://localhost:8080/camel-example-axis/servicesImage Removed and you should see the famous Axis start page with the text And now... Some Services.

...

We do this by adding the wsdlFile tag in the service element where we can point to the real .wsdl file.

Integrating Spring

First we need to add its dependencies to the pom.xml.

...

The spring XML file is currently empty. We hit jetty again with mvn jetty:run just to make sure Spring was setup correctly.

Using Spring

We would like to be able to get hold of the Spring ApplicationContext from our webservice so we can get access to the glory spring, but how do we do this? And our webservice class AxisReportIncidentService is created and managed by Axis we want to let Spring do this. So we have two problems.

...

So now we have integrated Axis with Spring and we are ready for Camel.

Integrating Camel

Again the first step is to add the dependencies to the maven pom.xml file:

Code Block
xml
xml
        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-core</artifactId>
            <version>1.45.0</version>
        </dependency>

        <dependency>
            <groupId>org.apache.camel</groupId>
            <artifactId>camel-spring</artifactId>
            <version>1.45.0</version>
        </dependency>

...

Code Block
xmlns:camel="http://activemq.apache.org/camel/schema/spring"
http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd"

CamelContext

CamelContext is the heart of Camel its where all the routes, endpoints, components, etc. is registered. So we setup a CamelContext and the spring XML files looks like:

Code Block
xml
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:camel="http://activemq.apache.org/camel/schema/spring"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
         http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd">

    <bean id="incidentservice" class="org.apache.camel.example.axis.ReportIncidentService"/>

    <camel:camelContext id="camel">
        <!-- TODO: Here we can add Camel stuff -->
    </camel:camelContext>

</beans>

Store a file backup

We want to store the web service request as a file before we return a response. To do this we want to send the file content as a message to an endpoint that produces the file. So we need to do two steps:

  • configure the file backup endpoint
  • send the message to the endpoint

The endpoint is configured in spring XML so we just add it as:

...

In the CamelContext we have defined our endpoint with the id backup and configured it use the URL notation that we know from the internet. Its a file scheme that accepts a context and some options. The contest is target and its the folder to store the file. The option is just as the internet with ? and & for subsequent options. We configure it to not append, meaning than any existing file will be overwritten. See the File component for options and how to use the camel file endpoint.

Next up is to be able to send a message to this endpoint. The easiest way is to use a CamelProducerProducerTemplate. A CamelProducer ProducerTemplate is inspired by Spring template pattern with for instance JmsTemplate or JdbcTemplate in mind. The template that all the grunt work and exposes a simple interface to the end-user where he/she can set the payload to send. Then the template will do proper resource handling and all related issues in that regard. But how do we get hold of such a template? Well the CamelContext is able to provide one. This is done by configuring the template on the camel context in the spring XML as:

...

The template in the code above uses 4 parameters:

  • the endpoint name, in this case the id referring to the endpoint defined in Spring XML in the camelContext element.
  • the payload, can be any kind of object
  • the key for the header, in this case a Camel keyword to set the filename
  • and the value for the header

Running the example

We start our integration with maven using mvn jetty:run. Then we open a browser and hit http://localhost:8080Image Removed. Jetty is so smart that it display a frontpage with links to the deployed application so just hit the link and you get our application. Now we hit append /services to the URL to access the Axis frontpage. The URL should be http://localhost:8080/camel-example-axis/servicesImage Removed.

You can then test it using a web service test tools such as SoapUI.
Hitting the service will output to the console

...

Code Block
dir target /b
123.txt

Unit Testing

We would like to be able to unit test our ReportIncidentService class. So we add junit to the maven dependency:

...

Code Block
java
java
        // should generate a file also
        File file = new File("target/" + input.getIncidentId() + ".txt");
        assertTrue("File should exists", file.exists());

Smarter Unit Testing with Spring

The unit test above requires us to assemble the Camel pieces manually in java code. What if we would like our unit test to use our spring configuration file axis-example-context.xml where we already have setup the endpoint. And of course we would like to test using this configuration file as this is the real file we will use. Well hey presto the xml file is a spring ApplicationContext file and spring is able to load it, so we go the spring path for unit testing. First we add the spring-test jar to our maven dependency:

...

Now our unit test is much better, and a real power of Camel is that is fits nicely with Spring and you can use standard Spring'ish unit test to test your Camel applications as well.

Unit Test calling WebService

What if you would like to execute a unit test where you send a webservice request to the AxisReportIncidentService how do we unit test this one? Well first of all the code is merely just a delegate to our real service that we have just tested, but nevertheless its a good question and we would like to know how. Well the answer is that we can exploit that fact that Jetty is also a slim web container that can be embedded anywhere just as Camel can. So we add this to our pom.xml:

...

And now we have an unittest that sends a webservice request using good old Axis.

Annotations

Both Camel and Spring has annotations that can be used to configure and wire trivial settings more elegantly. Camel has the endpoint annotation @EndpointInjected that is just what we need. With this annotation we can inject the endpoint into our service. The annotation takes either a name or uri parameter. The name is the bean id in the Registry. The uri is the URI configuration for the endpoint. Using this you can actually inject an endpoint that you have not defined in the camel context. As we have defined our endpoint with the id backup we use the name parameter.

Code Block
java
java
    @EndpointInject(name = "backup")
    private ProducerTemplate template;

Camel is smart as @EndpointInject @EndpointInjected supports different kinds of object types. We like the ProducerTemplate so we just keep it as it is.
Since we use annotations on the field directly we do not need to set the property in the spring xml file so we change our service bean:

...

Running the unit test with mvn test reveals that it works nicely.

And since we use the @EndpointInject @EndpointInjected that refers to the endpoint with the id backup directly we can loose the template tag in the xml, so its shorter:

...

Then we avoid to duplicate the name and if we rename the endpoint name then we don't forget to change it in the code also.TODO: Add more links to Camel stuff
TODO: Link to other tutorials
TODO: TOC
TODO: Resources

The End

This tutorial hasn't really touched the one of the key concept of Camel as a powerful routing and mediation framework. But we wanted to demonstrate its flexibility and that it integrates well with even older frameworks such as Apache Axis 1.4.

Check out the other tutorials on Camel and the other examples.

Note that the code shown here also applies to Camel 1.4 so actually you can get started right away with the released version of Camel. As this time of writing Camel 1.5 is work in progress.

See Also