Versions Compared

Key

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

...

  • 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 (wink). We use it's ContextListener

...

Code Block
xml
xml
    <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
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.

...

Code Block
xml
xml
    <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
java
java
    // 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
java
java
/**
 * 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 (wink)

Code Block
java
java

    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