What are the techniques to manage "session" or invocation context for Stateless EJBs during Remote calls?

786 views Asked by At

I am writing an application that uses RMI to invoke EJBs. The EJBs are Stateless; the business requirements do not require conversational state with the client.

One of the parameters to the EJB method calls is a "User" object used to determine if the user associated with the call has permission to perform the action. We are not using container-managed auth-auth: the User object is just a POJO provided by the remote client.

I would like to make this User object globally available/injectable within the "session" or invocation context. I am aware that Stateless EJBs do not have a "session" in the EJB sense; what I mean by "session" is "the current invocation". For example, say we have only one remote EJB with two methods:

  • myStatelessEjb.add(Thing, User)
  • myStatelessEjb.update(Thing, User)

These methods call many more methods: there are other EJBs involved, Bean Validators, etc. Rather than passing-around the User object everywhere, I would like to make the User object globally available/injectable with the context of the current remote EJB invocation.

I could of course just pass around the User object or encapsulate it with "Thing", but I thought maybe it would be a better design to not "pollute" my objects and APIs with User since it's a cross-cutting concern.

Notes (for emphasis):

  • I am using RMI.
  • There is no HTTP session, because I am using RMI.
  • I am not using container-managed auth-auth.
  • I am using container-managed transactions.

Is there a standard technique suitable for this problem? e.g. Perhaps the remote client should invoke a Stateful EJB which will hold the User, or maybe ThreadLocal is appropriate, or maybe I can hook onto the container-managed transaction, or maybe there's already an applicable session/context I'm unaware of.

1

There are 1 answers

1
dngfng On BEST ANSWER

Easiest way would be to store the user in a @RequestScoped CDI bean and inject that as required:

@RequestScoped
public class RequestUser {
    private User user;

    //getter and setter for user
}

@Remote
@Statless
public class MyRemoteInterface {
   @Inject
   private RequestUser requestUser;
   ...
   public void foo(User user, Bar bar) {
      request.setUser(user);
      ...
   }
}

@Stateless
public class OtherEJB() {
    @Inject
    private RequestUser user;

    public void doBar(Bar bar) {
        User user = user.getUser();
        ...
    } 
}

While @SessionScoped is useful for HTTP sessions only, @RequestScoped has broader applicability:

public @interface RequestScoped

Specifies that a bean is request scoped.

The request scope is active:

  • during the service() method of any servlet in the web application, during the doFilter() method of any servlet filter and when the container calls any ServletRequestListener or AsyncListener,
  • during any Java EE web service invocation,
  • during any remote method invocation of any EJB, during any asynchronous method invocation of any EJB, during any call to an EJB timeout method and during message delivery to any EJB message-driven bean, and
  • during any message delivery to a MessageListener for a JMS topic or queue obtained from the Java EE component environment.