How to debug Camel Route builder in eclipse IDE? - debugging

I have written Camel Route build in Java DSL and now I wanted to debug it in eclipse IDE, my class look like
public class PMRouteBuilder extends RouteBuilder {
UserProfileResponseProcessor responseProcessor=new UserProfileResponseProcessor();
System.out.println("\n");
System.out.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
System.out.println(" STARTED PROCESS MANAGER ROUTEBUILDER ");
System.out.println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
try{
from("cxf:bean:process-manager-ws?dataFormat=POJO").routeId("process-manager-route-userprofile").log( "This is ${in.header.operationName} operation called...." )
.log( "Entering inside the Choice with operation....${in.header.operationName}")
//.wireTap(RouterEndPoints.ENDPOINT_AUDITOR_QUEUE.value(),true, new PreWireTapProcessor())
.choice()
/**
* ##################################### ROUTE FOR USER PROFILE REQUEST ###########################################
*/
.when(simple("${in.header.operationName} == 'retrieveUserProfile'"))
.to("log:?showAll=true&multiline=true")
.setHeader("OPERATION_NAME", constant("retrieveUserProfile") )
.process(pmRequestProcessor)
.log( "Setting header value to...."+constant(AuditActions.Actions.ACTION_GET_USER_PROFILE.desc()) )
.setHeader(RouteActions.Actions.OMGMEAT_ACTION_ID.desc(), constant(AuditActions.Actions.ACTION_GET_USER_PROFILE.desc())).convertBodyTo(UserProfile.class)
.to(RouterEndPoints.ENDPOINT_USERPROFILE_QUEUE.value()).process(responseProcessor)
.when(simple("${in.header.operationName} == 'addUserProfile'"))
.log( "Setting header value to...."+constant(AuditActions.Actions.ACTION_ADD_PROFILE.desc()) )
.setHeader(RouteActions.Actions.OMGMEAT_ACTION_ID.desc(), constant(AuditActions.Actions.ACTION_ADD_PROFILE.desc())).convertBodyTo(UserProfile.class)
.to(RouterEndPoints.ENDPOINT_USERPROFILE_QUEUE.value()).process(responseProcessor)
.end()
}catch(Exception exc){
ApplicationLogger.error("PMRouteBuilder.configure():Exception while configure the route for 'cxf:bean:process-manager-ws?dataFormat=POJO'",exc);
}
I am able to see the log is getting printed but is there any way to put the debug point(breakpoint) and debug this Route builder?

Additionnaly to the techniques described in the link provided by Claus, we also use the Hawtio console with the Camel plugin.
With this plugin, you can:
Lists of all running Camel applications
Detailed information of each Camel Context such as Camel version number, runtime statics
Lists of all routes in each Camel applications and their runtime statistics
Manage the lifecycle of all Camel applications and their routes, so you can restart / stop / pause / resume, etc.
Graphical representation of the running routes along with real time metrics
Live tracing and debugging of running routes
Profile the running routes with real time runtime statics; detailed specified per processor
Browsing and sending messages to Camel endpoint
I know you asked for Eclipse, but I think debugging step-by-step a DSL is not possible today, that is why we mainly use the Tracer enabled mode and in the last resort, use the Hawtio console for a step-by-step debugging.

Another technique would be to use the JUnit of your IDE but you should modify your class a bit to be better testable:
Use properties for your endpoints, like changing
from("cxf:bean:process-manager-ws?dataFormat=POJO")
...
.to(RouterEndPoints.ENDPOINT_USERPROFILE_QUEUE.value()) // the two instances
with
from("{{from.endpoint}}")
...
.to("{{user.profile.endpoint.1}}")
...
.to("{{user.profile.endpoint.2}}")
and set the properties with the original values in your spring or bluprint file (depending which one you use).
After you can create a test in the test folder (src/test if using maven) called PMRouteBuilderTest with extends CamelTestSupport and with the following content:
#EndpointInject(uri = "direct:test")
protected Endpoint inputTest;
#EndpointInject(uri = "mock:userEndpointOne")
protected MockEndpoint destinationOne;
#EndpointInject(uri = "mock:userEndpointTwo")
protected MockEndpoint destinationTwo;
#Test
public void testRoutingSampleToDestOne() throws Exception {
destinationOne.expectedMessageCount(1);
destinationTewo.expectedMessageCount(1);
String body = "Anything that can make your test useful"
sendBody(inputTest.getEndpointUri(), body);
assertMockEndpointsSatisfied();
}
#Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new PMRouteBuilder();
}
#Override
protected Properties useOverridePropertiesWithPropertiesComponent() {
Properties props = new Properties();
// Set your test properties here, those are examples
props.put("from.endpoint", "direct:test");
props.put("user.profile.endpoint.1", "mock:userEndpointOne");
props.put("user.profile.endpoint.2", "mock:userEndpointTwo");
return props;
}
You have to make your test to use the real beans as much as possible but sometimes when you cannot, you have to use a mock framework like Mockito to simulate method calls.
After that, you can execute your test in debug mode from your IDE and put breakpoints to the real processors you're using in the route.
I strongly recommend reading this article about Camel testing.
I postfixed the test class name with Test in sake of simplicity, but normally it should be named PMRouteBuilderIT as it test more than one class and should be executed in the Integration Test phase (mvn verify, with failsafe plugin).

