How can I get a notification when a CamelContext is stopped, the API has addStartupListener but nothing similar for when the context is stopped?
This question was also asked on the Camel mailing list
http://camel.465427.n5.nabble.com/Notification-on-CamelContext-stop-tp5729300.html
There is several ways. One as Evgeniy Dorofeev shows with the lifecycle strategy.
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/spi/LifecycleStrategy.html
And another is the event notifier which is using Event objects and has more events than the lifecycle strategy. For example as shown in this example: http://camel.apache.org/eventnotifier-to-log-details-about-all-sent-exchanges.html
And if you use Spring or Blueprint XML then you can configure them by defining a bean and Camel will pick it up as documented here: http://camel.apache.org/advanced-configuration-of-camelcontext-using-spring.html
this is one of the ways
camelContext.addLifecycleStrategy(new LifecycleStrategySupport() {
#Override
public void onContextStop(CamelContext context) {
}
});
see more in Claus Ibsen's answer, he is the author of Camel in Action http://www.manning.com/ibsen/
Related
For an application I'm using spring-boot, spring-batch and spring-integration.
My problem is that, on startup, when everything is auto configured and auto wired, my spring-integration #MessageEndpoints, connected to RabbitMQ, are starting to process available messages on its queues. Based on the received messages, these #MessageEndpoints are trying to start specific spring-batch Jobs, looked up, through it's auto wired JobRegistery.
Because of all the auto configuration not all jobs are yet registered to the used JobRegistery! (A few seconds later they will be).
After all spring-batch jobs are registered to the JobRegistery then the #MessageEndpoints should start. Is this possible? Maybe thought the ContextRefreshEvent?
I just looked at the code and the problem appears to be that the AutomaticJobRegistrar uses the context refreshed event to load the jobs; it should really implement SmartLifecycle and start in an "early-ish" phase.
The spring integration components implement SmartLifecycle and inbound endpoints (such as the rabbit endpoints) start in a late phase.
I suggest you open a JIRA against Batch - there's a TODO in the AutomaticJobRegistrar code:
// TODO: With Spring 3 a SmartLifecycle is started automatically
As a work-around, you could set autoStartup to false on the inbound adapter(s) and use your own event listener to start them on the context refreshed event.
The listener should implement Ordered; the AutomaticJobRegistrar is Ordered.LOWEST_PRECEDENCE so you want to run with a higher precedence (lower priority).
Gary Russell thank you for your push in the right direction! I have solved it as follow:
Disable autostart for the inbound channels in my integration XML.
After SpringApplication.run() if start manually these inbound channels, found through getBeansOftype().
.
public static void main(final String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(SpringBatchApplication.class, args);
startInboundChannelAdapters(context);
}
private static void startInboundChannelAdapters(ConfigurableApplicationContext context) {
Map<String, AmqpInboundChannelAdapter> adapters = context.getBeansOfType(AmqpInboundChannelAdapter.class);
adapters.forEach((name, adapter) -> {
if (!adapter.isRunning()) {
adapter.start();
}
});
}
Does anyone have an example of using the EventBusBuilder for greenrobot's Eventbus?
I have an app that is using EventBus.getDefault() all over the place, but now I want to configure that bus to stop sending the no subscriber message. It is discussed here: https://github.com/greenrobot/EventBus/blob/master/HOWTO.md
Since the code to configure an EventBus, seems to return an instance of the bus itself (from the doc above):
EventBus eventBus = EventBus.builder().logNoSubscriberMessages(false).sendNoSubscriberEvent(false).build();
I am just not sure where to put that instance! Do I have to make a singleton somewhere to include it, just like the EventBus library itself does? And then re-plumb all of my calls to EventBus.getDefault() to my own class?
Just a little confused. Help is appreciated.
Thanks,
Judd
You don't read the document carefully. Here is what you want:
EventBus.builder().logNoSubscriberMessages(false).
sendNoSubscriberEvent(false).installDefaultEventBus();
Then EventBus.getDefault() should work with this config
You'll have to excuse me if I'm describing this incorrectly, but essentially I'm trying to get a service-like class to be instantiated just once at server start and to sort of "exist" in the background until it is killed off at server stop. At least from what I can tell, this is not exactly the same as a typical servlet (though I may be wrong about this). What's even more important is that I need to also be able to access this service/object later down the line.
As an example, in another project I've worked on, we used the Spring Framework to accomplish something similar. Essentially, we used the configuration XML file along with the built-in annotations to let Spring know to instantiate instances of some of our services. Later down the line, we used the annotation #Autowired to sort of "grab" the object reference of this pre-instantiated service/object.
So, though it may seem against some of the major concepts of Java itself, I'm just trying to figure out how to reinvent this wheel here. I guess sometimes I feel like these big app frameworks do too much "black-box magic" behind the scenes that I'd really like to be able to fine-tune.
Thanks for any help and/or suggestions!
Oh and I'm trying to run this all from JBoss 6
Here's one way to do it. Add a servlet context listener to your web.xml, e.g.:
<listener>
<listener-class>com.example.BackgroundServletContextListener</listener-class>
</listener>
Then create that class to manage your background service. In this example I use a single-threaded ScheduledExecutorService to schedule it to run every 5 minutes:
public class BackgroundServletContextListener implements ServletContextListener {
private ScheduledExecutorService executor;
private BackgroundService service;
public void contextInitialized(ServletContextEvent sce) {
service = new BackgroundService();
// setup single thread to run background service every 5 minutes
executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(service, 0, 5, TimeUnit.MINUTES);
// make the background service available to the servlet context
sce.getServletContext().setAttribute("service", service);
}
public void contextDestroyed(ServletContextEvent sce) {
executor.shutdown();
}
}
public class BackgroundService implements Runnable {
public void run() {
// do your background processing here
}
}
If you need to access the BackgroundService from web requests, you can access it through the ServletContext. E.g.:
ServletContext context = request.getSession().getServletContext();
BackgroundService service = (BackgroundService) context.getAttribute("service");
Have you considered using an EJB 3.1 Session bean? These can be deployed in a war file, and can be annotated with #Singleton and #Startup.
A number of annotations available with EJB 3.1 are designed to bring Spring goodies into the Java EE framework. It may be the re-invention you're considering has been done for you.
If you must roll your own, you can create a servlet and configure it start up when the application does using load-on-startup. I built a system like that a few years ago. We then used the new(ish) java.util.concurrent stuff like ExecutorService to have it process work from other servlets.
More information about what you're trying to do, and why the existing ways of doing things is insufficient, would be helpful.
You can use messaging for that. Just send message to the queue, and let the message listener do the processing asynchronously in the background.
You can use JMS for the implementation, and ActiveMQ for the message broker.
Spring has JMSTemplate, JMSGateWaySupport API to make JMS Implementation simple
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jms.html
I was going through the Spring documentation on JMX and came across the following paragraph:
By configuring NotificationListeners in place, every time a JMX Notification is broadcast
from the target MBean (bean:name=testBean1),the ConsoleLoggingNotificationListener bean
that was registered as a listener via the notificationListenerMappings property will be
notified.
And this is how the ConsoleLoggingNotificationListener is implemented:
public class ConsoleLoggingNotificationListener
implements NotificationListener, NotificationFilter {
public void handleNotification(Notification notification, Object handback) {
System.out.println(notification);
System.out.println(handback);
}
public boolean isNotificationEnabled(Notification notification) {
return AttributeChangeNotification.class.isAssignableFrom(notification.getClass());
}
}
But, since I am a newbie, I want to know when is a JMX Notification broadcasted? Is it when the a JMX-exposed attribute's value is changed?
Please help me know this.
Thanks!
I guess this question has nothing to do with Spring per se. If I understand correctly the notifications which are meant here are javax.management.Notification objects.
I haven't read it but at the first glance this article seems to cover the topic in a quite extensive manner.
And, as you can see attribute change is one of the events when a notification is broadcast.
Maybe it is a bit too late.. however since this question has no accepted answer I'll post my answer.
Spring documentation also says:
The key interface in Spring's JMX notification publication support is the NotificationPublisher interface (defined in the org.springframework.jmx.export.notification package). Any bean that is going to be exported as an MBean via an MBeanExporter instance can implement the related NotificationPublisherAware interface to gain access to a NotificationPublisher instance.
The answer you are looking for is in the final sentence of above excerpt
Ref: http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch24s07.html#jmx-notifications-listeners
I have recently discovered message selectors
#ActivationConfigProperty(
propertyName="messageSelector",
propertyValue="Fragile IS TRUE")
My Question is: How can I make the selector dynamic at runtime?
Lets say a consumer decided they wanted only messages with the property "Fragile IS FALSE"
Could the consumer change the selector somehow without redeploying the MDB?
Note: I am using Glassfish v2.1
To my knowledge, this is not possible. There may be implementations that will allow it via some custom server hooks, but it would be implementation dependent. For one, it requires a change to the deployment descriptor, which is not read after the EAR is deployed.
JMS (Jakarta Messaging) is designed to provide simple means to do simple things and more complicated things to do more complicated but less frequently needed things. Message-driven beans are an example of the first case. To do some dynamic reconfiguration, you need to stop using MDBs and start consuming messages using the programmatic API, using an injected JMSContext and topic or queue. For example:
#Inject
private JMSContext context;
#Resource(lookup="jms/queue/thumbnail")
Queue thumbnailQueue;
JMSConsumer connectListener(String messageSelector) {
JMSConsumer consumer = context.createConsumer(logTopic, messageSelector);
consumer.setMessageListener(message -> {
// process message
});
return consumer;
}
You can call connectListener during startup, e.g. in a CDI bean:
public void start(#Observes #Initialized(ApplicationScoped.class) Object startEvent) {
connectListener("Fragile IS TRUE");
}
Then you can easily reconfigure it by closing the returned consumer and creating it again with a new selector string:
consumer.close();
consumer = connectListener("Fragile IS FALSE");