JBoss 6: Injecting EJB into servlet - dependency-injection

Folks,
I am very annoyed by having to re-learn and waste time with this stuff every time a new version of JBoss rolls around.
I have a stateless EJB that is discovered and declared in the JNDI space:
10:01:53,044 INFO [org.jboss.ejb3.proxy.impl.jndiregistrar.JndiSessionRegistrarBase] Binding the following Entries in Global JNDI:
DTalk/UserManager/local - EJB3.x Default Local Business Interface
DTalk/UserManager/local-com.doctalk.ejb.UserManagerLocal - EJB3.x Local Business Interface
I need to use this EJB in a servlet which is part of a war which is part of the EAR that contains the EJB. I'd like to do it using injection.
When I use the most intuitive notation:
#EJB
private UserManager userManager;
I get an exception in JBoss logs.
When I use a more flowery notation such as:
#EJB( mappedName = "UserManager" )
private UserManager userManager;
Or
#EJB( mappedName = "DTalk/UserManager/local" ) // EAR is called DTalk
private UserManager userManager;
I get no injections errors in jboss but the injected bean is null.
This is maddening and a huge waste of time and makes me question why I don't dump the Eclipse/jboss tools franchise in favor of NetBeans and GlsssFish.
Any insights appreciated.
Thanks.

You are trying to inject (a proxy to) the bean instance itself, instead of its interface.
Yet, according to the deployment logging you've shown, you have only declared the bean to be bounded in JNDI via its (local) interface. In order to make the injection happen, you should either declare the variable in which you're injecting as the interface:
#EJB
private UserManagerLocal userManager;
OR declare that a no-interface view should be created for your bean:
#Stateless
#LocalBean
public class UserManager implements UserManagerLocal {
...
}
after which you can declare the variable as you did earlier:
#EJB
private UserManager userManager;

Related

How to access a local interfaces from one project into another within the same ear project

I have a web project that has FacesValidator, this validator needs to access an EJB service to verify if a record exists. Unfortunately, I cannot inject my enterprise beans since the validator is not a managed-bean, so I'm trying to access it via InitialContext. I've tried different combination from http://docs.oracle.com/javaee/6/tutorial/doc/gipjf.html but failed.
What works is this format:
java:global/myProject-ear-1.0.0/myProject/MyService!com.czetsuya.myProject.service.membership.MyService,
My question is can it be simplify? Seems too long.
Thanks,
czetsuya
Look at the server logs. A bit decent EJB container (at least, Glassfish 3 and JBoss 6/7 do), logs all available JNDI names of the EJB during EJB deployment step. Provided that the validator is properly been put in the WAR and the EJB has a #Local interface, then the shortest JNDI name would be the java:app one which should in your case have been java:app/myProject/MyService.
A completely different alternative is to just make the validator a JSF or CDI managed bean instead, so that you can just use the #EJB annotation.
#ManagedBean // Or #Named.
#ApplicationScoped // Provided that the instance doesn't have any state.
public class MyValidator implements Validator {
#EJB
private MyService myService;
// ...
}
and reference it by binding instead of validatorId:
<f:validator binding="#{myValidator}" />
Note that from JSF 2.2 on, you should be able to inject #EJB in a #FacesValidator (and #FacesConverter).
See also:
How to inject in #FacesValidator with #EJB, #PersistenceContext, #Inject, #Autowired

Inject singleton bean into session bean via remote interface, object always "null"

