Forget Session, Application, Request, and Coversation Scope. All these scopes, though useful, still have to be managed by hand. ie.,
– a reference must be created in a session or request (the context)
– a utility method must be written to manage this context (& cleanup eventually)
– the component needs to have access to this utlity method or the context (session, request) to retrive the reference
Most importantly, the “client” component and original “context holder” have direct coupling of the refereced object. With JSR299, it’s like this:
a reference to any object can be injected into any object without actually referring to the object
Really? That’s crazy.
Exactly.
JSR299 container manages thereferences for you in a context (session, requestm, conversation, etc.,) and provides a type-safe way of retrieving these references by a quaifier annotation. For ex, let’s say a PersonSearch Service needs to know the currently logged in user. Normally, you would use a utility function that will return the user. In Spring that would be SecurityContextHolder.getContext().getAuthentication().getPrincipal(). In Seam, it would be something simpler. But what if you don’t want to deal with a service that takes no method parameters and all that you want is a typed object in return?
Think. No parameters.
Would it be easier if you had somethinkg like this?
@LoggedIn Principal principal;
in your service bean?
By injecting this annotated field, any component in the application can get the “reference to loggedIn user object.” The container holds this reference for any component that asks for it, and it holds it in the scope that the original reference was created. In this case, maye an Authenticator bean created it to keep it in SessionScope. In other words, any “managed” bean (ie., managed by the container, so Stateless, SessionScoped, ApplicatinScoped, etc.,) can get the reference to the logged in user by simply injecting a User object with a qualifier @LoggedInUser. Forget about static methods and manual context management!
But how do you create a @LoggedIn user? Simple, actually.
@Produces @LoggedIn @Named
public User getCurrentUser() {
return currentUser;
}
In this case, a sessionScoped Authenticator component has a method that returns an instance variable, currentUser.
The advantage of this is loose coupling and at the same time, strong typing. Further, by providing multiple qualifier like @Produces and overriding scopes, the injectable object can be custom defined both at the injectable context and the point of creation (Producer).
Another fine example. Let’s say in the above person search, you want to return the list of persons and tie it to the request scope so that any other component in the same underlying request cycle can retrieve it (JSF page).
@Produces @Named @RequestScoped
public List&<Person> getPersons() {
return em.createQuery( "select p from Person p" ).getResultList();
}
Even better, you’d like to have a static lookup across the session.
@Produces @Named @SessionScoped public List<Person> getPersons() {
return em.createQuery( "select p from Person p" ).getResultList();
}
But how do you then update the search list in the session if a new person was added in the same session? Welcome to JEE 6 build in Event Model.
public void onPersonListChanged(
@Observes( notifyObserver = Reception.IF_EXISTS )
final Person person ) {
getPersons();
}
See here to understand what @Reception means.