Versions Compared

Key

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

...

Wiki Markup
{snippet:id=e2|lang=xml|url=activemq/camel/trunk/examples/camel-example-spring-jms/pom.xml}

...

And dependencies for the AOP enable server example:

Wiki Markup
{snippet:id=e3|lang=xml|url=activemq/camel/trunk/examples/camel-example-spring-jms/pom.xml}

Writing the Server

Create the Spring Service

...

component-scan

Defines the package to be scanned for Spring stereotype annotations, in this case, to load the "multiplier" bean

camel-context

Defines the package to be scanned for Camel routes. Will find the ServerRoutes class and create the routes contained within it

jms bean

Creates the Camel JMS component

Run the Server

Code Block
titleorg/example/server/CamelServer.java

public class CamelServer {

  public static void main(final String[] args) {
    ApplicationContext context = new ClassPathXmlApplicationContext("camel-server.xml");
  }

}

The main method can then be executed to start the server.

Creating the Client

We will initially create a client by directly using CamelTemplate. We will later create a client which uses Spring remoting to hide the fact that messaging is being used.

Code Block
1xml
titlecamel-client.xml

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

	<camel:camelContext id="camel" />
	<camel:template id="camelTemplate" />
	
	<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
		<property name="connectionFactory">
			<bean class="org.apache.activemq.ActiveMQConnectionFactory">
				<property name="brokerURL" value="tcp://localhost:61616" />
			</bean>
		</property>
	</bean>
</beans>

The client will not use the Camel Maven Plugin so the Spring XML has been placed in src/main/resources so not to conflict with the server configs.

camelContext

The Camel context is defined but does not contain any routes

tempate

The CamelTemplate is used to place messages onto the JMS queue

jms bean

This initialises the Camel JMS component, allowing us to place messages onto the queue

Code Block
titleorg/example/client/CamelClient.java

public class CamelClient {

  public static void main(final String[] args) {

    ApplicationContext context = new ClassPathXmlApplicationContext("camel-client.xml");
    CamelTemplate<JmsExchange> camelTemplate = (CamelTemplate) context.getBean("camelTemplate");

    int response = (Integer)camelTemplate.sendBody("jms:queue:numbers",
      ExchangePattern.InOut,
      22
    );

    Assert.assertEquals(66, response);
    System.out.println(response);

  }
}

The CamelTemplate is retrieved from a Spring ApplicationContext and used to manually place a message on the "numbers" JMS queue. The exchange pattern (ExchangePattern.InOut) states that the call should be synchronous, and that we will receive a response. We then assert that the response is three times the value of the original.

Before running the client be sure that both the ActiveMQ broker and the CamelServer are running.

Using Spring Remoting

Spring Remoting "eases the development of remote-enabled services". It does this by allowing you to invoke remote services through your regular Java interface, masking that a remote service is being called.

Code Block
1xml
titlecamel-client-remoting.xml

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

	<camel:camelContext id="camel" />
	
	<camel:proxy
		id="multiplier"
		serviceInterface="org.example.server.Multiplier"
		serviceUrl="jms:queue:numbers"
	/>
	
	<bean id="jms" class="org.apache.camel.component.jms.JmsComponent">
		<property name="connectionFactory">
			<bean class="org.apache.activemq.ActiveMQConnectionFactory">
				<property name="brokerURL" value="tcp://localhost:61616" />
			</bean>
		</property>
	</bean>
</beans>

AOP Enabled Server

The example has an enhanced Server example that uses fullblown Aspejct AOP for doing a audit tracking of invocations of the business service.

