Versions Compared

Key

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

...

We continue from part 4 where we have the routing in place. However as you might have noticed that we aren't quiet there yet with a nice solution.

These issues are still there as we:

  • is creating and starting Camel manually
  • is starting the routing by manually sending a message to direct:start

Of course for both issues there is a more convienient solution with Camel. But as this tutorial is very much about showing how things is done manually and also peeks how Camel does this internally for you. So let's get rocking

, we are still coding to much. In this part we will look into to address these two concerns:

  • Staring Camel automatically
  • Using CXF in routing

Starting Camel automatically

...

Code Block
xml
xml
    <camelContext id="camel" xmlns="http://activemq.apache.org/camel/schema/spring">
       <package>org.apache.camel.example.reportincident</package>
    </camelContext>

Using CXF directly

Now we have seen how you can leverage Spring to start Camel, in fact it handles the lifecycle of Camel, so you can say Camel is embedded with Spring in your application.

From the very start of this tutorial we have used CXF as the webservice framework and we haven't integrated it directly with Camel as it can do out-of-the-box. Camel ships with a camel-cxf component for integrating CXF directly within Camel routing. In our tutorial we are exposing a webservice so we want continue to do this. Before we continue let's recap at what the webservice implementation we have from part 4

Code Block
java
java

/**
 * The webservice we have implemented.
 */
public class ReportIncidentEndpointImpl implements ReportIncidentEndpoint {

    private CamelContext context;

    public ReportIncidentEndpointImpl() throws Exception {
        // create the context
        context = new DefaultCamelContext();

        // append the routes to the context
        context.addRoutes(new ReportIncidentRoutes());

        // at the end start the camel context
        context.start();
    }

    public OutputReportIncident reportIncident(InputReportIncident parameters) {
        // create the producer template to use for sending messages
        ProducerTemplate producer = context.createProducerTemplate();
        // send the body and the filename defined with the special header key
        Object mailBody = producer.sendBody("direct:start", parameters);
        System.out.println("Body:" + mailBody);

        // return an OK reply
        OutputReportIncident out = new OutputReportIncident();
        out.setCode("OK");
        return out;
    }

}

We have already seen how we can get Spring starting Camel so the constructor method can be removed. What next is that the CamelContext needed in this code should be the one from our camel-context.xml file. So we change the code to use a plain setter injection (we can use Spring annotations and whatelse but we keep it simple with a setter):

Code Block
java
java

/**
 * The webservice we have implemented.
 */
public class ReportIncidentEndpointImpl implements ReportIncidentEndpoint {

    private CamelContext context;

    public void setCamelContext(CamelContext context) {
        this.context = context;
    }

    public OutputReportIncident reportIncident(InputReportIncident parameters) {
        // create the producer template to use for sending messages
        ProducerTemplate producer = context.createProducerTemplate();
        // send the body and the filename defined with the special header key
        Object mailBody = producer.sendBody("direct:start", parameters);
        System.out.println("Body:" + mailBody);

        // return an OK reply
        OutputReportIncident out = new OutputReportIncident();
        out.setCode("OK");
        return out;
    }

}

And then we need to instruct Spring to set this property. Turning back to cxf-config.xml from part 4 we can add a reference to our camel context

Code Block
xml
xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>

    <!-- implementation of the webservice, and we refer to our camel context with the id = camel from camel-context.xml -->
    <bean id="reportIncidentEndpoint" class="org.apache.camel.example.reportincident.ReportIncidentEndpointImpl">
       <property name="context" ref="camel"/>
    </bean>

    <!-- export the webservice using jaxws -->
    <jaxws:endpoint id="reportIncident"
                    implementor="#reportIncidentEndpoint"
                    address="/incident"
                    wsdlLocation="/WEB-INF/wsdl/report_incident.xml"
                    endpointName="s:ReportIncidentPort"
                    serviceName="s:ReportIncidentService"
                    xmlns:s="http://reportincident.example.camel.apache.org"/>
</beans>

So now we have two spring XML files
- cxf-config.xml
- camel-config.xml

And since cxf-config.xml is dependent on camel-config.xml we need to have correct ordering in our web.xml where we have defined the XML files to load by Spring. So we set the camel-config.xml before the cxf-config.xml so Spring have created the SpringCamelContext and registered it in its registry with the id = camel.
{code:xml}
	<!-- location of spring xml files -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
        <param-value>classpath:camel-config.xml</param-value>
        <param-value>classpath:cxf-config.xml</param-value>
	</context-param>