Thursday, July 21, 2011

Using Apache Camel to Monitor SNMP-enabled devices

I've been working with a hardware manufacturer company this week that wanted to use Apache Camel to get information about SNMP-enabled (http://en.wikipedia.org/wiki/Simple_Network_Management_Protocol) devices.

As you may know, Apache Camel has a SNMP component (http://camel.apache.org/snmp.html) able to poll devices or receive SNMP traps.

Here is a very simple Camel route example that we used to get started with the camel-snmp component:


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Configures the Camel Context-->
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:camel="http://camel.apache.org/schema/spring" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd        http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">

  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <package>com.fusesource.fusebyexample</package>
    <route id="SNMP-Sample-Route">
        <from uri="snmp:1.1.1.12:161?
                   protocol=udp&amp;
                   type=POLL&amp;
                   delay=10&amp;
                   oids=1.3.6.1.2.1.1.3.0"/>
        <log logName="SNMP_LOG" 
             loggingLevel="INFO" 
             message="&gt;&gt;&gt; ${body}"/>
    </route>
</camelContext>

</beans>


So, the snmp-camel component has many configuration options but you basically have to provide the following:


snmp://hostname[:port][?Options]


Additionally, you have the following options:














On our example, we added the following (additionally to the hostname and port number of the host we wanted to get information from) to test the configuration:

protocol=UDP - You can either use UDP or TCP protocols

type=POLL - You can enter POLL or TRAP to define whether the camel component is going to poll the device for info and create a listener for SNMP trap events

delay=10 - Frequency you want to poll the device for information

oids=1.3.6.1.2.1.1.3.0 - In this particular example, we setup the OID which retrieves the amount of time the device is up (http://www.oid-info.com/get/1.3.6.1.2.1.1.3.0)

The last piece of our Camel route was just a log component because we wanted to see what was coming back from the device. That's all!

We also used the FUSE IDE to rapidly test the scenario we wanted and that was pretty straightforward. The FUSE IDE can be downloaded from (http://fusesource.com/products/fuse-ide-camel/).

Don't forget to include camel-snmp as a dependency in your pom.xml file if you're using Maven which
should be like this:

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-snmp</artifactId>
    <version>${camel-version}</version>
</dependency>


Enjoy the ride!

Friday, July 8, 2011

Calling Web Services with Apache Camel

Web Services are very important components of most (if not all) of the integration projects these days. The Web Services architecture make them extremely useful for distributed applications and they are often associated with Service-Oriented Architecture (SOA).

Calling Web Services from Apache Camel is pretty simple yet powerful and Camel uses Apache CXF (http://cxf.apache.org).

Apache CXF provides you many options to build Web Services (JAX-WS Annotated Services from Java, JAX-WS Annotated Services from WSDL, JAX-WS Providers, Simple Frontend and JavaScript).
Additionally, there are three major types of services (SOAP, REST and CORBA). For more information, check this web page http://cxf.apache.org/docs/how-do-i-develop-a-service.html.

JAX-WS (Java API for XML Web Services) specification defines annotations that allow you to tell CXF how your POJOs should be represented on the web.

Basically, there two types of web services development with Apache CXF:

Contract-first development - Recall that WSDLs define what operation and types a web service provides. This is often referred to as web services contract, and in order to communicate with a web service, you must satisfy the contract. Contract-first development means that you develop a WSDL file and then generate stub Java class implementations using a tool like Apache CXF.

Code-first development - The other way to develop web services is by starting out with a Java class and then letting the web service framework handle the job of generating a WSDL contract for you. In this case, Apache CXF will be in control of what the contract will be.

To configure the CXF component URI in Camel there are two main ways that you can do that:

Configuring Using the URI Options - The most simple way (and the one will be using for demo purposes) where you pass inline parameters to the component. Here is the format you have to specify:

cxf://<service_address>[?options]

The options available for the CXF component are available here: http://camel.apache.org/cxf.html

Referencing a Bean - Using this approach, you have to specify a bean containing the configuration. You have much more power and flexibility than configuring CXF via URI options but it also requires more work on your side. You can configure things like CXF interceptors, JAX-WS handlers and the CXF bus but we're going to cover that on a different blog post. To configure the CXF component referencing a bean the URI is something like this:

cxf:bean:beanName where the beanName specifies the ID of the CXF endpoint bean defined in your Spring XML file.

So, to give you a taste of what's going to be a simple project calling Web Services with Apache Camel here is the step-by-step procedure:

I'll be using the FuseIDE for that but the artifacts generated are pretty much the same if you choose the Maven approach.

Here is what you need:

- Eclipse IDE (Eclipse Helios 3.6.2)
- Apache Maven (3.0.3)
- FuseSource Camel IDE (http://fusesource.com/products/fuse-ide-camel/)


Then, create a new Fuse IDE project and select the Camel Archetype and type the Group Id, Artifact Id and Package name for your project then click Finish.


As I've explained before on my previous post (http://marcelojabali.blogspot.com/2011/06/file-batch-splitter-with-apache-camel.html) the default Fuse IDE project comes with a sample configuration that you can remove for the purpose of this demonstration.


Create a new Camel XML File (camelContext.xml) and then create a new route. 


Drag and drop an endpoint from the palette and also a log component. Connect them and make sure you save your project. You should see something like the picture below:




Edit the URI property of the Endpoint to be: file:src/data?noop=true


Edit the Message property of the Log component to be: ${body} and the Logging Level to INFO


You should be able to run this route now which is going to display the content of files under the src/data directory in your project in the Camel log. It's always a good practice to make sure every step in your route runs consistently and without any problems.


To run the Camel route (if you're using the FuseIDE) just right click int the Camel XML file and then select Run As... Local Camel Context.


If everything executed correctly you should see the content of the files in the Eclipse console and you're ready for the next step.


Add another Endpoint to your route. Connect the Log component to the new created Endpoint.

The recently added Endpoint is going to be our CXF component. We're going to use a sample Stock Quote Web Service available at http://www.webservicex.net/WS/WSDetails.aspx?CATID=2&WSID=9

Click on the Endpoint and then add the following to the URI:

cxf://http://www.webservicex.net/stockquote.asmx?wsdlURL=src/main/resources/META-INF/stockquote.wsdl&serviceName={http://www.webserviceX.NET/}StockQuote&portName={http://www.webserviceX.NET/}StockQuoteSoap&dataFormat=MESSAGE

Here are the options being used on this simple call:

cxf://http://www.webservicex.net/stockquote.asmx - Endpoint definition (cxf) and then the required service address

wsdlURL=src/main/resources/META-INF/stockquote.wsdl - The location of the WSDL file

serviceName={http://www.webserviceX.NET/}StockQuote - The service name this service is implementing, it maps to wsdl:service@name

portName={http://www.webserviceX.NET/}StockQuoteSoap - The port name this service is implementing, it maps to wsdl:port@name

dataFormat=MESSAGE - The data type messages supported by the CXF endpoint (default is POJO)


The last step in the route to be implemented is a Log component to display the Web Service response. To do that, just add another Log and connect the CXF component to it.


Edit the Message property of the Log component to be: ${body} and the Logging Level to INFO


Your route should be similar to the following:




Save the project.


For reference, here is the whole route:




<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:cxf="http://camel.apache.org/schema/cxf" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://camel.apache.org/schema/spring
    http://camel.apache.org/schema/spring/camel-spring.xsd">

  <camelContext xmlns="http://camel.apache.org/schema/spring" trace="false">
    <route id="my_Sample_Camel_Route_with_CXF">
        <from uri="file:src/data?noop=true"/>
        <log loggingLevel="INFO" message="&gt;&gt;&gt; ${body}"/>
        <to uri="cxf://http://www.webservicex.net/stockquote.asmx?
        wsdlURL=src/main/resources/META-INF/stockquote.wsdl&amp;
        serviceName={http://www.webserviceX.NET/}StockQuote&amp;
        portName={http://www.webserviceX.NET/}StockQuoteSoap&amp;
        dataFormat=MESSAGE"/>
        <log loggingLevel="INFO" message="&gt;&gt;&gt; ${body}"/>
    </route>
</camelContext>

</beans>




Before you test it make sure you change the values of the sample messages (under src/data) to the following:


message1.xml:


<?xml version="1.0" encoding="utf-8"?>


<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <GetQuote xmlns="http://www.webserviceX.NET/">
      <symbol>AAPL</symbol>
    </GetQuote>
  </soap12:Body>
</soap12:Envelope>

message2.xml:

<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <GetQuote xmlns="http://www.webserviceX.NET/">
      <symbol>GOOG</symbol>
    </GetQuote>
  </soap12:Body>
</soap12:Envelope>

This is the SOAP format that the web service is expecting and we're not doing any message transformation here so far.
At this point, you're ready to go and you just need to run the Camel route as explained before.
After you run the route, you should see two messages being displayed in the Eclipse console with the content of the files you just edited and then two responses from the Web Service showing the stock value of AAPL and GOOG.

The sample code is available at https://github.com/mjabali/CXF-Sample

Enjoy the ride!






Using SMS Channels with Oracle Intelligent Bots

Using SMS is a very convenient way to communicate with someone these days and most people prefer to use SMS instead of email. SMS also give...