Related

Spring with Apache Beam

I want to use Spring with Apache Beam that will run on Google Cloud Data flow Runner. Dataflow job should be able to use Spring Runtime application context while executing the Pipeline steps. I want to use Spring feature in my Apache Beam pipeline for DI and other stuff. After browsing hours on google, I couldn't find any post or documentation which shows Spring integration in Apache Beam. So, if anyone has tried spring with Apache beam, please let me know.
In main class i have initialised the spring application context but it is not available while execution of pipeline steps. I get null pointer exception for autowired beans. I guess the problem is, at runtime context is not available to worker threads.
public static void main(String[] args) {
initSpringApplicationContext();
GcmOptions options = PipelineOptionsFactory.fromArgs(args)
.withValidation()
.as(GcmOptions.class);
Pipeline pipeline = Pipeline.create(options);
// pipeline definition
}
I want to inject the spring application context to each of the ParDo functions.
The problem here is that the ApplicationContext is not available on any worker, as the main method is only called when constructing the job and not on any worker machine. Therefore, initSpringApplicationContext is never called on any worker.
I've never tried to use Spring within Apache Beam, but I guess moving initSpringApplicationContext in a static initializer block will lead to your expected result.
public class ApplicationContextHolder {
private static final ApplicationContext CTX;
static {
CTX = initApplicationContext();
}
public static ApplicationContext getContext() {
return CTX;
}
}
Please be aware that this alone shouldn't be considered as a best practice of using Spring within Apache Beam since it doesn't integrate well in the lifecycle of Apache Beam. For example, when an error happens during the initialization of the application context, it will appear in the first place where the ApplicationContextHolder is used. Therefore, I'd recommend to extract initApplicationContext out of the static initializer block and call it explicitly with regards to Apache Beam's Lifecycle. The setup phase would be a good place for this.

JAX-RS: How to run a method on start (without servlets)

I have a JAX-RS (Jersey) server with which I register and bind my stuff.
I want to print a banner when the server starts up. I want to do this using the JAX-RS framework not the web server's platform (i.e., no Jetty, Netty, Thorntail, etc hooks).
I saw the following which mentions the tried and true Servlet way of doing things:
Jax rs: How can I run a method automatically everytime my server restarts? , but that does not work because I am not running a servlet container in my server so that lifecycle call is never made.
I figured there must be a JCA-ish type object that I can register with Application/ResourceConfig that has such a lifecycle call, but I am unable to even find any kind of list of the things you can actually register.
Not to complain (but I will), but I cannot decide if this is so difficult because when they moved the project to eclipse, they broke every hyperlink to the old official documentation or that it is simply so implicit, like Spring, that it only works by github'ing other people's code and realizing, 'oh, I did not know you could do that'.
Jersey has Event Listeners. You'll want to use the ApplicationEventListener and the ApplicationEvent.Type you'll probably want to listen for to print the banner is the INITIALIZATION_FINISHED
public class MyApplicationEventListener
implements ApplicationEventListener {
#Override
public void onEvent(ApplicationEvent event) {
switch (event.getType()) {
case INITIALIZATION_FINISHED:
printBanner();
break;
}
}
#Override
public RequestEventListener onRequest(RequestEvent requestEvent) {
return null;
}
}

How to Integration Test Spring Shell v2.x

