Managing multiple applications & classloaders

Hi,

I'm currently investigating different solutions to manage our applications remotely (and from a single point), and JMX sounds like something that might satisfy our needs. So far it seems to do what I want, but there are some areas that are still unclear. Some clarifications will be appreciated.

Let's say I want to manage different applications using JMX, and that these applications are made of components that are wrapped as MBeans. So I will register all the mbeans of application A in a particular domain, all the mbeans of application B in another domain, and so on. This way I can limit the client to only manage mbeans from a particular application.

However, what I realize is that if I do that, all the mbeans will share the same classloader, which is bad. I don't want application A component to see application B component, of course, neither do I want application A component to access application B ressources.

I saw in the documentation that when you register (or create) a mbean on the mbeanServer, you can pass the ObjectName of a classloader, and that will create the mBean using that classloader. Does that mean that I have to handle classloaders by hand, manually instanciating classloaders before attempting to register my applications' components, passing a different one for each application?

At first I thought that using different domains for components would use different classloaders, but it doesn't seem to be the case.

Actually, as I'm typing, I'm realizing that using their own classloader won't be enough. Actually I don't want component from domain A to be able to invoke mbeans from domain B.

So to summarize my question: Is there an elegant way to automatically encapsulate some mbeans so that they are isolated from others?

Thanks

[1834 byte] By [Will30a] at [2007-11-27 3:23:41]
# 1
Would registering the MBeans in separate MBeanServers solve your problem? If you want to prevent direct method calls, it may not solve your problem, but it may if you are trying to prevent calls using jmx api.alper
aakturea at 2007-7-12 8:26:28 > top of Java-index,Core,Monitoring & Management...
# 2

Hi,

There are several layers of answers to your question.

Part 1:

--

If you want to prevent MBeans from different application to see each other

then using one MBeanServer per application seems like a good idea.

To expose these MBeans to remote clients, you would then normally need to

create one connector server per MBeanServer.

If having one connector server per MBeanServer is not desirable, then you could

instead use "cascading". You could write your own,

http://weblogs.java.net/blog/emcmanus/archive/2007/02/cascading_its_a.html

or use the OpenDMK cascading feature http://opendmk.dev.java.net/

(see CascadingAgent and MBeanServerConnectionFactory).

The idea here would be to create one MBeanServer per application, and then "mount"

all these MBeanServers in a master MBeanServer. You would then only need to create

a single connector server to expose your "master" MBeanServer.

MBeans from application A (a1 and a2) would only see MBeans from application A

(a1 and a2). MBeans from application B (b1, b2, b3) would only see MBeans from

application B (b1, b2, b3). However a client of the master MBeanServer would see

all MBeans: (A/a1, A/a2, B/b1, B/b2, B/b3).

Note: Cascading/Federation of MBeanServers is also discussed for standardization

in JMX 2.0 (JSR 255) expert group. Eamonn McManus will say a few words

about this in his talk at Java One tomorrow.

http://weblogs.java.net/blog/emcmanus/archive/2007/04/jmx_technology_2.html

Part 2:

Concerning classloaders, if you create an MBean, then register it using registerMBean,

e.g.:

1:My my = new MyMBean();

2:ObjectName myMBeanName = new ObjectName("my:type=My,name=x");

3:server.registerMBean(my, myMBeanName);

then you don't need to specify any classloader to the MBeanServer: the classloader

of your MBean is the classloader used to load the class MyMBean at line 1.

In other words: all depends on how/where these three lines of codes are executed, and

you can usually control that.

Another possibility is to use a PrivateMLet. Create a PrivateMLet that points to the jars

of application A, and register it in the MBeanServer you created for application A.

Then, for each MBean of application A you want to create use the server.createMBean

form that takes a loader name, the loader name being that of the PrivateMLet for

application A.

http://java.sun.com/javase/6/docs/api/javax/management/loading/PrivateMLet.html

1:PrivateMLet mletA = new PrivateMLet(...);

2:ObjectName loaderForA = new ObjectName("my:type=MLet,name=A");

3:server.registerMBean(mletA, loaderForA); // register the MLet for A

4:ObjectName myMBeanName = new ObjectName("my:type=My,name=x");

5:server.createMBean("my.MyClass",myMBeanName,loaderForA,...);

<a href="http://java.sun.com/javase/6/docs/api/javax/management/MBeanServer.html#createMBean(java.lang.String,%20javax.management.ObjectName,%20javax.management.ObjectName)">createMBean(className,mbeanName,loaderName)</a>

