EJB 3.1 - Using #EJB inside an EJB - is it possible? - java

Is it possible to use #EJB inside another EJB? I'm trying to do this now, and my EJB is ending up null. I'll outline my problem in an example.
#Stateless
#LocalBean
#Local(LoginServiceLocal.class)
public class LoginService implements LoginServiceLocal {
public void createLogin(String email, String password) { ... }
}
#Stateless
#LocalBean
#Local(AccountServiceLocal.class)
public class AccountService implements AccountServiceLocal {
#PersistenceContext(unitName = "accounts")
private EntityManager accountEntityManager;
#EJB
private LoginServiceLocal loginService;
public void createAccount(Account account, String email, String password) {
accountEntityManager.persist(account);
loginService.createLogin(email, password);
}
}
Is this type of thing supposed to be possible? I should also mention that I'm using an embedded container (via EJBContainer), and I'm looking up the AccountService using JNDI, however when I try and call loginService.createLogin in the AccountService, the loginService is null (not being initialized by #EJB).
Is what I'm trying to do possible?
Thanks.

Yes, it's possible.
The #LocalBean annotation, enables an EJB to expose a no-interface client view, so that you won't need to define a Local interface.
On the other hand, the #Local annotation defines a bean's local client interface.
Choose one of the above configuration options not both.
If you choose to use the #LocalBean annotation, drop the #Local annotation, remove the implements keyword and inject the bean class name with the #EJB annotation.
If you choose to use the #Local annotation, drop both #Local and #LocalBean annotations and inject the bean with the #EJB annotation using the interface name.

Yes, I was just working on some of my code that does just that. It might be an issue with how you're creating the EJB. I have only done it using injection and not a jndi lookup.

If you are used EJB3.1 you can also use #Inject from CDI

Related

Lookup using #EJB fails

I'm trying to look up my stateless bean using the annotation class #EJB, but fails. I'm using WildFly 10 as EE container. The stateless bean interface looks as follows:
#Local
public interface T1Service {
String sayHi();
}
The implementation class:
#Stateless
public class T1ServiceImpl implements T1Service {
#Override
public String sayHi() {
return "Hi!";
}
}
In my controller I want to inject the service:
#EJB(lookup = "javaee/T1ServiceImpl")
private T1Service t1Service;
Make the call:
t1Service.sayHi();
But it fails with a NullPointerException (t1Service is null).
What am I missing?
Note, the JNDI bindings are:
java:global/javaee/T1ServiceImpl!p1.T1Service
java:app/javaee/T1ServiceImpl!p1.T1Service
java:module/T1ServiceImpl!p1.T1Service
java:jboss/exported/javaee/T1ServiceImpl!p1.T1Service
java:global/javaee/T1ServiceImpl
java:app/javaee/T1ServiceImpl
java:module/T1ServiceImpl
The controller where you want to inject the T1Service is also a #Stateless Bean? If it is runnning in the same application you can omit the definition of property lookup.
I would also suggest to use CDI (#Inject) in case that you are using Java EE 6/7/8. (see here for more information)

null #Resource in method triggered on event

I have singleton bean in which I inject resource with #Resource annotation. When I try to retrieve that resource in the method called on event, the resource is null. What's going and why resource is not injected? What solution can be found for this? I can't refuse from using observers.
#Singleton
#javax.ejb.Startup
#Stateless
public class ScheduleManager implements IScheduleManager
{
#Resource
private TimerService timerService;
#Override
#Observer(value=EventConstants.SCHEDULE_CHANGE_EVENT)
public void reSchedule(PtSchedulesDTO schedule)
{
Collection<Timer> timers = timerService.getTimers();
//...
}
//...
}
I am not sure what framework or technology you are using but for annotation (#Resource) to work, usually something must be declared to look for that annotation. It could be declared in an xml file, where it gets pick up by the framework. Also you could also check if you have a TimerService class that you need to annotate or create a bean for the framework to be able to inject it in.

#Inject and #PostConstruct not working in singleton pattern

I have a class as below:
public class UserAuthenticator {
private static UserAuthenticator authenticator =
#Inject
private UserRepository userRepository;
#PostConstruct
public void init() {
List<User> allUsers = userRepository.findAll();
for (User user : allUsers) {
users.put(user.getEmail(), user.getPassword());
serviceKeys.put(user.getServiceKey(), user.getEmail());
}
}
public static UserAuthenticator getInstance() {
if (authenticator == null) {
authenticator = new UserAuthenticator();
}
return authenticator;
}
}
When I call
UserAuthenticator authenticator = UserAuthenticator.getInstance();
init() method isn't called and userRepository is null
My web application run in JBOSS EAP 6.3.
How is this caused and how can I solve it?
In a Java EE application, don't think in singletons. That's only recipe for trouble and confusion. Instead, think in "just create one". Tell the Java EE container to just create only one instance of the specified class, application wide, and obtain the instance via the facility offered by the Java EE container. Your concrete problem is caused because you're manually creating an instance of the class using new operator without manually performing the injection and post construct call like as the technical correct but conceptually wrong example below:
authenticator = new UserAuthenticator();
authenticator.userRepository = new UserRepository();
authenticator.init();
In other words, you incorrectly expected that the new operator magically recognizes the bean management and dependency injection related annotations.
The right approach depends on the one you'd like to point out as the responsible for creating and managing the instance of the specified class. If it's CDI, then just tell it to create only one managed bean instance of the backing bean class, application wide, using #Named #ApplicationScoped.
import javax.inject.Named;
import javax.enterprise.context.ApplicationScoped;
#Named
#ApplicationScoped
public class UserAuthenticator {}
It will be created just once and be available via #Inject as below in any other Java EE managed artifact (read: in any other class annotated with #Named, #Stateless, #ManagedBean, #WebServlet, #WebListener, #WebFilter, #Path, etc..):
#Inject
private UserAuthenticator userAuthenticator;
If you're absolutely positive that you need a static method to grab the current CDI managed bean instance of a given backing class, then you should be obtaining it via BeanManager as below instead of manually constructing the instance (assuming Java EE 7 / CDI 1.1 available):
#SuppressWarnings("unchecked")
public static <T> T getCurrentInstance(Class<T> beanClass) {
BeanManager beanManager = CDI.current().getBeanManager();
Bean<T> bean = (Bean<T>) beanManager.resolve(beanManager.getBeans(beanClass));
return (T) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
}
Usage:
UserAuthenticator userAuthenticator = YourCDIUtil.getCurrentInstance(UserAuthenticator.class);
// ...
See also:
Java singleton class vs JSF application scoped managed bean - differences?
Java EE 6 and Singletons
Well i think you shouldn't explictly call UserAuthenticator.getInstance() but to define the UserAuthenticator for example as #ApplicationScoped and get the instance via DI provided by your app server (#Inject).
UserAuthenticator should be then initialized properly.
The #PostConstruct method will not be invoked until you do some action on that class (ex: call some methods

How to access stateful session bean through remote interface proxy?

I have a testcase which makes use of OpenEjb's #LocalClient annotation (embedded container) and injects EJBs using the #EJB annotation:
#LocalClient
public class MyTestCase {
#EJB
private BoxDao boxDao;
...
}
BoxDao is a remote EJB interface. Now, for testing, I need to access some internal state of BoxDao's implementation BoxDaoBean, which is a stateful session bean. I created a protected method in BoxDaoBean, which exposes the needed internal state, but I found not yet a way to access it in my test case, since the injected BoxDao is a remote interface proxy (an cannot be cast to BoxDaoBean).
Is there a way to access the stateful session bean behind the remote interface BoxDao in the test case? Would not matter if solution is OpenEjb specific.
Update: We can't use EJB 3.1 specific solutions unfortunately, as we have several EJB 3.0 projects running. Using Proxy.getInvocationHandler(boxDao), I can get access to the OpenEjb container, via StatefulEjbObjectHandler. Is it possible to access the stateful bean this way?
You could try having BoxDaoBean also expose an #LocalBean interface. A single EJB can expose a near unlimited number of views from #WebService, #Local, #Remote, JAX-RS and more.
Just update your bean like so:
#Stateful
#LocalBean
public class BoxDaoBean implements BoxDao {
//...
}
Then add another field to your test:
#LocalClient
public class MyTestCase {
#EJB
private BoxDao boxDao;
#EJB
private BoxDaoBean boxDaoBean;
...
}

Adding a dependency to an EJB

I want to add a dependency to an EJB. How do I do this using Spring? The dependent object is a general service object. Based on code below I want to wire myDependency without having to use 'new'.
The EJB runs in weblogic.
#Stateless(mappedName = "MyBean")
public class MyBean implements MyBeanRemote, MyBeanLocal {
#EJB(name = "MyOtherBean")
private MyOtherBean myOtherBean;
private MyDependency myDependency;
...
}
This is well described in the Spring documentation:
For EJB 3 Session Beans and Message-Driven Beans, Spring provides a
convenient interceptor that resolves Spring 2.5's #Autowired
annotation in the EJB component class:
org.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor.
This interceptor can be applied through an #Interceptors annotation in
the EJB component class, or through an interceptor-binding XML element
in the EJB deployment descriptor.
#Stateless
#Interceptors(SpringBeanAutowiringInterceptor.class)
public class MyFacadeEJB implements MyFacadeLocal {
// automatically injected with a matching Spring bean
#Autowired
private MyComponent myComp;
// for business method, delegate to POJO service impl.
public String myFacadeMethod(...) {
return myComp.myMethod(...);
}
...
}
Stateless EJBs and Spring beans, however, offer more or less the same possibilities. Mixing them together seems like unnecessary complexity.

Categories

Resources