1
votes

I believe this question is an extension of What is local/remote and no-interface view in EJB?

I am trying to port a group of EJB Jars whose EJBs are called by a Servlet in a generic fashion, from WebLogic to JBoss. This whole system is very old, the EJBs are 2.0. I have tried to update this by changing the deployment descriptor to 3.2.

That part is relatively easy.

Here's the part that isn't.

The EJBs participating in this arranbement all implement the SessionBean interface. Their local and remote interfaces are generic, they inherit from a common business interface. Here is a sample of the deployment descriptor:

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         version="3.2"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd">
<module-name>WhizBangSessionEJB</module-name>
<enterprise-beans>
   <session>
        <ejb-name>WhizBangSessionEJB</ejb-name>
        <home>com.whatever.hostinterface.ServiceLogicHome</home>
        <remote>com.whatever.hostinterface.ServiceLogic</remote>
        <local-home>com.whatever.hostinterface.ServiceLogicLocalHome</local-home>
        <local>com.whatever.hostinterface.ServiceLogicLocal</local>
        <ejb-class>com.whatever.whizbang.ejbs.WhizBangSessionBean</ejb-class>
        <session-type>Stateful</session-type>
        <transaction-type>Container</transaction-type>
    </session>
 </enterprise-beans>
</ejb-jar>

I should also mention here the signature of these interfaces:

public interface ServiceInterface
{
// business interface methods.
}

public interface ServiceLogic extends EJBObject, ServiceInterface
{}

public interface ServiceLogicLocal extends ServiceLogic, EJBLocalObject 
{}

So a ServiceLogic IS-A ServiceInterface. A ServiceLogicLocal IS-A ServiceLogic and therefore IS-A ServiceInterface

Using the remote interface, the servlet is able to instantiate a bean as follows:

Object home = ctx.lookup({JNDI of Home Interface});
EJBHome obHome = (EJBHome)PortableRemoteObject.narrow(home, EJBHome.class);
Method m = obHome.getClass().getDeclaredMethod("create", new Class[0]);
sl = (ServiceLogic) m.invoke(obHome, new Object[0]);

and I have my EJB which can be cast into a service logic.

But these EJBs and the Servlet will always be in the same container. Therefore local interfaces are indicated. Here is where I run into trouble. And Local EJBs don't require Home Interfaces in 3.x.

So I thought something like this should work.

sl = (ServiceLogicLocal)ctx.lookup({JNDI of Local Interface to Bean});

This fails with the following error.

java.lang.ClassCastException: com.whatever.hostinterface.ServiceLogicLocal$$$view60 cannot be cast to com.whatever.hostinterface.ServiceLogicLocal

And I know that the Local Home interface is not required, but I have created it. Trying to use that and calling its create() method, produces the same kind of ClassCastException where I fail because trying to cast a view (proxy) of an object into an object of the type.

What is the difference between a Local EJB Interface and a ClientView of a Local EJB Interface, and how may I instantiate this EJB through its local interface?

Thanks.

2
How any copies of ServiceLogicLocal.class are floating around in your EAR file and where are they? - Steve C
there's no Ear file. There's a war file with the Servlet and EJBs deployed in ejb jars on the same application server. This is done to allow separate deployment of the EJBs. - Steve Cohen
If there is no EAR file then your web module cannot see the classes in the ejb module, which makes me wonder about where it's getting ServiceLogicLocal.class - Steve C

2 Answers

2
votes

By default, Java EE deployment units (jars, ejb-jars, wars, ears-and-their-contents) are isolated from each other. In other words, classes in one deployment unit do not have access to classes in other deployment units.

This is normally a good thing.

Some Java EE implementations, such as JBossAS and WildFly, provide a mechanism for overriding this constraint.

If your EJBs and interfaces are packaged in a jar named WhizBang.jar, then you can make the classes in this jar accessible to your web application by adding a WEB-INF/jboss-deployment-structure.xml file to it with the following content:

<?xml version="1.0"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.3">
    <deployment>
        <dependencies>
            <module name="deployment.WhizBang.jar" />
        </dependencies>
    </deployment>
</jboss-deployment-structure>

Given the above, you can then lookup your EJBs:

 InitialContext initialContext = new InitialContext();
 ServiceInterface serviceBean = (ServiceInterface)initialContext.lookup("java:global/WhizBangSessionEJB/WhizBangSessionEJB!com.whatever.hostinterface.ServiceLogicLocal");
 ServiceLogic remoteService = (ServiceLogic)initialContext.lookup("java:global/WhizBangSessionEJB/WhizBangSessionEJB!com.whatever.hostinterface.ServiceLogic");

I have this code working in WildFly 10.1.0.Final

0
votes

This worked for me in Wildfly,

Although I had to add the dependency as provided.

 		<!-- Business Interfaces of the server EJB. -->
		<dependency>
			<groupId>com.sample.ejb</groupId>
			<artifactId>sample-engine-ejb</artifactId>
			<type>ejb</type>
			<version>1.0</version>
			<scope>provided</scope>
		</dependency>

Thank you!!