<a href="http://java.sun.com/javase/6/docs/api/javax/management/MBeanServer.html#createMBean(java.lang.String,%20javax.management.ObjectName,%20javax.management.ObjectName,%20java.lang.Object[],%20java.lang.String[])">createMBean(className,mbeanName,loaderName,params,signature)</a>

Be careful that there are some security implication when creating an MLet.

If you expose MLet MBeans to remote clients you will probably want to limit/control their access by setting up the appropriate security when creating your connector server.

http://blogs.sun.com/lmalventosa/entry/jmx_authentication_authorization

Hope this helps,

-- daniel

JMX, SNMP, Java, etc...

http://blogs.sun.com/jmxetc

dfuchsa at 2007-7-12 8:26:28 > top of Java-index,Core,Monitoring & Management...
# 3

Hi,

Thanks a lot for your very complete and insightful response. That answers very well to my question. It removes some of the initial fears I had with JMX.

I will continue to play around with JMX with the new information you gave me, and if I have more questions, I will definitely come back here! There are some good and helpful folks around here!

Thanks again!

Will30a at 2007-7-12 8:26:28 > top of Java-index,Core,Monitoring & Management...
# 4

Hi again,

I played a little with PrivateMlet, as it seems to me that it's the best way to achieve classloader separation, but it doesn't seem to work as expected. Beside the javadoc, I haven't found any detailed info on how to use them, so a little bit of help would certainly be welcomed!

Here is what I do:

I have a main class that create the mBeanServer and creates two mbean. I want these beans to have separated classloader.

So I created two folders, folder1 and folder2, each one containing a different jar file. These two folders are not in the classpath of my main class. The two mBean are on the main class classpath. They are both at the root of my base directory (where the app runs).

Before creating my mbeans, I do something like that:

URL url1 = new File("folder1").toURI().toURL();

PrivateMLet mlet1 = new PrivateMLet(new URL[] {url1}, false);

ObjectName nameMLet1 = new ObjectName("my:type=MLet,name=1");

mBeanServer.registerMBean(mlet1, nameMLet1);

( For the URL, I tried too putting "folder1/[nameOfTheJar].jar", with the same result )

As I understand, this PrivateMLet is a classloader that should have my jar in its classpath. So after that I do this:

mBeanServer.createMBean([mbean classname], null, nameMLet1);

However, in my mbean I try to do, for exemple, a Class.forName("[name of a class in the jar]"), and I have a ClassNotFoundException.

Actually I was expecting this forName to work, while in my other mBean, where I don't define that jar in the PrivateMLet, I was expecting the error. That would prove that classloaders are separated.

So I suspect that I do something wrong (in fact I'm pretty sure :) ). Am I right thinking that the URL[ ] is used to define the classpath?

That's the only hurdle left in my path to JMX adoption :)

Thanks

Will30a at 2007-7-12 8:26:28 > top of Java-index,Core,Monitoring & Management...
# 5
I'm not sure if this could cause it, but did you try it with the class files not in jar files? i.e., just in the folders?
aakturea at 2007-7-12 8:26:28 > top of Java-index,Core,Monitoring & Management...
# 6
Nope, it's have the same behavior with classes not in a jar.
Will30a at 2007-7-12 8:26:28 > top of Java-index,Core,Monitoring & Management...
# 7

Hi,

I suggest you try the following:

final File myjar = new File("folder1/myjar.jar");

if (!myjar.canRead())

throw new IOException("folder1/myjar.jar: no such file");

URL url1 = myjar.toURI().toURL();

PrivateMLet mlet1 = new PrivateMLet(new URL[] {url1}, false);

ObjectName nameMLet1 = new ObjectName("my:type=MLet,name=1");

mBeanServer.registerMBean(mlet1, nameMLet1);

AFAIK, the URL must be similar to a 'classpath element', that is, it must be

either a jar file, or a directory that contains classes - like what you would

put in the classpath.

If the URL is a directory, then it must end with '/' (otherwise, it's assumed to

be a jar) - see <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/net/URLClassLoader.html#URLClassLoader(java.net.URL[])">API doc</a>.

Let me know if this works!

BTW - you could also take a look at what I did here (steps 3 and 4) - it certainly

did work for me:

http://blogs.sun.com/jmxetc/entry/tracing_jmx_what_s_going

BTW2 - you will find an example here

http://docs.sun.com/app/docs/doc/816-7609/6mdjrf877?a=view

-- daniel

JMX, SNMP, Java, etc...

http://blogs.sun.com/jmxetc

dfuchsa at 2007-7-12 8:26:28 > top of Java-index,Core,Monitoring & Management...