Could you please tell me how to lookup EJB on Weblogic?
I have following bean:
#Stateless
#EJB(name = "DataAccess", beanInterface = DataAccessLocal.class)
public class DataAccess implements DataAccessLocal {
...
}
I need this bean in other class which is not part of managed content (just simple class), so I guess it should be done like this:
DataAccessLocal dataAccess = DataAccessLocal.class.cast((new InitialContext()).lookup("%SOME_JNDI_NAME%"));
The question is what should be used as %SOME_JNDI_NAME% in case of Weblogic 10.x.x AS?
Any help will be appreciated.
I would update your EJB class to look like this:
#Stateless(name="DataAccessBean", mappedName="ejb/DataAccessBean")
#Remote(DataAccessRemote.class)
#Local(DataAccessLocal.class)
public class DataAccess implements DataAccessLocal, DataAccessRemote {
...
}
Looking up the EJB from a class deployed in the same EAR (using the local interface):
InitialContext ctx = new InitialContext(); //if not in WebLogic container then you need to add URL and credentials.
// use <MAPPED_NAME>
Objet obj = ctx.lookup("java:comp/env/ejb/DataAccessBean");
EJB injection is usually preferred, and you can do it as follows:
#EJB(name="DataAccessBean")
DataAccessLocal myDataAccessBean;
If you are trying to use the EJB remotely then you will need to use the remote interface and the following JNDI name:
DataAccessBean#<package>.DataAccessRemote
Related
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.
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;
}
I'm currently puzzled with the way Glassfish 3.1.2.2 handles EJBs.
I have an OSGi project, which consists of many OSGi bundles (jars). Also, there are a few WARs, including a Tapestry web application.
In one such bundle, let's call it "interfaces.jar", I have an interface defined:
public interface MyInterface() {
public static final String JNDI_NAME = "java:global/MyInterface";
void myMethod();
}
The implementation of that interface is as following, and it's contained in bundle "beans.jar":
#Stateless
#EJB(name = MyInterface.JNDI_NAME, beanInterface = MyInterface)
public class MyBean implements MyInterface() {
void myMethod() {
...
}
}
I am calling it from my Tapestry WAR app via JNDI lookup:
InitialContext.doLookup(MyInterface.JNDI_NAME);
Now, I was reading EJB 3.1 specification, and it says that I can one of the following scenarios:
Interface has #Local annotation; EJB is implementing this interface.
Interface is a plain Java interface without annotation; EJB with #Local annotation is implementing it.
Interface is a plain Java interface without annotation; EJB is implementing it.
Interface is a plain Java interface without annotation; EJB with #Local annotation is not implementing it.
EJB doesn’t have any special annotations.
So, by elimination:
I don't have #Local on interface
I don't have #Local on EJB
Seems somewhat right
I don't have #Local on EJB
I have #EJB annotation on my EJB
So, it seems that it's case 3:
"Because it’s the only implemented interface of the EJB, a container assumes that it must be a local business interface."
Now, a few questions:
Is my interface a local or remote one, since there is no local or remote annotation?
If it is local, I should be able to inject it with #EJB annotation, but it fails?
If it's remote, it is not in compliance with the explanation a few lines above?
If I add either #Local or #Remote, and perform JNDI lookup, I get a naming exception and NPE telling me there is nothing under that JNDI_NAME. How is that possible?
What exactly does #EJB(name = ..., beanInterface = ...) do on bean class and how does it interact with #Local and #Remote annotations?
1.)
First, let's see your example without the "unnecessary" #EJB annotation
#Stateless
public class MyBean implements MyInterface() {
void myMethod() {
...
}
}
You can now see clearly, that the EJB implements only one interface. As you mentioned in the 3rd points, "Interface is a plain Java interface without annotation; EJB is implementing it.", so MyInterface is a Local Business Interface of the MyBean EJB.
2.)
You use wrong JNDI name for the lookup:
#Stateless
public class MyBean implements MyInterface() {
...
The global JNDI name of your EJB:
java:global[/app-name][/module-name]/MyBean[!interface-name]
The interface-name is "MyInterface", but it is optional if there are no other business interfaces for your beans, like here, so you can skip it.
You have to figure out what the application- and module-name is for your bean in case of OSGI.
In a simple EJB application, the application-name is the name of the .ear file, and the module-name is the name of the .war/.jar file. application-name can be skipped if your module is not packaged in an ear.
So for example:
new InitialContext().lookup("java:global/myModuleName/MyBean");
5.)
#Stateless
#EJB(name = "MyInterface", beanInterface = MyInterface.class)
public class MyBean implements MyInterface() {
void myMethod() {
...
}
}
Here the #EJB annotation creates an EJB and put a reference to it into the Environment Naming Context (ENC). So it does nothing with the MyBean EJB, just expand its ENC with a new entry.
So from the business method of the current bean you can lookup for that new entry:
void myMethod() {
new InitialContext().lookup("java:comp/env/MyInterface")
}
You can locate the bean's ENC by "java:comp/env/" JNDI name.
As you can see, the name parameter defines the name of the entry in the ENC.
The beanInterface defines the Business Interface of the created Bean. If the Bean has more business interfaces, then you have to define beanName too, so the container could determine wich Bean you would like to create.
You can read about this topic here:http://thegreyblog.blogspot.hu/2010/09/introduction-to-ejb-30-injection-and.html
Wierd problem here. I have a bean with a remote interface declared and an implementation defined as a Stateless bean. Since I want to be able to replace the bean with a different bean depending on the implementation requirements, I have an ejb-reference declared in glassfish-web.xml.
I can successfully inject the bean if I use the name syntax to refer to the reference name like #EJB(name = "BeanReference"). I can also do a lookup: new InitialContext().lookup("java:comp/env/BeanReference").
The weird thing happens when I don't have any injections at all (no #EJB). Then the lookup fails with "javax.naming.NameNotFoundException: No object bound to name java:comp/env/BeanReference". If I list the pairs in "java:comp/env" it confirms that the reference doesn't exist unless an #EJB injection occurs somewhere in the application. I have checked the jndi-name entry and confirmed it matches the output from Glassfish during initialization.
I also tried using #Local instead of #Remote and get the same results. I prefer the #Remote since in an actual deployment the MyBean implementation will likely reside on a remote glassfish instance. It is local only for development and testing.
Using Glassfish 3.1.1 and NetBeans 7.1.2. Code snippets below...exception handling omitted for clarity.
#Remote
public interface MyBean {
public String doSomething();
}
#Stateless
public class MyBeanImpl implements MyBean {
#Override
public String doSomething() {
return "something";
}
}
#Stateless
#LocalBean
public class MyOtherBean {
public MyOtherBean() {
Context ctx = new InitialContext();
MyBean myBean = (MyBean)ctx.lookup("java:comp/env/BeanReference");
String rc = myBean.doSomething();
System.out.println("rc = " + rc);
}
}
<ejb-ref>
<ejb-ref-name>BeanReference</ejb-ref-name>
<jndi-name>java:global/appName/MyBeanImpl!com.test.bean.MyBean</jndi-name>
</ejb-ref>
I want to inject an EJB3 into a java class which is not an EJB.
these classes are both on the same server and application.
Is that possible ...and if yes ..then how ?
Thanks,
Perhaps you should supply more information about your work environment. The usage of CDI changes the whole specturm. You can inject it when you use CDI, otherwise you can only inject it into other EJB's and servlets (if your application server supports it).
Otherwise you can do a lookup using
Context ctx = new InitialContext();
MyEjb ejb = (MyEjb) ctx.lookup("java:comp/env/myEjb");
You can supply a name in the #EJB annotation you supply together with your #Stateless/#Stateful annotation.
#Stateless
#EJB(name="myEjb", beanInterface=MyEjb.class)
public class myEjbImpl implements MyEjb{
// code goes here
}
You can't inject it, but you can make a lookup for that EJB:
Look here:
http://www.roseindia.net/ejb/ejb-lookup.shtml
During the deploymentprocess of your EJB you may see, the Name of your Bean.