3 Replies Latest reply on Oct 25, 2010 8:32 PM by gaborj

    A few questions about interceptors

    marcelstoer

      I'm helping a few friends cleaning-up/refactoring a Seam-based project which, besides the web interface, also has a REST interface.


      Personally I'm very familiar with Spring but not with Seam - I might be biased. I've got a few questions about a piece of code whose underlying pattern I see time and time again in this project.




      @Name("activityPageController")
      @Scope(ScopeType.PAGE)
      public class ActivityPageController extends AbstractPageController {
          @In
          private FacesContext facesContext;
          @In
          private LocaleSelector localeSelector;
          @In(required = false) // outjected in Authenticator (Identity.EVENT_POST_AUTHENTICATE)
          private UserDTO loggedInUser;
          @In
          private CurrentRequest currentRequest;
          @In
          private GetName getNameService;
      
      ...some more service references...
      
          @In
          private SessionData sessionData;
          @In
          private Conversation conversation;
      
          @Override
          public void preparePage() {
              ...some code...



      While injecting dependencies as seen above seems fair in components with page scope (as with the above controller) its usage feels very wrong for the REST interface.


      In my opinion a REST interface implementation is like a facade aggregating functionality of a number of underlying services. And each REST service/facade must be stateless. Also, ideally I'd like them to be singletons with JVM-scope (i.e. one instance per JVM, which is default behavior in Spring). In my friend's project I see REST services like this:


      @Name("activityRestService")
      @Scope(ScopeType.EVENT)
      @Path("/activity")
      public class ActivityRestService {
          ...a number of service dependencies...
      
          @In
          private CreateActivity createActivityService;
      
          ...a number of service dependencies...
      
          @In(required = false) // outjected in Authenticator (Identity.EVENT_POST_AUTHENTICATE)
          private UserDTO loggedInUser;
      
          ..methods...



      I'm not quite sure whether my concepts can't be applied to Seam, whether my friends didn't use Seam properly or whether the above really is wrong. My complaints:




      • The scope is wrong (don't want a new instance for each event), but there is no singleton scope...only application but that's not quite the same (think clusters)

      • If this service is stateless I don't want the same dependent services be injected again and again before each method call (that's what @In causes). Hence, all methods should get their dependencies through Component.getInstance()???

      • If a service method really needs to get a hold of the logged in user it should get it through Component.getInstance() or some other means like ThreadLocal. Injecting the logged in user with @In effectively violates the desired statelessness of this service.




      I'd appreciate if someone familiar with Seam could explain if and where I'm wrong.



      Thanks!


      FYI, I'm familiar with the discussion about Component.getInstance vs. Injection in this forum.

        • 1. Re: A few questions about interceptors
          gaborj

          Assuming its all about Seam 2:



          • Scope is a vehicle to use for life cycle management of components in the container. So, which scope to use for your REST interface depends a lot on your dependent service components' life cycle and in general on design of your service layer. In most cases I found the CONVERSATION scope applicable, because the life cycle of Seam conversation can be controlled explicitly e.g. also depending on app logic...in some use cases I think its really useful to keep state on the server.

          • As I understand the other 2 points address the same Component.getInstance() instead on @In(jection) issue, which I also found the good way to follow in most cases. However, this is not true anymore with Seam 3 and Weld injections.



          • 2. Re: A few questions about interceptors
            marcelstoer

            Ah yes, it's about Seam 2.


            The REST interface is invoked by native mobile clients (e.g. iPhone). As such they don't maintain a conversation. Every call can be treated as an isolated incident. So, keeping those services stateless makes even more sense for me.
            However, once one starts injecting session-scoped dependencies the service is no longer stateless...


            With Seam there seems to be no out-of-the-box way to declare a JVM-wide singleton scope?

            • 3. Re: A few questions about interceptors
              gaborj

              Mobile clients can also maintain the conversation without any problem. However, if you do not need that state you simply leave them as


              Temporary Conversations. They are initialized immediately after JSF Restore View and destroyed after Render Response phase. You can still use them achieving the same result as the flash hash in Ruby on Rails: transporting data across a redirect.


              Or apparently, you can use pure @Stateless scope, for this you need an EJB container in place.


              If you want a single instance you can use Application Scope. But I do not see your point here, why would you do that?