The new Spring Shell docs don't seem to provide any examples of how to integration test CLI commands in a Spring Boot context. Any pointers or examples would be appreciated.
The method Shell#evaluate() has been made public and has its very specific responsibility (evaluate just one command) for exactly that purpose. Please create an issue with the project if you feel like we should provide more (A documentation chapter about testing definitely needs to be written)
Here is how I got this working.
You first need to override the default shell application runner to avoid getting stuck in the jline loop. You can do this by defining your own such as:
#Component
public class CliAppRunner implements ApplicationRunner {
public CliAppRunner() {
}
#Override
public void run(ApplicationArguments args) throws Exception {
//do nothing
}
}
Note that you will have to associate this custom Application runner against a "Test" profile so it overrides only during integration testing.
If you want to test a shell command "add 1 3", you then can write a test like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest(classes =CliConfig.class)
public class ShellCommandIntegrationTest {
#Autowired
private Shell shell;
#Test
public void runTest(){
Object result=shell.evaluate(new Input(){
#Override
public String rawText() {
return "add 1 3";
}
});
DefaultResultHandler resulthandler=new DefaultResultHandler();
resulthandler.handleResult(result);
}
}
Note that the above test does not Assert anything. You will probably have to write your own little implementation of the ResultHandler interface that deals with parsing/formatting of the result so that it can be asserted.
Hope it helps.
Spring Shell 2.0.1 depends on Spring Boot 1.5.8, which in turn depends on Spring Framework 4.3.12. This makes researching how to implement tests challenging, since the latest version of Spring Shell does not depend on the latest versions of other Spring libraries. Take a look at my example project, sualeh/spring-shell-2-tests-example which has example unit, functional and integration tests for a sample Spring Shell application.

How to refresh the URI end points in route builder using Apache Camel periodically?

I have a requirement where by the application will need to be periodically refreshed to subscribe from different end points. I am using Apache Camel for orchestration and I am comfortable subscribing to an end point.
I have a routebuilder class as follows:
public class SampleRouteBuilder extends RouteBuilder {
#Override
public void configure() throws Exception {
String... subscriptionTopicUris = someService.getUris();
// Simple logic - read from URIs and write to topic
from(subscriptionTopicUris) //
.to(destinationUri) //
.routeId("SAMPLE_ROUTE_ID");
}
}
I run a scheduled job with a given time interval and I remove the route from Camel Context, stop the context and add it back and start the context. However, the configure method is not fired on starting the context and hence the service (someService) possibly returning a different list of URIs is never fired.
How do I reload the route?
I am using Spring, Apache Camel and annotation based approach and this is a web application running in jetty.
Thanks

Unit testing with Spring and the Jersey Test Framework

I'm writing some JUnit-based integration tests for a RESTful web service using JerseyTest. The JAX-RS resource classes use Spring and I'm currently wiring everything together with a test case like the following code example:
public class HelloResourceTest extends JerseyTest
{
#Override
protected AppDescriptor configure()
{
return new WebAppDescriptor.Builder("com.helloworld")
.contextParam( "contextConfigLocation", "classpath:helloContext.xml")
.servletClass(SpringServlet.class)
.contextListenerClass(ContextLoaderListener.class)
.requestListenerClass(RequestContextListener.class)
.build();
}
#Test
public void test()
{
// test goes here
}
}
This works for wiring the servlet, however, I'd like to be able to share the same context in my test case so that my tests can have access to mock objects, DAOs, etc., which seems to call for SpringJUnit4ClassRunner. Unfortunately, SpringJUnit4ClassRunner creates a separate, parallel application context.
So, anyone know how can I create an application context that is shared between the SpringServlet and my test case?
Thanks!
Override JerseyTest.configure like so:
#Override
protected Application configure() {
ResourceConfig rc = new JerseyConfig();
rc.register(SpringLifecycleListener.class);
rc.register(RequestContextFilter.class);
rc.property("contextConfigLocation", "classpath:helloContext.xml");
return rc;
}
For me the SpringServlet was not required, but if you need that you may be able to call rc.register for that too.
I found a couple of ways to resolve this problem.
First up, over at the geek#riffpie blog there is an excellent description of this problem along with an elegant extension of JerseyTest to solve it:
Unit-testing RESTful Jersey services glued together with Spring
Unfortunately, I'm using a newer version of Spring and/or Jersey (forget which) and couldn't quite get it to work.
In my case, I ended up avoiding the problem by dropping the Jersey Test Framework and using embedded Jetty along with the Jersey Client. This actually made better sense in my situation anyway since I was already using embedded Jetty in my application. yves amsellem has a nice example of unit testing with the Jersey Client and embedded Jetty. For Spring integration, I used a variation of Trimbo's Jersey Tests with Embedded Jetty and Spring

Resources