Apache Camel - Deploy war application with RouteBuilder - apache-camel

Im new to Apache Camel, Please let me know How do we deploy a war with camel which activate routeBulder automatically?
I have configure in the applicationContext.xml
<camelContext xmlns="http://camel.apache.org/schema/spring" id="camel-3">
<routeBuilder ref="SearchProcessRoute" />
<bean id="SearchProcessRoute" class="camel.core.SearchProcessRouteBuilder" />
and the Route builder
public class SearchProcessRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
// TODO Auto-generated method stub
from("activemq://search.queue")
.log("Process from the queue")
.bean("SearchProcessBean","ProcessData")
.to("activemq://search.process.queue");
}}
When I send a message to the search.queue it doesnt process anything?
Please let me know the proper way to deploy a web app with camel (Is there any sample application) and how do we solve the above issue?
PS. I was able to execute this as a standalone application. However, What I want to achieve is that connect from the standalone application to the activmq ("activemq://search.queue") which is deployed in the war and then the route (SearchProcessRouteBuilder) which is in the war activate automatically and that would process the queue. Then it will send the message to the other queue "activemq://search.process.queue".
Is this possible with Apache Camel, if So how we can achieve this?

you just need to add the following to the web.xml to bootstrap the Spring/Camel contexts
<!-- location of spring xml files -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
<!-- the listener that kick-starts Spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
see http://camel.apache.org/servlet-tomcat-example.html

Related

OSGI service Call using Camel route

I get method not found exception when I try to connect/call OSGI service using camel route and I am not sure what logic I am missing here.
//Exception
Caused by: org.apache.camel.RuntimeCamelException: org.apache.camel.component.bean.MethodNotFoundException: Static method with name: getGreeting not found on class: com.test.api.Hello
//The below is the blueprint that exports osgi service
<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<bean id="hello" class="com.test.HelloImpl"/>
<service ref="hello" interface="com.test.api.Hello"/>
</blueprint>
// Below is Java Interface and I did not include the java implementation code for interface here. but FYI, all method and class are declared as public
package com.test.api;
public interface Hello {
public String getGreeting();
}
//This below timer route is in Java DSL that is called by the route builder ref in the camel context and this camel context is defined inside blueprint
from("timer:foo?repeatCount=1")
.bean(com.test.api.Hello.class, "getGreeting")
.log("The message contains: ${body}")
I got the same exception when I tried executing this route in the same bundle where I export interface service and also I tried executing this timer route in another separate bundle by referencing the exported OSGI interface.
I am testing/executing these bundles in Red Hat Fuse server.
Request for thumbs down audience: please specify the reason before you thumbs down so that helps me to ask question in better way in future.
Thanks!!

How to use same CamelContext in multiple jar on the same war

