...
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 |
jms bean | Creates the Camel JMS component |
Run the Server
Code Block | ||
---|---|---|
| ||
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 | ||||
---|---|---|---|---|
| ||||
<?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 |
jms bean | This initialises the Camel JMS component, allowing us to place messages onto the queue |
Code Block | ||
---|---|---|
| ||
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 | ||||
---|---|---|---|---|
| ||||
<?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 |
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} | ||
| ||
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.
- The Spring context is created with the new camel-client-remoting.xml
- 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. - 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.
...