I need to inject a singleton bean into the session bean. Below are the corresponding classes. The problem is that the injected object is always null. I tried all of the JNDI lookup strings which my JBoss 7.0.1 server showed me during startup (i.e. JNDI bindings for session bean named GlobalBean in deployment unit subdeployment .. of deployment .. are as follows: ..). I also tried commenting out the #EJB annotation in GlobalBean.java and also tried to use the "ejb/GlobalBean" during injection. However, no luck. What could be the reason? Thx.
GlobalBean.java:
#Startup
#Singleton
#Remote(GlobalBeanRemote.class)
#EJB(name="ejb/GlobalBean", beanName="GlobalBean", beanInterface=GlobalBeanRemote.class)
#ConcurrencyManagement(ConcurrencyManagementType.CONTAINER)
public class GlobalBean implements GlobalBeanRemote
{
// CODE
}
SessionBean.java:
#Stateful
public class SessionBean extends ParentBean
{
#EJB(name="java:module/GlobalBean!project.framework.interfaces.GlobalBeanRemote")
private GlobalBeanRemote globalBeanAPI3;
// CODE
}
In your SessionBean class try changing name attribute of #EJB to mappedName.
#EJB(mappedName="java:module/GlobalBean!project.framework.interfaces.GlobalBeanRemote")
This will, of course, only work if your two beans are in the same module.
Update
Given that your beans are in separate modules, try using the java:app namespace:
#EJB(mappedName="java:app ...")
The java:app namespace is used to look up local enterprise beans packaged within the same application. That is, the enterprise bean is packaged within an EAR file containing multiple Java EE modules. JNDI addresses using the java:app namespace are of the following form:
java:app[/module name]/enterprise bean name[/interface name]
Also try removing GlobalBean's #EJB annotation. #EJB is used to define a dependency.

Question about multi-threading and EntityManager

I have been developing my web-app using JPA 2.0 implementation EclipseLink 2.2.0. I finally got around to running multi-threaded code and I got this exception:
java.lang.IllegalStateException: Attempting to execute an operation on a closed EntityManager.
The objects that have all the javax.persistence calls in my application are defined as application scoped, like this:
#Model
#ApplicationScoped
public class LocationControl implements Serializable {
#PersistenceContext private EntityManager em;
#Resource private UserTransaction utx;
// etc
And of course all the managed beans (usually RequestScoped or ConversationScoped) that want to access the data base do so like this:
#Inject private LocationControl lc;
So my question is this: Did I get that Exception through the use of #ApplicationScoped DAO? I had thought that it would be more efficient that way, since the container would not have to be continually re-creating this object on every request if it did not have a scope, and the DAO has no state of its own. However if the EntityManager and UserTransaction object have to be separate instances for each user, then that would be a problem.
Alternatively, I could use syncrhonized on the DAO methods, but I think that would cause thread lockups in the container (GlassFish).
Any advice appreciated.
#Model annotation was originally created to annotate request scoped beans, here is how it's defined:
#Named
#RequestScoped
#Stereotype
#Target({TYPE, METHOD, FIELD})
#Retention(RUNTIME)
public #interface Model {}
You can of course override '#RequestScoped' with another annotation but '#ApplicationScoped' it's not a good choice as everyone in the application would modify the state of the same injected EntityManager. I think it would be best to leave it #RequestScoped in most cases, sometimes, for example for a login/logout data bean '#SessionScoped' could be an option but I cannot see a scenario for '#ApplicationScoped' dao.
If you don't want to use #Model at all and you use full Java EE container, then the stateless EJB ,as BalusC said, would be a great option for Dao too.

Is there any Spring #Required annotation equivalent in EJB 3.0?

Is there any equivalent annotation in EJB for #Required (Spring)? I do dependency injection using setters and I want to be sure that resource was injected (almost no probability of NullPointerException ;)). In Spring it is easy:
#Required
public void setProperty(Property p) {
this.property = p;
}
Is there any way to do such a validation in EJB? (Maybe some other solution than annotatations). Thanks
In ejb injection is done via #EJB and #Resource (as stated above).
If the bean for the given (or auto-generated) name doesn't exist you get an error from the container (in many cases this happens at deployment time).
The only way to (maybe) get a nullpointer exception inside a ejb bean is if you try to access an injected object in the default constructor. By spec injection happens after the constructor and before the #PostConstruct lifecycle is called.

Injecting entity manager into managed bean

It is possible to inject entity manager (or its factory) into jsf managed bean using #PersistenceContext (or #PersistenceUnit)?
I Tried it but nothing, I obtain a NullPointerException.
Yes it is possible. This is the syntax.
#PersistenceContext
EntityManager em;
You need to have a persistence.xml in your project. Btw: I'm running Glassfish 3.
After this you can then use methods like em.createNamedQuery.
Also remember the injection takes place after the constructor so if your trying to do database functions in the constructor this will not work. You will have to add the #PostConstruct annotation to a method. This is probably the problem your having.

Resources