Hi Guys,

I've managed to do some work on the no-interface view work. I've managed to
read the localbean ejb-jar.xml config and @LocalBean annotation, and
propagate this through to CoreDeploymentInfo. I've got to a point where I
can lookup an EJB and get a proxy back. There's still some work to do, as
I'm getting this exception:

    //START SNIPPET: localbean
    public void testCalculatorViaLocalBeanInterface() throws Exception {
        Object object = initialContext.lookup("CalculatorImplLocalBean");

        assertNotNull(object);
        assertTrue(object instanceof CalculatorImpl);
        CalculatorImpl calc = (CalculatorImpl) object;
        assertEquals(10, calc.sum(4,6));
        assertEquals(12, calc.multiply(3,4));
    }

java.lang.reflect.UndeclaredThrowableException
    at $LocalBeanProxy0.sum($LocalBeanProxy0.java)
    at
org.superbiz.calculator.CalculatorTest.testCalculatorViaLocalBeanInterface(CalculatorTest.java:87)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at junit.framework.TestCase.runTest(TestCase.java:164)
    at junit.framework.TestCase.runBare(TestCase.java:130)
    at junit.framework.TestResult$1.protect(TestResult.java:110)
    at junit.framework.TestResult.runProtected(TestResult.java:128)
    at junit.framework.TestResult.run(TestResult.java:113)
    at junit.framework.TestCase.run(TestCase.java:120)
    at junit.framework.TestSuite.runTest(TestSuite.java:228)
    at junit.framework.TestSuite.run(TestSuite.java:223)
    at
org.junit.internal.runners.OldTestClassRunner.run(OldTestClassRunner.java:35)
    at
org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
    at
org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
    at
org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)
    at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at
org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:338)
    at
org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:997)
Caused by: java.lang.IllegalStateException: Received method invocation and
cannot determine corresponding business interface: method=public int
$LocalBeanProxy0.sum(int,int)
    at
org.apache.openejb.core.ivm.BaseEjbProxyHandler.getInvokedInterface(BaseEjbProxyHandler.java:188)
    at
org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:245)
    ... 25 more

I haven't dived into this exception much, so I'll keep working on it, but if
anyone has any advice it would be much appreciated!

There are a couple of things I could do with some guidance on, I'd be
grateful for any help anyone could give.

JNDI:

I've added the following code to JndiBuilder.bind():

        try {

            if (deployment.isLocalbean()) {
                Class beanClass = deployment.getBeanClass();

                LocalBeanReference ref = new LocalBeanReference(deployment);

                optionalBind(bindings, ref, "openejb/Deployment/" +
format(deployment.getDeploymentID(), beanClass.getName(), null));

                String internalName = "openejb/Deployment/" +
format(deployment.getDeploymentID(), beanClass.getName(),
InterfaceType.LOCALBEAN);
                bind(internalName, ref, bindings, beanInfo, beanClass);

                String name = strategy.getName(beanClass,
JndiNameStrategy.Interface.LOCALBEAN);
                bind("openejb/local/" + name, ref, bindings, beanInfo,
beanClass);
                bind("openejb/remote/" + name, ref, bindings, beanInfo,
beanClass);
            }
        } catch (NamingException e) {
            throw new RuntimeException("Unable to bind localbean deployment
in jndi.", e);
        }

I created a LocalBeanReference class - which what is bound into JNDI. This
takes a CoreDeploymentInfo object, and its getObject() creates a proxy.
Here's the code:

package org.apache.openejb.core.ivm.naming;

import org.apache.openejb.core.CoreDeploymentInfo;

import javax.naming.*;

public class LocalBeanReference extends Reference {
    private CoreDeploymentInfo deployment;


    public LocalBeanReference(CoreDeploymentInfo deployment) {
        this.deployment = deployment;
    }

    public Object getObject() throws javax.naming.NamingException {
        return deployment.getLocalBean();
    }
}

I'm concerned that this isn't the right approach - I notice that the other
interfaces bind a BusinessRemoteHome/BusinessLocalHome class, should this
follow the same pattern, or could just bind a ObjectReference with the
proxy?

Also, the default Global JNDI name is <className>LocalBean - is this ok?

Class loading:

I've added a method to CoreDeploymentInfo, which will create a new proxy.
The code I've written to create the proxy using the ASM library returns a
byte[]. To load this class I'm creating a new ClassLoader,  which is a child
of the ClassLoader that the bean itself is created from, and calling
defineClass(). I'm not sure if this is right, I'd appreciate any thoughts
anyone has.

 Cheers,

Jon

Reply via email to