(beginner) return types of an MBean

I have an MBean interface which looks like this:

interface MyMBean

{

Host getHost( String name );

}

interface Host

{

Integer getId();

// ... other methods

}

On the server side, the implementation defines

class HostImplimplements Host

{

...

}

class MyMBeanImplimplements MyMBean

{

public Host getHost( String name )

{

returnnew HostImpl( ... );

}

}

When I invoke getHost( .. ), I get the exception

Caused by: java.rmi.UnmarshalException: error unmarshallingreturn; nested exception is:

java.lang.ClassNotFoundException: com.raverun.demo.HostImpl (no security manager: RMIclass loader disabled)

So it is not possible to just provide the interfaces to the client code ? And I am forced to have to also provide the implementation classHostImpl to the classpath of my client code ?

Thanks

Message was edited by:

garedunord

[1662 byte] By [garedunorda] at [2007-11-27 10:48:54]
# 1

This is the way Java serialization works. What is serialized is the concrete Java object, which means that the object's class must be present in order to deserialize.

If you are using Java SE 6, then you can use MXBeans to avoid this problem. See the documentation for javax.management.MXBean, and also the article at <http://java.sun.com/developer/technicalArticles/J2SE/mxbeans/>.

Regards,

amonn McManus -- JMX Spec Lead -- http://weblogs.java.net/blog/emcmanus

emcmanusa at 2007-7-29 11:15:46 > top of Java-index,Core,Monitoring & Management...
# 2

Thanks amonn.

After placing the implementation classes on the client, I still have the same problem.

Run#1

MBeanServerConnection mbsc = ...;

MyMBean proxy = ( MyMBean ) MBeanServerInvocationHandler.newProxyInstance

( mbsc, mBeanName, MyMBean.class, true );

proxy.getHost( "foo" ); // throws java.rmi.UnmarshalException (caused: ClassNotFoundException).

Run #2

MBeanServerConnection mbsc = ...;

MyMBean proxy = ( MyMBean ) MBeanServerInvocationHandler.newProxyInstance

( mbsc, mBeanName, MyMBean.class, true );

mbsc.invoke( mBeanName, "getHost", params, signature ); // direct call

proxy.getHost( "foo" ); // runs fine NOW!

Noticed that the proxy invocation runs fine if I precede it by directly calling mbsc.invoke( ... ). Is there some magic in the MBeanServerConnection.invoke() that caused the ClassLoader to load the HostImpl; whereas the proxy invocation does not ? I'm stumped.

garedunorda at 2007-7-29 11:15:46 > top of Java-index,Core,Monitoring & Management...
# 3

By the way, I'm using Java SE 5.

garedunorda at 2007-7-29 11:15:46 > top of Java-index,Core,Monitoring & Management...
# 4

I have solved my problem. See code below. The trick was to force the loading of the relevant return values.

MBeanServerConnection mbsc = ...;

MyMBean proxy = ( MyMBean ) MBeanServerInvocationHandler.newProxyInstance

( mbsc, mBeanName, MyMBean.class, true );

Class.forName( "com.raverun.demo.HostImpl", false, Thread.currentThread().getClassLoader() );

proxy.getHost( "blah" );

garedunorda at 2007-7-29 11:15:46 > top of Java-index,Core,Monitoring & Management...
# 5

For me, something is very wrong if it only works when you do this. I don't see how it can make any difference whether you do the Class.forName or not. RMI should not care whether the HostImpl class has already been loaded or not. I'm concerned that you might be building a very fragile application here.

What happens if you change the third parameter of Class.forName into proxy.getClass().getClassLoader()? That is more correct than using the context class loader.

emcmanusa at 2007-7-29 11:15:46 > top of Java-index,Core,Monitoring & Management...