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

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

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;
}
}

Best way to handle Content Provider failures in Java Spring Application

I have Spring Web Application, which invokes content provider for some data. Its becoming common issue that content provider service is failing and app is becoming unresponsive. What would be best approach or design to check that content provider service is up or down at application level and handle it appropriately.
You can use circuit breaker pattern and Hystrix library.
It will monitor the method annotated with #HystrixCommand and if the failures amount to a certain threshold, it will start redirecting the calls to a fallbackMethod, allowing the continuation of service, and leaving you time to recover from failure.
A simple snippet that shows it in action is as follows:
#Service
public class BookService {
...
#HystrixCommand(fallbackMethod = "reliable")
public String readingList() {
...
}
public String reliable() {
...
}
}

How to debug Camel Route builder in eclipse IDE?

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).

How to delay spring beans startup?

Having spring application (actually grails app) that runs apache-activemq server as spring bean and couple of apache-camel routes. Application use hibernate to work with database. The problem is simple. Activemq+Camel starts up BEFORE grails injects special methods into hibernate domain objects (actually save/update methods etc). So, if activemq already has some data on startup - camel starts processing messages w/o having grails DAO methods injected. This fails with grails.lang.MissingMethodException. Must delay activemq/camel startup before Grails injects special methods into domain objects.
If all these are defined as spring bean, you can use
<bean id="activeMqBean" depends-on="anotherBean" />
This will make sure anotherBean is initialized before activeMqBean
can you move MQ managment into a plugin? It would increase modularity and if you declare in plugin-descriptor
def loadAfter = ['hibernate']
you should have the desired behavior. Works for JBPM plugin
I am not sure in your case but lazy loading may also help e.g.
<bean id="lazybean" class="com.xxx.YourBean" lazy-init="true">
A lazily-initialized bean indicates to the IoC container to create bean instance when it is first requested. This can help you delay the loading of beans you want.
I know this question is pretty old, but I am now facing the same problem in the year 2015 - and this thread does not offer a solution for me.
I came up with a custom processor bean having a CountDownLatch, which I count down after bootstrapping the application. So the messages will be idled until the app has started fully and its working for me.
/**
* bootstrap latch processor
*/
#Log4j
class BootstrapLatchProcessor implements Processor {
private final CountDownLatch latch = new CountDownLatch(1)
#Override
void process(Exchange exchange) throws Exception {
if(latch.count > 0){
log.info "waiting for bootstrapped # ${exchange.fromEndpoint}"
latch.await()
}
exchange.out = exchange.in
}
/**
* mark the application as bootstrapped
*/
public void setBootstrapped(){
latch.countDown()
}
}
Then use it as a bean in your application and call the method setBootstrapped in your Bootstrap.groovy
Then in your RouteBuilder you put the processor between your endpoint and destination for all routes you expect messages coming in before the app has started:
from("activemq:a.in ").processRef('bootstrapProcessor').to("bean:handlerService?method=handle")

Resources