I'm using the camel 2.16.2 and I need to use the one CamelContext across multiple jars as I need to have all the Camel Routers in to one CamelContext. So my war will have all those jars as maven artifacts.
Please let me know how do I handle above scenario?
Edit
Just to elaborate more on above question.
In my war myApp.war, I have initialized the CamelContext. There are three jars myApp1.jar, myApp2.jar and myApp3.jar. Each jar has it own routers defined separately.
How do I start the routers in each jar ?
Can I use the same CamelContext injected to each routers?
If I cannot handle through jars, is it possible to implement with multiple war (myApp1.war, myApp2.war and myApp3.war) and each war having different camelContext and communicate to those routers from the main war (myApp.war) ?
As other guys said, you can't use the same CamelContext across different Jars. Could you explain a little what you want to do?
IMHO what you want to do is use routes defined in different Jars. So for that you can define a Camel Context and add all the routes from different Jars. Of course your Camel-Context-JAR has to have access to all those jars.
<camel:camelContext id="camel5">
<camel:package>org.apache.camel.spring.example</camel:package>
</camel:camelContext>
Or class by class
<camelContext id="camel5" xmlns="http://camel.apache.org/schema/spring">
<routeBuilder ref="myBuilder" />
</camelContext>
<bean id="myBuilder" class="org.apache.camel.spring.example.test1.MyRouteBuilder"/>
Or if you are using CDI you can follow this great article https://dzone.com/articles/using-camel-routes-in-java-ee-components
Reference: http://camel.apache.org/spring.html
After doing some research found a way to implement this. Infact we can use the same CamelContext across different jars as all jars are in the same war (Web Container).
We can implement easily with Apache Camel 2.16.2 with camel CDI. If you're using wildfly to deploy your war then you may need to add the camel patch. Download the the wildfly 9.0.2 pach
Steps are Given Below.
In your war create a servlet or restService and Inject the camelContext.
#Inject
#ContextName("cdi-context")
private CamelContext camelctx;
Create a router in the jar with below annotation.
#Startup
#ApplicationScoped
public class MyJRouteBuilder extends RouteBuilder {
In Configure method add
#Override
public void configure() throws Exception {
from("direct:startTwo").routeId("MyJRouteBuilder")
.bean(new SomeBeanThree());
}
Create a BootStrap Class in your jar and add the Router
#Singleton
#Startup
public class BootStrap {
private CamelContext camelctx;
#PostConstruct
public void init() throws Exception {
camelctx.addRoutes(new MyJRouteBuilder());
}
Add your jar as a artifact in the war pom.xml. Once you deploy the war you can see MyJRouteBuilder is Registred in the cdi-context CamelContext. So now you can access your Router anywhere you want.
Hope this would useful anyone who has the same issue what I had.

Translation XML information to Java - Apache Camel

This is the example that is bundled with apache camel binaries
<route>
<!-- incoming requests from the servlet is routed -->
<from uri="servlet:///hello"/>
<choice>
<when>
<!-- is there a header with the key name? -->
<header>name</header>
<!-- yes so return back a message to the user -->
<transform>
<simple>Hello ${header.name} how are you?</simple>
</transform>
</when>
<otherwise>
<!-- if no name parameter then output a syntax to the user -->
<transform>
<constant>Add a name parameter to uri, eg ?name=foo</constant>
</transform>
</otherwise>
</choice>
</route>
How to translate this to Java
Am a beginner in camel, and some how came up to this
CamelContext context = new DefaultCamelContext();
context.addRoutes(new RouteBuilder(){
public void configure(){
from("servlet://hello").transform().....
}
});
But dont know how to proceed further...
If you want to port it over to java without any XML (spring that is) you can't (easily) use the servlet component.
Just porting the route will be like:
from("servlet:///hello")
.choice()
.when()
.header("name")
.transform(simple("Hello ${header.name} how are you?"))
.otherwise()
.transform(constant("Add a name parameter to uri, eg ?name=foo"));
It should work in the spring example (or any spring web app), just replacing the <route> in the <CamelContext> with <routeBuilder ref="demoRoute"> given you have defined your route as a spring bean (<bean id="demoRoute" class="org.example.demo.DemoRoute">).
However, I guess you want to do this in plain java (no spring, no xml, no webapp). You could go with the Jetty component. The difference being that Camel then will start the servlet container, instead of the servlet container starting Camel. No difference for this simple example though.
I suggest you start out with a Maven archetype to get the skeleton up
e.g. mvn archetype:generate then choose org.apache.camel.archetypes:camel-archetype-java (Creates a new Camel project using Java DSL.)
Well, you don't need the maven archetype if you have your own java application and have the thread keep running. Then you should do fine with your approach. The maven archetype is however very good for training purposes.
You then need to add a dependency to Jetty (camel-jetty.jar) (read more here).
The actual route would be exactly the same except the first row: from("jetty:http://localhost:8080/camel/hello")
Nice and easy.
Try this one:
from("servlet://hello")
.choice()
.when(header("name").isNotNull()).transform(simple("Hello ${header.name} how are you?"))
.otherwise().transform(constant("Add a name parameter to uri, eg ?name=foo"));

Apache Camel: Route from camel tomcat servlet to cxfbean component

Problem Description:
I am failing to route from my camel servlet to a cxfbean. Route initialization fails with the following error message:
"Failed to create route route1 at: >>> To[cxfbean:fooEndpoint] <<< in route:
Route[[From[servlet:///?servletName=BwsServlet]] -> [To[cxfb... because of Failed to resolve
endpoint: cxfbean://fooEndpoint due to: null".
The servlet starts fine without the cxfbean.
UPDATED: Please note that I intend to use a Camel Cxf Bean Component as opposed to a Camel Cxf Bean.
What I want to achieve:
I am running a camel servlet within Tomcat. I have a bean which implements my webservice interface (generated from WSDL by CXF). I want to process the XML message bodies before passing them on to this webservice bean. I would like to use cxf bean component as opposed to a cxf endpoint bean, since I do not want to have my cxf endpoint listen on a network port in addition to the already running camel servlet.
How my code looks like:
My camel-config.xml looks like this:
<bean id="bwsRouteBuilder" class="local.com.foo.BwsRouteBuilder"/>
<bean id="fooEndpoint" class="local.com.foo.FooBws"/>
<camel:camelContext id="bws">
<camel:routeBuilder ref="bwsRouteBuilder"/>
</camel:camelContext>
My route builder (written in Java DSL) looks like this:
public void configure() throws Exception {
from("servlet:///?servletName=BwsServlet")
// some processing of message here
.to("cxfbean:fooEndpoint");
}
UPDATED: Note the cxfbean URI format in the above code as defined here.
My web.xml looks like this:
<servlet>
<servlet-name>BwsServlet</servlet-name>
<servlet-class>org.apache.camel.component.servlet.CamelHttpTransportServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>BwsServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
camel-cxf is included as dependency in my pom.xml.
Where I looked at so far for help: I was following the documentation at Apache Camel cxfbean description and followed stackoverflow. I hope my question is not a no-brainer to answer, I am new to Camel.
Many thanks in advance for your thoughts
If you want to use a cxf bean you have to write "cxf:bean:fooEndpoint" in your route (you have forget : between cxf and bean).
public void configure() throws Exception {
from("servlet:///?servletName=BwsServlet")
// some processing of message here
.to("cxf:bean:fooEndpoint");
}

Trouble getting unit testing of RPC on GWT

I am trying to get RPC testing using GWT. I am using the default StockWatcher project that is mentioned here, I download the project, I import it, everything works fine.
I then run junitcreator in the StockWatcher project:
/Users/stephen/Work/gwt/gwt-mac-1.6.4/junitCreator -junit /Users/stephen/Applications/eclipse/plugins/org.junit_3.8.2.v20080602-1318/junit.jar -module stockwatcher -eclipse StockWatcher com.google.gwt.sample.stockwatcher.StockWatcherTest
this creates the StockWatcherTest.java in the appropriate test directory, and gives me some hosted and web mode launch files.
I then also added junit.jar to the classpath for this project.
I then modify StockWatcherTest.java to test whether I am capable of making a asynchronous request to the server. Everything looks fine, but when I try to run StockWatcherTest.java in hosted mode, I get the following error:
Starting HTTP on port 0 HTTP
listening on port 49569
The development shell servlet received a
request for 'greet' in module
'com.google.gwt.sample.stockwatcher.StockWatcher.JUnit.gwt.xml'
[WARN] Resource not found: greet;
(could a file be missing from the
public path or a tag
misconfigured in module
com.google.gwt.sample.stockwatcher.StockWatcher.JUnit.gwt.xml
?)
com.google.gwt.user.client.rpc.StatusCodeException:
Cannot find resource 'greet' in the
public path of module
'com.google.gwt.sample.stockwatcher.StockWatcher.JUnit'
Here is my StockWatcherTest.java class
package com.google.gwt.sample.stockwatcher.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.rpc.AsyncCallback;
/**
* GWT JUnit tests must extend GWTTestCase.
*/
public class StockWatcherTest extends GWTTestCase {
/**
* Must refer to a valid module that sources this class.
*/
public String getModuleName() {
return "com.google.gwt.sample.stockwatcher.StockWatcher";
}
/**
* Add as many tests as you like.
*/
public void testSimple() {
GreetingServiceAsync greetingService = GWT.create(GreetingService.class);
greetingService.greetServer("Bob",
new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
// Show the RPC error message to the user
System.out.println(caught);
fail("big time failure");
finishTest();
}
public void onSuccess(String result) {
System.out.println("success, biatch");
assertTrue(true);
}
});
delayTestFinish(1000);
}
}
Here is com/google/gwt/sample/stockwatcher/StockWatcher.gwt.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.2//EN" "http://google-web-toolkit.googlecode.com/svn/tags/1.6.2/distro-source/core/src/gwt-module.dtd">
<module rename-to='stockwatcher'>
<!-- Inherit the core Web Toolkit stuff. -->
<inherits name='com.google.gwt.user.User'/>
<!-- Inherit the default GWT style sheet. You can change -->
<!-- the theme of your GWT application by uncommenting -->
<!-- any one of the following lines. -->
<inherits name='com.google.gwt.user.theme.standard.Standard'/>
<!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
<!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> -->
<!-- Other module inherits -->
<!-- Specify the app entry point class. -->
<entry-point class='com.google.gwt.sample.stockwatcher.client.StockWatcher'/>
</module>
and here is web.xml in my generated war
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<!-- Default page to serve -->
<welcome-file-list>
<welcome-file>StockWatcher.html</welcome-file>
</welcome-file-list>
<!-- Servlets -->
<servlet>
<servlet-name>greetServlet</servlet-name>
<servlet-class>com.google.gwt.sample.stockwatcher.server.GreetingServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>greetServlet</servlet-name>
<url-pattern>/stockwatcher/greet</url-pattern>
</servlet-mapping>
</web-app>
So what am I doing wrong? Any help is appreciated. Thank you.
1-you need to add "finishTest();" at the end of the "onSuccess" method.
2-And to resolve the exeption you got : add in your StockWatcher.gwt.xml the path to your servlet greet.
servlet path='/greet' class='com.google.gwt.sample.stockwatcher.server.GreetingServiceImpl'/
Another solution is using GWT SyncProxy (support both sync & async) to test GWT RPC services in JRE
See the post at http://www.gdevelop.com/w/blog/2010/01/10/testing-gwt-rpc-services/ for details
i made some simple tests for the stock watcher. you can see them at: http://tayek.com/StockWatcher.zip

Resources