Consuming local EJB, in the same Container but different ears - java

I'm triying to consume a Local EJB in the same Glassfish, but different ears. But Glassfish can't found the local EJB or can't consume
I read this:
According to the JavaEE tutorial, the client of a #Local bean "must run in the same JVM as the enterprise bean it accesses."
In the first ear,
I have the local Interface inside a jar
#Local
public interface MyLocalBean {
int getNumber(int num3);
}
In another jar, I have the implementation
#Stateless
#LocalBean
public class MyLocalBeanImpl implements MyLocalBean,Serializable{
public MyLocalBeanImpl() {}
public int getNumber(int num3){......
In the second ear,
in the same Glassfish
I have the local Interface inside a jar
#Local
public interface MyLocalBean {
int getNumber(int num3);
}
In another jar, I have the consumer
#Stateless
#LocalBean
public class BeanConsumer{
#EJB(name="MyLocalBeanImpl")
private MyLocalBean beanlocal;
with #EJB and (name="MyLocalBeanImpl") parameter the error is:
Cannot resolve reference Local ejb-ref name=MyLocalBeanImpl,Local 3.x
interface =my.package.MyLocalBean,ejb-link=null,lookup=,
mappedName=,jndi-name=,refType=Session|#]
with #EJB and (name="my.package.MyLocalBeanImpl") parameter the error is:
Cannot resolve reference Local ejb-ref name=my.package.MyLocalBeanImpl,
Local 3.x interface =my.package.MyLocalBean,ejb-link=null,
lookup=,mappedName=,jndi-name=,refType=Session|#]***
I tried too with mappedName
#Stateless(name="MyLocalBeanImpl",mappedName ="MyLocalBeanImpl")
public class MyLocalBeanImpl implements MyLocalBean{
#EJB(name="MyLocalBeanImpl",mappedName ="MyLocalBeanImpl")
private MyLocalBean beanlocal;
but the error persist
Cannot resolve reference Local ejb-ref name=MyLocalBeanImpl,
Local 3.x interface =my.package.MyLocalBean,ejb-link=null,
lookup=,mappedName=MyLocalBeanImpl,jndi-name=,refType=Session
GlassFish works with a JNDI like
java:global[/<app-name>]/<module-name>/<bean-name>
I added the annotation #LocalBean to the bean MyLocalBeanImpl
#Stateless
#LocalBean
public class MyLocalBeanImpl implements MyLocalBean{
public MyLocalBeanImpl() {}
public int getNumber(int num3){......
and when I deployed Glassfish say the jndi are two
Portable JNDI names for EJB OtroBean
java:global/myfirstear/myejbs/MyLocalBeanImpl!my.package.MyLocalBeanImpl
and
java:global/myfirstear/myejbs/MyLocalBeanImpl!my.package.MyLocalBean
i'm trying with
#EJB(lookup="java:global/myfirstear/myejbs/MyLocalBeanImpl!my.package.MyLocalBeanImpl")
It seems that Glassfish found the Local Bean, but... Glassfish have problems casting o something like this
javax.naming.NamingException
javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
at
com.sun.ejb.containers.StatelessSessionContainer
._getContext(StatelessSessionContainer.java:454)
.....
Caused by: javax.ejb.EJBException:
javax.ejb.CreateException: Could not create stateless EJB
....
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException:
Exception attempting to inject Local ejb-ref name=my.package.BeanConsumer/beanlocal,
Local 3.x interface =my.package.MyLocalBean,ejb-link=null,
lookup=java:global/myfirstear/myejbs/MyLocalBeanImpl!my.package.MyLocalBeanImpl,
mappedName=,jndi-name=,refType=Session into class my.package.BeanConsumer:
Can not set my.package.MyLocalBean field my.package.BeanConsumer.beanlocal
to my.package.beans.__EJB31_Generated__MyLocalBeanImpl__Intf____Bean__
And trying with
#EJB(lookup="java:global/myfirstear/myejbs/MyLocalBeanImpl")
I get:
throws javax.naming.NamingException
javax.ejb.EJBException: javax.ejb.EJBException: javax.ejb.CreateException: Could not create stateless EJB
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException:
Exception attempting to inject Local ejb-ref
name=my.package.BeanConsumer/beanlocal,
Local 3.x interface =my.package.MyLocalBean,
ejb-link=null,
lookup=java:global/myfirstear/myejbs/MyLocalBeanImpl,
mappedName=,jndi-name=,refType=Session
into class my.package.BeanConsumer:
Lookup failed for 'java:comp/env/my.package.BeanConsumer/beanlocal'
in SerialContext
[myEnv={java.naming.factory.initial=
com.sun.enterprise.naming.impl.SerialInitContextFactory,
java.naming.factory.state=
com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl,
java.naming.factory.url.pkgs=
com.sun.enterprise.naming}

It is possible to inject a local EJB into another EJB in the same JVM but different ear.
The problem is that you cannot rely on the name of the bean anymore as you need to tell the consumer bean the complete JNDI name. You can find this name in the server logs during deployment; the moment the bean is bound to the JNDI directory the server shows it in the logs.

Related

Referencing EJB Local home from a POJO class of a separate web application

I am trying to port 2 EJB modules in my application from EJB2.1 to EJB3.0. I am using the Eclipse Kepler IDE and regenerated the session beans using an EJB3.0 configuration. I am not using an ejb-jar.xml because in EJB 3.0 that is supposed to be redundant. I have instead used annotations for marking my bean as Stateless and specifying the Local and Local Home Interfaces. I have still kept the Local Home interface since I wanted the basic structure of my project to be similar to what it was in EJB2.1. I have also done away with the xml bindings for the EJB while migrating.
We are using a WAS 7 application server for deployment and while the EJB is getting successfully deployed without errors, I am getting a naming Exception while looking up my Local Home interface from a separate POJO class of a different web application it is required in. I basically want to call the create() method of the Local Home interface after referencing the EJB Local Home. Adding code samples below:
Session Bean:
#Stateless
#Local(AccessLDAPSessionLocal.class)
#LocalHome(AccessLDAPSessionLocalHome.class)
public class AccessLDAPSessionBean implements AccessLDAPSessionLocal {
//Business Logic
}
Local Interface:
public interface AccessLDAPSessionLocal {
//business Interface
}
Local Home Interface:
public interface AccessLDAPSessionLocalHome extends EJBLocalHome {
public AccessLDAPSessionLocal create() throws CreateException;
}
Pojo class referencing the Local Home interface:
public static AccessLDAPSessionLocal getAccessLDAPSessionBean() throws NamingException, CreateException {
if (accessLDAPSessionBean == null) {
InitialContext context = new InitialContext();
Object obj = context.lookup("java:global/AccessLDAP/AccessLDAPSessionBean!com.ibm.asset.hrportal.core.ejb.ldap.AccessLDAPSessionLocalHome");
accessLDAPSessionBean = ((AccessLDAPSessionLocalHome) obj).create();
}
return accessLDAPSessionBean;
}
Also my Local and Local Home interfaces are inside my EJB client which I use as a jar file, while my Session Bean is inside the actual EJB which is used as an EAR.
Following is the error I am getting:
NamingException::javax.naming.NameNotFoundException: Name global not found in context "java:".
Am I missing some configuration resulting in the failure of JNDI lookup? Any help would be gratefully appreciated. Thanks in advance.
WebSphere Application Server 7.0 is only an implementation of EJB 3.0, but the java:global namespace wasn't added until EJB 3.1, which wasn't implemented in WebSphere Application Server until 8.0. As with all EJB 3.0 implementations, you will need to lookup a vendor-specific binding name. You can find the WebSphere Application Server binding name by looking at the CNTR0167I messages in SystemOut.log. See the EJB 3.0 application bindings overview topic in the Knowledge Center if you would like to customize this binding name.
Regardless, it is not a best practice to directly lookup EJBs by their binding name. Instead, you should use an EJB reference. In EJB 3.0, that means using an annotation like this in an EE managed object (such as a servlet or another EJB):
#EJB
private AccessLDAPSessionLocalHome home;
In this case, the EJB container is required to find a target EJB within the same application that contains the EJB reference, so you do not need to explicitly configure a target binding name for the EJB reference.
If you need to access the EJB reference from a utility class rather than an EE managed class, then declare the EJB reference with a name on a managed class (such as a servlet or another EJB), and look it up from the utility class:
#EJB(name = "ejb/accessHome", beanInterface = AccessLDAPSessionLocalHome.class)
public class MyServlet { ... }
public class MyUtility {
...
InitialContext context = new InitialContext();
Object obj = context.lookup("java:comp/env/ejb/accessHome");
...
}
You can configure multiple such EJB references on the same managed EE class using the #EJBs annotation:
#EJBs({
#EJB(name = "ejb/accessHome", beanInterface = AccessLDAPSessionLocalHome.class),
#EJB(name = "ejb/other" beanInterface = Other.class)
})
public class MyServlet { ... }
If your EJB is packaged in a separate EAR, then note that this is not a portable configuration. See the "Local client views" section of the EJB modules topic in the Knowledge Center. Additionally, you will need to explicitly configure a binding name for the EJB reference.
I think the way you are looking up the ejb is not correct. The JNDI name would be something like "java:comp/env/". ejb-ref-name would be part of your web.xml
Also, you will need to give providerURL and factoryName to the context object before doing the lookup.

Accessing ejb in ear from war via local interface

Is it possible to access ejb that resides inside ear file, from a war using local interface?
Both deployed under same app server.
The ejb:
#Stateless(name="FirstDemoEJB",mappedName = "FirstDemoEJB/Local")
public class FirstSessionBean implements FirstSessionBeanRemote, FirstSessionBeanLocal {
}
Now, in test servlet (war):
InitialContext context = new InitialContext();
Object ob = context.lookup("java:comp/env/FirstDemoEJB/Local");
Fails on:
javax.naming.NameNotFoundException: While trying to look up
comp/env/FirstDemoEJB/Local in /app/webapp/FirstWebEJBTest/12292093.;
But remote lookup works fine:
Object ob = context.lookup("FirstDemoEJB/Local#org.weblogic.FirstSessionBeanRemote");
You should use container dependency injection to access the ejb from the servlet. Most likely, the problem is that you have the jndi lookup path incorrect. Using the container dependency injection relieves you of knowing the jndi naming scheme.
public class MyServlet extends HttpServlet {
#EJB(mappedName = "FirstDemoEJB/Local")
private FirstSessionBeanLocal firstSessionBeanLocal;
}

ejb injection within package

I've got an ejb
#Stateless
#LocalBinding(jndiBinding = DmsExportExecutor.DEFAULT)
public class InjectedBean implements BeanInterface {
}
that implements interface
#Local
public interface BeanInterface {
public static final String DEFAULT = "package.InjectedBean";
}
And i'm trying to inject this into a bean, that's in exactly the same project and package. by #jndiinject annotation
public class AnotherBean {
#JndiInject(jndiName = BeanInterface.DEFAULT)
BeanInterface bean;
}
If i do that, a runtime exception is thrown.
java.lang.RuntimeException: Unable to inject jndi dependency: env/package.InjectedBean/bean into property package.InjectedBean. AnotherBean.bean: package.InjectedBean not bound
Caused by: javax.naming.NamingException: Could not dereference object [Root exception is javax.naming.NameNotFoundException: package.InjectedBean not bound]
Caused by: javax.naming.NameNotFoundException: package.InjectedBean not bound
After refactoring my InjectedBean into another package that is even located inside of the same maven project, it starts working.
Could anyone explain why this happens?
Have you tried using the standard #EJB annotation ?
#EJB
BeanInterface bean;
This should do the work for you by bean type.
You should see if (and how) your injected bean is loaded by the EJB container at container startup
or using the admin gui.
You can always do a basic lookup:
InitialContext().lookup("the.bean.jndi.name").
Y.Lev

how to give custom JNDI name to an EJB 3.0 bean in WebSphere

Can any one let me know how to give custom JNDI name to an EJB 3.0 stateless (local) session bean component in WebSphere 7? I know server is giving default name to some thing like ejblocal:<fully qualified interface name>. But I dont want to use this name in my client lookup.
I also would like to know whether the same approach will work for WebSphere 8.0 as well?
interface #Remote
public interface HellowWorldBeanRemote {}
bean class import javax.ejb.Stateless;
#Stateless(mappedName="HelloWorld") //Giving custom Jndi name to ejb
public class HellowWorldBean implements HellowWorldBeanRemote {}

#Local interface with many realisation

I have #Local interface
#Local
public interface IRepo
{
and two realisation, but only 1 bean realisation
#Stateless(name = "RepoBean")
public class RepoBean implements IRepo
{
second
public class SimpleRepo implements ILogRepositoryIRepo
{
and inject it ti my Web service using
#EJB(name = "RepoBean")
private IRepo repository;
And it's works well on jboss and on WebLogic. But on GlassFish 3.1.1 I get Error (while deploying)
Cannot resolve reference Local ejb-ref name=RepoBean,Local 3.x interface =com.company.IRepo,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session because there are 2 ejbs in the application with interface com.company.IRepo.
But I have only 1 ejb realisation.
Any ideas? May be I can use some deployment-desriptor or something else.
EJB 3.0, Java EE 5
I really didn't understand what you're trying to do, but if you have two beans that implement the same business interface, you'll have to use the 'beanName' attribute as follows:
#EJB(beanName = "RepoBean")
private IRepo repository;
-- UPDATE
Look at this: java.net/node/702013. There is a bug issue to this problem: java.net/jira/browse/GLASSFISH-11684
Seems like this only occurs with EJB-in-WAR packaging. In ejb jar doesn't happen.
Well, Glassfish is more right than JBoss and WebLogic, Business-Bean-Classes should all have their own EJB-Local-Interface.
I Guess WL or JBoss will give you a warning instead of an error.

Categories