...
- Starting Camel automatically
- Using CXF in routing
Starting Camel automatically
Our 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 . We use it's ContextListener
...
Code Block | ||||
---|---|---|---|---|
| ||||
<camelContext id="camel" xmlns="http://activemq.apache.org/camel/schema/spring"> ... </camelContext> |
Adding route builder
Now we have Camel integrated but we still need to add our route bulder that we did manually from the javacode as:
...
Code Block | ||||
---|---|---|---|---|
| ||||
<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.
...
Code Block | ||||
---|---|---|---|---|
| ||||
<xs:element name="inputReportIncident"> <xs:complexType name="inputReportIncident"> |
Using CXF endpoint
Okay now we are ready to turn our attention to using CXF directly in Camel routing. So we zap ReportIncidentEndpointImpl
as we no longer need this code. So what's left is:
...
Code Block | ||||
---|---|---|---|---|
| ||||
// return OK as response .transform(constant(OK)); |
Important issue regarding using CXF endpoints in Camel
Now we are nearly there, there is an important issue left with using CXF endpoints in Camel. In part 4 we started the route by sending the InputReportIncident object containing the webservice input. Now we are using CXF endpoints directly in our routing so its a CxfExchange that is created and passed in the routing. CxfExchange stores the payload in a CXF holder class org.apache.cxf.message.MessageContentsList
. So to be able to get our InputReportIncident class we need to get this object from the holder class. For this we show how it's done in Java using a processor, then later we show a nicer solution.
...
Now the route is nice and simple.
Unit testing
...
Now lets turn our attention to unit testing it. From part 4 we have an unit test that is capable of exposing a webservice and send a test request and assert a mail is received. We will refactor this unit test to start up Camel, as it's Camel that should expose the webservice.
...
Code Block | ||||
---|---|---|---|---|
| ||||
/** * Unit test of our routes */ public class ReportIncidentRoutesTest extends TestCase { private CamelContext camel; // should be the same address as we have in our route private static String ADDRESS = "http://localhost:8080/part-five/webservices/incident"; protected void startCamel() throws Exception { camel = new DefaultCamelContext(); camel.addRoutes(new ReportIncidentRoutes()); camel.start(); } protected static ReportIncidentEndpoint createCXFClient() { // we use CXF to create a client for us as its easier than JAXWS and works JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(ReportIncidentEndpoint.class); factory.setAddress(ADDRESS); return (ReportIncidentEndpoint) factory.create(); } public void testRendportIncident() throws Exception { // start camel startCamel(); // assert mailbox is empty before starting Mailbox inbox = Mailbox.get("incident@mycompany.com"); assertEquals("Should not have mails", 0, inbox.size()); // create input parameter InputReportIncident input = new InputReportIncident(); input.setIncidentId("123"); input.setIncidentDate("2008-08-18"); input.setGivenName("Claus"); input.setFamilyName("Ibsen"); input.setSummary("Bla"); input.setDetails("Bla bla"); input.setEmail("davsclaus@apache.org"); input.setPhone("0045 2962 7576"); // create the webservice client and send the request ReportIncidentEndpoint client = createCXFClient(); OutputReportIncident out = client.reportIncident(input); // assert we got a OK back assertEquals("0", out.getCode()); // let some time pass to allow Camel to pickup the file and send it as an email Thread.sleep(3000); // assert mail box assertEquals("Should have got 1 mail", 1, inbox.size()); // stop camel camel.stop(); } } |
Conclusion
We have now seen how we have created a more much nicer solution leveraging Camel's powerful routing capabilities.
What we have here is routing logic with the help of the code comments could be understood by non developers. This is very powerful. In a later part we will look at some of the tools that Camel provides, for instance a tool to generate a nice diagrams of your routes
Code Block | ||||
---|---|---|---|---|
| ||||
public void configure() throws Exception {
// webservice response for OK
OutputReportIncident OK = new OutputReportIncident();
OK.setCode("0");
// endpoint to our CXF webservice
String cxfEndpoint = "cxf://http://localhost:8080/part-five/webservices/incident"
+ "?serviceClass=org.apache.camel.example.reportincident.ReportIncidentEndpoint"
+ "&wsdlURL=report_incident.wsdl";
// first part from the webservice -> file backup
from(cxfEndpoint)
// we need to convert the CXF payload to InputReportIncident that FilenameGenerator and velocity expects
.convertBodyTo(InputReportIncident.class)
// then set the file name using the FilenameGenerator bean
.setHeader(FileComponent.HEADER_FILE_NAME, BeanLanguage.bean(FilenameGenerator.class, "generateFilename"))
// and create the mail body using velocity templating
.to("velocity:MailBody.vm")
// and store the file
.to("file://target/subfolder")
// return OK as response
.transform(constant(OK));
// second part from the file backup -> send email
from("file://target/subfolder")
// set the subject of the email
.setHeader("subject", constant("new incident reported"))
// send the email
.to("smtp://someone@localhost?password=secret&to=incident@mycompany.com");
}
|
In the next part's look at using XML to create the route instead of Java code. Then it might be even more readable by non developers.
#Resources
Attachments patterns .*part-five.zip