We leverage Spring AOP support in the {{camel-server-aop.xml} configuration file. First we must declare the correct XML schemas to use:

Wiki Markup
{snippet:id=e1|lang=xml|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/resources/META-INF/spring/camel-server-aop.xml}

Then we include all the existing configuration from the normal server example:

Wiki Markup
{snippet:id=e2|lang=xml|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/resources/META-INF/spring/camel-server-aop.xml}

Then we enable the AspejctJ AOP auto proxy feature of Spring that will scan for classes annotated with the @Aspect annotation:

Wiki Markup
{snippet:id=e3|lang=xml|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/resources/META-INF/spring/camel-server-aop.xml}

Then we define our Audit tracker bean that does the actual audit logging. It's also the class that is annotated with the @Aspect so Spring will pick this up, as the aspect.

Wiki Markup
{snippet:id=e4|lang=xml|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/resources/META-INF/spring/camel-server-aop.xml}

And the gem is that we inject the AuditTracker aspect bean with a Camel endpoint that defines where the audit should be stored. Noticed how easy it is to setup as we have just defined an endpoint URI that is file based, meaning that we stored the audit tracks as files. We can change this tore to any Camel component as we wish. To store it on a JMS queue simply change the URI to jms:queue:audit.

Wiki Markup
{snippet:id=e5|lang=xml|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/resources/META-INF/spring/camel-server-aop.xml}

And the full blown Aspejct for the audit tracker java code:

Wiki Markup
{snippet:id=e1|lang=java|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/java/org/apache/camel/example/server/AuditTracker.java}

Run the Server

The Server is started using the org.apache.camel.spring.Main class that can start camel-spring application out-of-the-box. The Server can be started in several flavors:

  • as a standard java main application - just start the org.apache.camel.spring.Main class
  • using maven jave:exec
  • using camel:run

In this sample as there are two servers (with and without AOP) we have prepared some profiles in maven to start the Server of your choice.
The server is started with:
mvn compile exec:java -PCamelServer

Or for the AOP enabled Server example:
mvn compile exec:java -PCamelServerAOP

Creating the Client

We will initially create a client by directly using ProducerTemplate. We will later create a client which uses Spring remoting to hide the fact that messaging is being used.

Wiki Markup
{snippet:id=e1|lang=xml|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/resources/camel-client.xml}
Wiki Markup
{snippet:id=e2|lang=xml|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/resources/camel-client.xml}
Wiki Markup
{snippet:id=e3|lang=xml|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/resources/camel-client.xml}

The client will not use the Camel Maven Plugin so the Spring XML has been placed in src/main/resources to not conflict with the server configs.

camelContext

The Camel context is defined but does not contain any routes

template

The ProducerTemplate is used to place messages onto the JMS queue

jms bean

This initialises the Camel JMS component, allowing us to place messages onto the queue

And the CamelClient source code:

Wiki Markup
{snippet:id=e1|lang=java|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/java/org/apache/camel/example/client/CamelClient.java}

The ProducerTemplate is retrieved from a Spring ApplicationContext and used to manually place a message on the "numbers" JMS queue. The exchange pattern (ExchangePattern.InOut) states that the call should be synchronous, and that we will receive a response.

Before running the client be sure that both the ActiveMQ broker and the CamelServer are running.

Using Spring Remoting

Spring Remoting "eases the development of remote-enabled services". It does this by allowing you to invoke remote services through your regular Java interface, masking that a remote service is being called.

Wiki Markup
{snippet:id=e1|lang=xml|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/resources/camel-client-remoting.xml}

The snippet above only illustrates the different and how Camel easily can setup and use Spring Remoting in one line configurations.

The proxy First we create a new Spring config file. This has a few changes made from camel-client.xml. Firstly the Camel template has been removed, as it will not be used. Secondly a proxy is defined. This will create a proxy service bean for you to use to make the remote invocations. The serviceInterface property details which Java interface is to be implemented by the proxy. serviceUrl defines where messages sent to this proxy bean will be directed. Here we define the JMS endpoint with the "numbers" queue we used when working with Camel template directly. The value of the id property is the name that will be the given to the bean when it is exposed through the Spring ApplicationContext. We will use this name to retrieve the service in our client. I have named the bean multiplierProxy simply to highlight that it is not the same multiplier bean as is being used by CamelServer. They are in completely independent contexts and have no knowledge of each other. As you are trying to mask the fact that remoting is being used in a real application you would generally not include proxy in the name.

And the Java client source code:

Wiki Markup
{snippet:id=e1|lang=java|url=activemq/camel/trunk/examples/camel-example-spring-jms/src/main/java/org/apache/camel/example/client/CamelClientRemoting.java}
titleorg/example/client/CamelClientRemoting.java

public class CamelClientRemoting {

  public static void main(final String[] args) {

    ApplicationContext context = new ClassPathXmlApplicationContext("camel-client-remoting.xml");
    Multiplier multiplier = (Multiplier) context.getBean("multiplierProxy");

    int response = multiplier.multiply(22);

    Assert.assertEquals(66, response);
    System.out.println(response);
  }

}

Again, the client is similar to the original client, but with some important differences.

  1. The Spring context is created with the new camel-client-remoting.xml
  2. We retrieve the proxy bean instead of a CamelTemplate ProducerTemplate. In a non-trivial example you would have the bean injected as in the standard Spring manner.
  3. The multiply method is then called directly. In the client we are now working to an interface. There is no mention of Camel or JMS inside our Java code.

...