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.