Sometimes we need to be able to change the behavior of our application without a restart.
JMX, apart from its monitoring capabilities, is a perfect solution for this.
Spring provides great JMX that will ease our task.
Let's start with a simple service, which behavior we will change at runtime.
DiscountService calculates discount based on a globalDiscount - it's value is harcoded for simplicity purposes, it would probably be read from some configuration file or database in more realistic example.
First of all, in order to expose methods to manage globalDiscount we need to add @ManagedResource annotation to our class and add the methods with @ManagedOperation annotation.
We could also use @ManagedAttribute if we would treat these methods as simple getter and setter for globalDiscount.
Class with needed methods and annotations would look like:
In Spring configuration we just need to define the bean for DiscountService and enabling exporting MBeans with MBean server.
We can run the application with:
Now we're ready to manage our service with jconsole:
Our service is exposed locally, but if we want to be able to connect to it remotely, we will need to add following beans to the Spring configuration:
Service is now exposed via RMI.
We can invoke the exposed methods programmatically, which allows us to write some scripts and manage services without using jconsole.
Let's write an integration test to check that it works correctly.
We will need a Spring config for the test with the RMI client.
The test will increment the value of globalDiscount.
Take a closer look at exposed methods invocation, which is very cumbersome, especially if the method has parameters.
The whole project can be found at github.