Dynamically instantiate JMX MBeans - java

I have a white label/multi-tennant server providing the same services, but branded for multiple customers. I want to use JMX to monitor the status of each customer (nbr of calls, nbr of errors, etc).
I know how to use Spring JMX annotations to wire up my POJOs (per the code below). What I really want is one MBean per customer, but because the customers are dynamically loaded up at server startup time I don't know how to wire this up using annotations.
Is this possible? If not, is it possible to instantiate my MBeans at startup time ?
#Component
#ManagedResource(objectName = "TravelAPI:name=Customer")
public class CustomerStatus extends GeneralCustomerStatus {
#ManagedAttribute
String customerId;
.
.
.
}

What I really want is one MBean per customer, but because the customers are dynamically loaded up at server startup time I don't know how to wire this up using annotations.
What we do is to have the entity that is actually instantiating your dynamic objects, register them with JMX via the MBeanExporter. We inject the MBeanExporter instance into the factory entity and then call MBeanExporter.registerManagedResource(...).
For example we do something like:
...
mbeanExporter.registerManagedResource(beanInstance);
...
#Required
public void setMbeanExporter(MBeanExporter mbeanExporter) {
this.mbeanExporter = mbeanExporter;
}
We also use a NamingPolicy so that the dynamic objects can provide their own names to make them unique. See more details about that here:
Change #ManagedResource objectName dynamically
As an aside, my SimpleJMX package has some code to help with dynamic objects.

Related

Options for dynamic properties in Spring Boot

