How to access stateful session bean through remote interface proxy? - java

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;
...
}

Related

EJB 3.1 - Why sateless bean must be injected by its interface (if there is one)?

Since EJB 3.1, beans don't need to have a Local interface, and I usually don't use one:
#Stateless
public class MyService(){
public void buisnesssMethodA(){
...
}
public void buisnesssMethodB(){
...
}
}
and in my CDI bean I just do
#Inject
private MyService myService;
This is easy and simple and it works just fine.
Now I have recently discovered something.
Imagine I need an interface that represents a subset of my business method.
public interface MyInterface{
void businessMethodA();
}
Now if I make my Stateless bean implement this interface, JBoss fails to deploy and throws the error
WELD-001408 Unsatisfied dependencies for type [MyService] with qualifiers [#Default] at injection point [[field] #Inject
So I believe I'm observing the following rule:
If a stateless bean doesn't have an interface it can be injected using the class. If it implements an interface it must be injected using the interface.
Here are my questions:
Is this rule correct?
If so is it defined by the EBJ specs?
What would be the reason for this restriction?
From my limited knowledge of Java EE and CDI:
CDI does not manage EJB 3.1 stateless session beans by itself (it wouldn't have all the lifecycle and interceptors) but it can #Inject exposed local views of those beans
session bean may expose local business interface view if it has an interface or no-interface view (consisting of beans public methods)
in Java EE 7 when session bean does not implement any interface, by default it exposes no-interface view - hence you could inject MyService without interface. This is equivalent to annotating bean with #LocalBean. Note that with #LocalBean you expose no-inerface view even if the bean class implements an interface - hence the comment from Tom worked
in Java EE 7 if the session bean implements an interface and is not marked #LocalBean, this interface is by default exposed as local view of the bean - hence you could not inject MyService after it implemented MyInterface, since no-interface view (MyService) was no longer exposed, and interface view MyInterface was exposed as local view instead
Hope this answers your question 3, and partly confirms, partly invalidates your rule from questoin 1. I cannot be bothered now to answer question 2 though...

Injecting local EJB on JBoss 7.3 - #EJB vs #Inject

I have an EAR file containing a WAR.
The EAR contains an EJB jar. The EJB exposes a Local and Remote interface.
#Stateless(name = "FooServiceEJB")
#Local(IFooServiceLocal.class)
#Remote(IFooService.class)
public class FooServiceBean implements IFooService, IFooServiceLocal {
...
}
The WAR file defines a JAXRS annotated class.
#Path("/foo")
#LocalBean
#Stateless
public class FooResource {
...
}
I wish to inject the local 'view' of the EJB into the JAXRS resource class. Apparently I have two options, which I assumed would be equivalent (for the most part):
Use #EJB
Use #Inject (To many, this appears to be the preferred option - see Should I use #EJB or #Inject)
I'm running JBoss EAP 6.2.0.GA (AS 7.3.0.Final-redhat-14).
The difference in behaviour that I am seeing is as follows (on JBoss - haven't tried any other app servers):
If I use #EJB to inject the local ejb, then the call semantics are by reference (as expected). For example:
#EJB
private FooServiceLocal fooService;
However, if I use #Inject to inject the local ejb, the call semantics are by value (i.e. serialization occurs). For example:
#Inject
private IFooServiceLocal fooService;
Here's a snapshot of the thread stack with the class that I believe is performing the serialization. The thread stack is completely different when I use the #EJB annoation.
http://i.stack.imgur.com/BXSaz.png
Any ideas why I am seeing this difference in behaviour?

#Inject, #EJB, #Local, #Remote, #LocalBean, etc... : confused?

I have the following configuration:
1 EAR on one GF containing 2 EJB-JARs with EJB components.
1 WAR on another Glassfish server (=> other JVM) containing web components accessing the EJB components.
I have 2 EJB business services in each EJB-JAR of my EAR, and they are all developped like this:
#Remote
public interface ServiceAItf {
...
}
#Stateless
#Local
public class ServiceAImpl implements ServiceAItf {
...
}
In my WAR, I access the EJB components via an explicit "InitialContext.lookup" on the remote interface.
In my EAR, I am quite confused about the best practice for injection, in terms of performance, architecture, and so on...
I have the following questions:
As you can see, I have declared the annotation "#Local" on the service implementation without defining the local interface. Is it correct? At least I have no error at deployment. But maybe I should use the "#LocalBean" annotation instead? I suppose that the "#LocalBean" annotation simply allows to invoke the implementation directly as a "Local" EJB, but you have to use the implementation in your code like this:
#Stateless
#Local
public class ServiceBImpl implements ServiceBItf {
#EJB
private ServiceAImpl serviceA;
...
}
What is the best way to inject one EJB into another one?
It works like this:
#Stateless
#Local
public class ServiceBImpl implements ServiceBItf {
#EJB
private ServiceAItf serviceA;
...
}
But from what I noticed, the "serviceA" injected is the remote proxy, while it is in the same JVM within the same EAR file. So I suppose that there will be an impact on the performance. That's why I have tried to inject the service like this:
#Stateless
#Local
public class ServiceBImpl implements ServiceBItf {
#Inject
private ServiceAItf serviceA;
...
}
But it doesn't work in GF, I have the following exception:
WELD-001408 Unsatisfied dependencies for type [...] ...
I then tried to create a local interface, and the injection via the annotation "#Inject" works when both services
Even if I create a local interface like this, the service is not injected via the annotation "#Inject" but is null:
#Local
public interface ServiceALocalItf {
...
}
I read a lot of articles where it is highly recommended to use "#Inject" instead of "#EJB" when it is for a local invocation. That leads me to the following question: in which case the "#Local" EJB invocation is recommended (or simply used)?
After all this analysis, I come to the following conclusion:
For each service, I create a "#Local" and a "#Remote" interface.
From WAR to EJB-JAR of EAR, make a JNDI lookup to the remote interface.
From EJB-JAR to EJB-JAR, make an injection via "#EJB" to the local interface.
For two services within the same EJB-JAR, make an injection via "#Inject" to the local interface.
What do you think about it? Is it correct?
As you can see, I have declared the annotation "#Local" on the service
implementation without defining the local interface. Is it correct?
With EJB 3.1, the requirement for local interfaces was dropped. No need to write them unless you explicitly need them.
What is the best way to inject one EJB into another one?
Couple of things to write here:
With Java EE 6, Java Enterprise has changed. A new JSR defines a so-called managed bean (don't confuse with JSF managed beans) as a sort of minimum component that can still benefit from the container in terms of dependency injection and lifecycle management. This means: If you have a component and "just" want to use DI and let the container control its lifecycle, you do not need to use EJBs for it. You'll end up using EJBs if - and only if - you explicitly need EJB functionality like transaction handling, pooling, passivation and clustering.
This makes the answer to your question come in three parts:
Use #Inject over #EJB, the concept of CDI (a) works for all managed
beans (this includes EJBs) and (b) is stateful and therefore far
superior over pure #EJB DI
Are you sure that you need EJBs for your
components?
It's definitely worthwhile to have a look at the CDI
documentation
#Inject annotation is used for java beans(POJOs) while #EJB annotation is used for enterprise java beans. When a container inject an ejb provided by #EJB annotation to another bean it also controls that ejb's lifecycle, performs pooling for stateless beans and so on(when bean which is going to be injected is not deployed the reference will be null). If you use #Inject annotation CDI mechanism simply find and create an instance of injected resource like with new operator(if the implementation of interface which is going to be injected doesn't exist the reference will be null). You can use qualifiers with #Inject annotation to choose different implementation of injected interface.

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.

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

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

Categories

Resources