Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

access existing instance stateful inside stateless, java ee 6

Is it possible to access a stateful session bean inside a stateless bean?

My problem is that I have a session bean called User and I want to access user info inside a stateless bean...

I am trying like this:

Ejb Side:

@Stateless
public class OfferManagerBean implements OfferManagerLocal, OfferManager
{
    @Resource 
    private SessionContext context;
    @EJB
    private ro.project.ejb.interfaces.User user;
    public String getUsername()
    {
        user = (ro.project.ejb.interfaces.User) context.lookup("java:global/project/projectEJB/User!ro.project.ejb.interfaces.User");
        return user.getUsername();
}

Client side

 User user = (User) ctx.lookup("java:global/project/projectEJB/User!ro.project.ejb.interfaces.User");
 user.setUsername("Alex");

 OfferManager offerManager = (OfferManager) ctx.lookup("java:global/project/projectEJB/OfferManagerBean!ro.project.ejb.interfaces.OfferManager");
 assertEquals(offerManager.getUsername(), "Alex");

The result of this test case is java.lang.AssertionError: expected:<null> but was:<Alex>

it fails.. It seems that how I am requesting the stateful bean is returning me a new instance...

  1. I know why this is not working. Because my test fails :P. I get a new instance..
  2. I want to check certain permissions of the logged in user in EJB because I don't want to count on the client side because I might do a mistake there or I will tell other developers to make a GUI for my project..
  3. I don't want to use Java EE Security beucause I don't know how to make the login in a RCP Application
  4. My main question is: How do I access a session bean (the same one the client own) inside an EJB.. is it possible? And how?

I am asking almost the same thing this guy is asking: Concept for reusable login session in rmi ejb calls

I want to do that but not with JAAS...

Thank you in advance

like image 737
Alex Avatar asked Dec 04 '22 17:12

Alex


2 Answers

You should never inject a @Stateful bean (SFSB) in a @Stateless bean (SLSB). A SFSB lives as long as its client lives (the client is the instance where the SFSB is been injected, which is in this case the SLSB itself). SLSB's are however intented to be stateless and most containers have them in a pool. So whenever the SLSB goes back to the pool after use, it will be reused entirely elsewhere, but it holds the same SFSB instance as it was when the SLSB was been created for the first time! This may lead to undesireable results.

Also, everytime when you get the SFSB from JNDI, you will get a brand new instance which is unlike SLSBs not shared elsewhere. The SFSB's client is then the current client class instance where you've got the SFSB from JNDI. You're supposed to keep hold of this instance yourself and reuse the very same instance until you're finished with performing the transaction on it. One of the ways is storing it in the HTTP session yourself or in a session scoped managed bean of the MVC framework you're using.

The functional requirement is not entirely clear to me, so it's hard to give a suitable answer how to solve your particular problem, but I have the impression that you actually need to store the user in the HTTP session, not in a SFSB. The most common beginner's mistake as to session beans is namely that they incorrectly interpret the "session" in EJB context as being the HTTP session.

See also this related answer on a question of the same kind for a more in-depth explanation: JSF request scoped bean keeps recreating new Stateful session beans on every request? According to your question history you're familiar with JSF, so this answer should be easy understandable.

like image 196
BalusC Avatar answered Apr 28 '23 01:04

BalusC


In general it is possible to access certain existing stateful session bean inside stateless bean. It can be for example given as argument to the business method of stateless session bean.

But what you are trying cannot work. Reason is that both, dependendy injection (@EJB ) and lookup (ctx.lookup...) are guaranteed to call newInstance and as consequence you will have new instance.

This is explained in specification with following words:

A session bean instance’s life starts when a client obtains a reference to a stateful session bean instance through dependency injection or JNDI lookup, or when the client invokes a create method on the session bean’s home interface. This causes the container to invoke newInstance on the session bean class to create a new session bean instance.

like image 45
Mikko Maunu Avatar answered Apr 28 '23 00:04

Mikko Maunu