I have an application with some externalized configuration in the form of properties. I would like the application to react to a change of such properties without a restart or full context refresh.
I am not clear what my options are.
Artificial example: the application implements a service that receives requests and decides whether to queue or reject them. The maximum size of the queue is a property.
final int queueMaxSize = queueProperties.getMaxSize();
if (queue.size() >= queueMaxSize) { //reject }
Where QueueProperties is a class annotated with #ConfigurationProperties.
#ConfigurationProperties(prefix = "myapp.limits.queue")
#Getter
#Setter
public class QueueProperties {
public int maxSize = 10;
}
This works as far as allowing me to control behavior via system properties, profiles, etc.
However, I would like to be able to change this value without releasing/deploying/restarting/refreshing the application.
My application already uses Archaius.
If I push a new value for this property using our internal infrastructure, i can see the application Spring Environment does receive the new value.
(e.g., /admin/env reflects the value and changes dynamically).
The part I'm not clear on is: how to make my service react to the change of value in the environment?
I found two ways, but they seem hairy, I wonder if there are better options. I expected this to be a common problem with a first class solution in the Spring ecosystem.
Hacky solution #1:
#Bean
#Scope("prototype")
#ConfigurationProperties(prefix = "myapp.limits.queue")
QueueProperties queueProperties() {
return new QueueProperties();
}
And inject this into the service using the properties as Provider<QueueProperties> and use it as queuePropertiesProvider.get().getMaxSize().
This works but has a few side-effects I'm not a fan of:
ConfigurationProperties annotation moved from the class to the bean definition
A new QueueProperties object is created and bound to values for every request coming in
Provider might throw on get()
Invalid values are not detected until the first request comes in
Hacky solution #2:
Don't annotate my properties class with ConfigurationProperties, inject the Spring environment at construction time. Implement the getters as such:
int getMaxSize() {
return environment.getProperty("myapp.limits.queue", 10);
}
This also works ok in terms of behavior. However
- This is not annotated as property (unlike the rest of the properties classes in this large project, makes it harder to find)
- This class does not show up in /admin/configprops
Hacky solution #3:
Schedule a recurring task that uses Environment to update my singleton QueueProperties bean.
Any further ideas/suggestions/pointers?
Is there a canonical/recommended way to do this that does not have the shortcoming of my solutions above?

MBeans not appearing in JConsole

I´m developping a java Web Application in Netbeans. Now I want to monitorize my app using jconsole.
public static void main(String[] args) throws Exception {
String name="Example";
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
ObjectName object = new ObjectName("org.javalobby.tnt.jmx:type=example");
mbs.registerMBean(name, object);
}
I also add the following lines to glassfish:
-Djava.rmi.server.hostname=myhost
-Dcom.sun.management.jmxremote.port=8686
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
The problem is my beans do not appear on JConsole. What I´m doing wrong?
You are passing string object as an MBean object. Follow the documentation as below.
Using this blog link to create a sample test mbean.
"An MBean is a managed Java object, similar to a JavaBeanTM, that
follows the design patterns set forth in the instrumentation level of
the JMX specification. An MBean can represent a device, an
application, or any resource that needs to be managed. MBeans expose a
management interface: a set of readable and/or writable attributes and
a set of invokable operations, along with a self-description.
A standard MBean is defined by writing a Java interface called
SomethingMBean and a Java class called Something that implements that
interface. Every method in the interface defines either an attribute
or an operation in the MBean. By default every method defines an
operation. Attributes and operations are simply methods which follow
certain design patterns. A standard MBean is composed of the MBean
interface which lists the methods for all exposed attributes and
operations, and the class which implements this interface and provides
the functionality of the instrumented resource."

How to Create a bean validation framework using Spring

I am having bean AddressBean, which has some properties like addressLine1, city etc.
Before persisting it to DB using AddressBeanService, I am prevalidating it, and after saving, i am post validating it, using preValidate and postValidate function in ValidateAddressService. And all this i am triggering from a AddressBeanHelper class.
class AddressBeanHelper{
AddressBean bean =null;
AddressBeanHelper(AddressBean bean){
this.bean=bean;
}
ValidationService validate=new ValidateAddressService();
function doStuff(){
validate.preValidateAddressBean (bean);
//business logic for AddressBean
validate.preValidateAddressBean (bean);
}
}
class ValidateAddressService implements ValidationService <AddressBean>{
preValidateAddressBean (AddressBean bean){
//here is the issue
}
preValidateAddressBean (AddressBean bean){
//here is the issue
}
}
I want some framework or trick in spring by which i just need to write generic code in validation functions and externalize my validation rule outside the code itself.
Like a rule engine which can automatically validates each and every property of bean.
currently my application infrastructure is spring/hibernate for server side, jsp/jquery on client side and deployment server is on heroku.
Have a look at this one:
http://hillert.blogspot.com/2011/12/method-validation-with-hibernate.html
It supports JSR-303, so its a standard. Its very easy to implement, and it supports, custom and some predefined ready to use validators.
You can also find some references here:
http://java.dzone.com/articles/method-validation-spring-31

Conditionally creating beans in spring

Right now I'm exposing the service layer of my application using spring remoting's RMI/SOAP/JMS/Hessian/Burlap/HttpInvoker exporters. What I'd like is to allow the user to somehow define which of these remoting mechanisms they'd like enabled (rather than enabling all of them), then only create those exporter beans.
I was hoping that spring's application context xml's had support for putting in conditional blocks around portions of the xml. However, from what I've seen so far there's nothing in the standard spring distribution that allows you to do something like this.
Are there any other ways to achieve what I'm trying to do?
I am going to assume that you are looking to configure your application based on your environment, as in... for production I want to use this beans, in dev these other ...
As Ralph is saying, since Spring 3.1 you have profiles... But the key, is that you understand that you should put your environment based beans in different configuration files... so you could have something like dev-beans.xml, prod-beans.xml... Then in your main spring file, then you just invoke the appropriate one based on the environment that you are using... So profiles are only technique to do so... But you can also use other techniques, like have a system environmental variable, or pass a parameter in your build to decide which beans you want to use
You could realize this by using a Spring #Configuration bean, so you can construct your beans in java code. (see http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-java)
#Configuration
public class AppConfig {
#Bean
public MyService myService() {
if ( userSettingIshessian ) {
return new HessianExporter();
}else {
return new BurlapExporter();
}
}
}
Of course you need to get the user setting from somewhere, a system parameter would be easy, or config file, or something else.
Spring 3.1 has the concept of Profiles. My you can use them.

How to expose a Stateless EJB method as MBean (on Jboss)?

I have a stateless EJB (3) that uses internal cache which is refreshed automatically every 24 hours. I would like to expose a MBean method to be able to force cache expiration or even cache reload on this EJB via JMX console on Jboss 4.2.
Can someone share an example on how to code this scenario? I'm totally new to JMX when it comes to creating my own beans.
Should I create an MBean that calls my EJB or is it possible to expose a specific EJB method as an Mbean interface by using annotation on EJB itself?
EJB looks like this:
#Stateless
#Local(BusinessCalendar.class)
public class BusinessCalendarBean implements BusinessCalendar {
synchronized private LocalDateKitCalculatorsFactory getCalculatorFactory() {
LocalDateKitCalculatorsFactory ldkc = (LocalDateKitCalculatorsFactory) CacheService.get(CACHE_KEY);
if (ldkc == null) {
ldkc = getCalculatorFactory();
CacheService.put(CACHE_KEY, ldkc);
}
return ldkc;
}
public function expireCache() {
// I would like to expose this as JMX managed method
}
...
}
Update:
This is surely valid for WildFly 10+, jBOSS EAP 6.x or 7.x. But I suspect the mechanisms are no longer proprietary and shall work very similarly in other app servers.
JBoss specific annotations #Service / #Management were removed when JavaEE 6 standardized Singletons. A MBean (always a singleton so that all JMX clients see the same consistent JMX data application-wide) becomes an EE6+ Singleton exposed via JMX as follows:
define an interface with a name ending in "...MXBean" (compulsory)
create a #Singleton and #Startup class that implements this interface
define #PostConstruct and #PreDestroy methods to register/unregister the MBean
the register/unregister code is like:
objectName = new javax.management.ObjectName("com.acme.example.jmx:type=" + this.getClass().getName());
platformMBeanServer = java.lang.management.ManagementFactory.getPlatformMBeanServer();
platformMBeanServer.registerMBean(this, objectName);
The getters/setters defined in your "...MXBean" interface become JMX attributes, other methods are mapped to operations as specified in JMX Specifications under "lexical design patterns"
Have you looked at the online JBoss configuration guide yet? This may be of some help:
http://www.redhat.com/docs/en-US/JBoss_Enterprise_Application_Platform/4.2.0.cp08/html/Server_Configuration_Guide/EJB3_Services-Message_Driven_Beans.html

Categories