Invoking EJB via remote interface with argument of value boolean.class results
in ClassNotFoundException
--------------------------------------------------------------------------------------------------------
Key: OPENEJB-832
URL: https://issues.apache.org/jira/browse/OPENEJB-832
Project: OpenEJB
Issue Type: Bug
Components: server
Affects Versions: 3.0
Reporter: Martin Vysny
When invoking an EJB remotely using its remote interface, for example method
someMethod(Class c) and the parameter value is boolean.class (or int.class or
the like), the following exception occurs:
Caused by: java.rmi.RemoteException: Container has suffered a SystemException;
nested exception is:
java.rmi.RemoteException: The server has encountered a fatal error:
Error caught during request processing java.lang.ClassNotFoundException:
boolean; nested exception is:
java.lang.ClassNotFoundException: boolean
at
org.apache.openejb.client.EJBObjectHandler._invoke(EJBObjectHandler.java:171)
at
org.apache.openejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:117)
at
org.apache.openejb.client.proxy.Jdk13InvocationHandler.invoke(Jdk13InvocationHandler.java:52)
at $Proxy56.invokeServant(Unknown Source)
at
com.whitestein.fe.client.ejb.JndiFeClient.invokeServant(JndiFeClient.java:170)
... 21 more
Caused by: java.rmi.RemoteException: The server has encountered a fatal error:
Error caught during request processing java.lang.ClassNotFoundException:
boolean; nested exception is:
java.lang.ClassNotFoundException: boolean
at
org.apache.openejb.server.ejbd.EjbRequestHandler.replyWithFatalError(EjbRequestHandler.java:425)
at
org.apache.openejb.server.ejbd.EjbRequestHandler.processRequest(EjbRequestHandler.java:103)
at
org.apache.openejb.server.ejbd.EjbDaemon.processEjbRequest(EjbDaemon.java:164)
at org.apache.openejb.server.ejbd.EjbDaemon.service(EjbDaemon.java:122)
at org.apache.openejb.server.ejbd.EjbDaemon.service(EjbDaemon.java:84)
at org.apache.openejb.server.ejbd.EjbServer.service(EjbServer.java:60)
at org.apache.openejb.server.ServicePool$2.run(ServicePool.java:78)
at org.apache.openejb.server.ServicePool$3.run(ServicePool.java:101)
at
java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)
at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.ClassNotFoundException: boolean
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:268)
at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:242)
at
org.apache.openejb.client.EjbObjectInputStream.resolveClass(EjbObjectInputStream.java:35)
at
java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1544)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1466)
at java.io.ObjectInputStream.readClass(ObjectInputStream.java:1433)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1288)
at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1634)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
at
org.apache.openejb.client.EJBRequest$Body.readMethodParameters(EJBRequest.java:386)
at
org.apache.openejb.client.EJBRequest$Body.readExternal(EJBRequest.java:200)
at
org.apache.openejb.server.ejbd.EjbRequestHandler.processRequest(EjbRequestHandler.java:101)
... 9 more
This is a known bug in JRE: the int.class value can be serialized but cannot be
deserialized by standard ObjectInputStream. The solution is to use a patched
ObjectInputStream (stolen from JBoss :)
/**
* An ObjectInputStream subclass used by the MarshalledValue class to
* ensure the classes and proxies are loaded using the thread context
* class loader.
*
* @author [EMAIL PROTECTED]
* @version $Revision: 16444 $
*/
public class MarshalledValueInputStream extends ObjectInputStream {
private static final Map<String, Class<?>> primitiveClasses = new
HashMap<String, Class<?>>();
static {
Class<?>[] primitives = {
byte.class, short.class, int.class, long.class,
float.class, double.class, char.class, boolean.class
};
for (Class<?> aClass : primitives) {
primitiveClasses.put(aClass.getName(), aClass);
}
}
/**
* Creates a new instance of MarshalledValueOutputStream
* @param is
* @throws IOException
*/
public MarshalledValueInputStream(InputStream is) throws IOException {
super(is);
}
/**
* Use the thread context class loader to resolve the class
* @param v
* @return resolved class
*
* @throws IOException Any exception thrown by the underlying
OutputStream.
* @throws ClassNotFoundException
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass v) throws IOException,
ClassNotFoundException {
final ClassLoader loader =
Thread.currentThread().getContextClassLoader();
final String className = v.getName();
final Class<?> aClass = primitiveClasses.get(className);
if(aClass != null)
return aClass;
return Class.forName(className, true, loader);
}
@Override
protected Class<?> resolveProxyClass(String[] interfaces) throws
IOException,
ClassNotFoundException {
// Load the interfaces from the thread context class loader
ClassLoader loader =
Thread.currentThread().getContextClassLoader();
Class<?>[] ifaceClasses = new Class[interfaces.length];
for(int i = 0; i < interfaces.length; i++) {
ifaceClasses[i] = loader.loadClass(interfaces[i]);
}
return java.lang.reflect.Proxy.getProxyClass(loader,
ifaceClasses);
}
}
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.