|
Page Edited :
CAMEL :
Tutorial-Example-ReportIncident-Part5
Tutorial-Example-ReportIncident-Part5 has been edited by Claus Ibsen (Jan 05, 2009). Content:Part 5We continue from part 4 where we have the routing in place. However as you might have noticed we aren't quiet there yet with a nice solution, we are still coding to much. In this part we will look into to address these two concerns:
Starting Camel automaticallyOur current deployment model is as a war and we have the web.xml to help start things. Well in fact we will leverage Spring to start the world <!-- the listener that kick-starts Spring --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
Using a spring bean we just declare the route builder using a regular spring bean: <bean id="myrouter" class="org.apache.camel.example.reportincident.ReportIncidentRoutes"/>
And then we can refer to it from our CamelContext: <camelContext id="camel" xmlns="http://activemq.apache.org/camel/schema/spring"> <routeBuilderRef ref="myrouter"/> </camelContext> So now when Spring start's it will read the camel-context.xml file and thus also start Camel as well. As SpringCamelContext is spring lifecycle event aware, Camel will also shutdown when Spring is shutting down. So when you stop the web application Spring will notify this and Camel is also shutdown nice and properly. So as an end user no need to worry. The package scanning solution is for convenience to refer to a java package and Camel will scan all classes within this package for RouteBuilder classes. If using this then you dont need to declare your route builder as a Spring bean. So the XML can be reduced to. <camelContext id="camel" xmlns="http://activemq.apache.org/camel/schema/spring"> <package>org.apache.camel.example.reportincident</package> </camelContext> Using CXF directlyNow 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 /** * 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): /** * 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 <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
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. <!-- 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>
But hey this isn't using CXF directly in the routing? Yes it's not but I wanted to show the halfway solution as well. What we have now is having Spring creating and handling lifecycle of Camel and showing how you can inject CamelContext using standard Spring into whatever code you have. This is very powerful as you can use the solution that you (or your team) already master and is familiar with. If they have Spring experience then the IoC principle of injecting resources is of course also possible with Camel as well. In fact it's a best practice principle. Later you will learn that you can inject other Camel types such as Endpoint, ProducerTemplate as well. Using the camel-cxf componentOkay let's continue and try to integrate CXF directly into our routing in Camel. This can be a bit more tricky than at first sight. Our goal is to avoid implementing the ReportIncidentEndpoint as we did with our code in ReportIncidentEndpointImpl (see above). Camel should be able to handle this automatically and integrate directly within our route. Before we started our routing using the Direct endpoint with "direct:start". We should replace this with the CXF endpoint. |
Unsubscribe or edit your notifications preferences
