tags:

views:

47

answers:

1
for (...) {
    UserList userList = (UserList) Component.getInstance(UserList.class, ScopeType.METHOD);
    userList.getUserByEmailAddress(emailId);
}

There are different ScopeTypes which are supported by Seam (e.g. METHOD, PAGE, EVENT, APPLICATION). We currently use the METHOD scope to retrieve User object by email id. The above code is present in a for loop (i.e. for a collection of user email addresses we retrieve the user object). Is this the right ScopeType or would it be preferable to move the UserList declaration above the for loop

We have observed in certain scope types that the userList object gets reused, can someone clarify on how it really works. Are there any tools within seam which will help you understand how these objects get reused (We turned on some trace logging, but there were too many calls which were being made and it was not quite clear)

+1  A: 

ScopeType.METHOD says

Each call to a session bean or JavaBean component puts a new method context onto the stack of method contexts associated with the current thread. The context is destroyed when the method returns.

Much of the functionality of Seam is implemented as a set of built-in Seam interceptors. Here goes a piece of code of MethodContextInterceptor (built-in Seam interceptor) which API says

Sets up the METHOD context and unproxies the SFSB for the duration of the call

MethodContextInterceptor.java See comments bellow and compare with The highlighted Text above

@AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception {
    Component comp = getComponent();

    String name = comp.getName();
    Object target = ctx.getTarget();
    Method method = ctx.getMethod();
    Object[] parameters = ctx.getParameters();

    /**
      * beginMethod
      *
      * Takes care of putting a NEW method context onto the stack of method contexts
      */
    Context outerMethodContext = Lifecycle.beginMethod();

    try {
        Contexts.getMethodContext().set(name, target);
        Contexts.getMethodContext().set("org.jboss.seam.this", target);
        Contexts.getMethodContext().set("org.jboss.seam.method", method);
        Contexts.getMethodContext().set("org.jboss.seam.parameters", parameters);
        Contexts.getMethodContext().set("org.jboss.seam.component", comp);

        /**
          * And after method return 
          */ 
        return ctx.proceed();
    } finally {
        /**
          * endMethod Takes care of destroying The previous added method context
          */       
        Lifecycle.endMethod(outerMethodContext);
    }
}

As you can see, i do not see any special behavior provided by ScopeType.METHOD. I Think Gavin King, founder of Seam project, has created The ScopeType.METHOD as an additional scope which could be used posteriorly. Even Seam in Action book does not cover ScopeType.METHOD scope.

So each Time you call getUserByEmailAddress, The routine above is performed. About context, Seam in Action book is clear

A context defines where a variable name can be found and for how long it hangs around

So your desired scope should draw your business requiment.

About EntityQuery ??? Here goes what Seam in Action book says

If you execute the query every time you need to present the results, you put undo pressure on the database. At the other extreme, if you hold onto the results for too long, you end up feeding users with stale information that may confuse them, or worse, cause them to make wrong decisions.

By default, some Query methods avoid redundant database queries by caching the results in a private property on the class. But it can be overrided since you change

  • A query restriction parameter
  • The sort order
  • The maximum result value
  • The first result offset
  • The results are manually cleared by a call to refresh()

The last item is useful when you update some @Entity and you need To refresh The stored result set. You can accomplish it by using a Seam event. But if you always want a fresh result set, set up your EntityQuery as ScopeType.EVENT and use it before for loop instead

UserList userList = (UserList) Component.getInstance(UserList.class, ScopeType.EVENT);
for (...) {
    userList.getUserByEmailAddress(emailId);
}

Here goes a side by side comparison between Seam and Spring scope

Seam                               Spring            Suited for
ScopeType.STATELESS                singleton         Service, repositories, Thread-safe components
ScopeType.APPLICATION              singleton         Service, repositories, Thread-safe components
ScopeType.SESSION                  session           User login
ScopeType.CONVERSATION             -                 Page flow
ScopeType.PAGE                     -                 Server-side based component model
ScopeType.EVENT                    request           Non Thread-safe components

Notice ScopeType.CONVERSATION is not equal To Spring web flow. Seam ScopeType.CONVERSATION goes beyond web layer. Even an persistence context can be included in conversation context. Keep in mind ScopeType.PAGE makes sense when you have a server-side based component model framework such as JSF, Wicket and so on... Usually, ScopeType.STATELESS is used when you have an fully JEE environment and ScopeType.APPLICATION when you use plain POJO's instead of EJB.

Arthur Ronald F D Garcia