1

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.

Community
  • 1
  • 1
Steve Cohen
  • 4,679
  • 9
  • 51
  • 89
  • How any copies of ServiceLogicLocal.class are floating around in your EAR file and where are they? – Steve C Nov 24 '16 at 03:05
  • 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 Nov 24 '16 at 14:56
  • 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 Nov 25 '16 at 02:12

2 Answers2

2

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

Steve C
  • 18,876
  • 5
  • 34
  • 37
  • Thank you and I will try your suggestion. However, I am wondering why the jboss deployment descriptor wasn't necessary in order to do a remote lookup. – Steve Cohen Nov 25 '16 at 14:08
  • Regardless of the above question, which I'd still like to understand, your suggestion of putting a dependency on the deployment of the EJB jar is a good one! Thank you @Steve_C – Steve Cohen Nov 25 '16 at 16:46
  • And no, Steve C is not me. – Steve Cohen Nov 25 '16 at 16:57
0

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!!