8
votes

I have a @RequestScoped CDI bean that I want to turn into an EJB to get declarative transactions. (I'm on EJB 3.1, Java EE 6)

Currently, I am passing state between subroutines, under the assumption that the instance is only used in a single request. If I add @Stateless now that assumption would change.

For example, I want to do something like

@Stateless
@Named
@RequestScoped
public class Foo {
  private String var1; // can't use instance vars in @Stateless?
  private String var2;

  public void transactionForRequest() {
    var1 = value; 
    var2 = value;
    ....
    subroutine();
  }
}

I assume the above doesn't work- is that correct?

I am contemplating two alternatives:

  • Use @Stateful instead of @Stateless, along with @Named and @RequestScoped.
  • Keep @Stateless and use EJBContext.getContextData map to replace instance variables.

Which is better? And is there some other alternative I'm not thinking of? (Besides wait for Java EE 7 or switch to Spring. :-))

3
Using @Stateful may be an over-skill. Have you considered using normal Stateless bean and @ConversationScoped managed bean to pass states?Mr.J4mes
how would this work - would you make the EJB @Stateless then @Inject a CDI bean? Could this CDI bean be @RequestScoped?wrschneider
I'd keep the bean as @Stateless and use @ConversationScoped bean to pass variables from pages to pages. Check out this article about creating wizard.Mr.J4mes
I'm not trying to have a wizard-like conversation - I'm trying to pass variables between subroutines in the scope of a single HTTP request / DB transaction.wrschneider
If so, @SessionScoped bean with Stateless bean may still be easier to manage than Stateful bean.Mr.J4mes

3 Answers

12
votes

While @Stateless, @Singleton and @MessageDriven can have scoped references injected via @Inject, they cannot be @RequestScoped or any other scope. Only the @Stateful model is flexible enough to support scopes. In other words, you can annotate the @Stateful bean class itself as @RequestScoped, @SessionScoped, etc..

In simple terms @Stateless, @Singleton have fixed "scopes" already. @Singleton is essentially @ApplicationScoped and @Stateless would perhaps be some made-up scope like @InvocationScoped, if that existed. The lifecycle of an @MessageDriven bean is entirely up to the Connector that drives it and is therefore also not allowed to have user-defined scope.

See also https://stackoverflow.com/a/8720148/190816

3
votes

I would go with SFSB instead of SLSB. You want to hold a state, so for me this is the most important information - this is a job for Stateful EJB.

Also I don't think that EJBContext#getContextData() would help you. As far as I remember, it's only valid for a duration of a call. Therefore, each invocation of a method on your EJB will create new context data map (at least it's what I would expect.)

1
votes

If you are using Stateless beans then you are responsible for any state-management and you would normally do this in the web-app layer using HttpSessions. And yes, you can't use instance variables as stateless beans are pooled.