Hi,

I've been looking at how Spring implements its custom scopes feature,
and how this interacts with JSF.

Can someone verify that I understand this right?

The class org.springframework.web.jsf.DelegatingVariableResolver is
configured as the var-resolver for a JSF webapp, via faces-config.xml. 

This class first delegates to the standard JSF var-resolver, which
directly looks in request, session and app scopes for the name. If it
finds the var, it just returns - this is pretty quick. If it fails, it
looks in its config for the name, and if found then it creates the bean,
adds it to the scope and returns - again fairly quick.

If this process fails (ie bean not in request, session or app scope and
no definition in the standard JSF manner) then
DelegatingVariableResolver calls
org.springframework.beans.factory.support.AbstractBeanFactory.getBean(...).

This code first checks its singleton cache. If it doesn't find an
already-created bean there then it looks up its bean definition.
* If the type is "singleton" then it creates a new instance, puts it in
the singleton cache then returns. 
* If the type is "prototype" then it creates a new instance, and returns
it without caching it anywhere.
* If the type is a custom scope then it finds the appropriate registered
scope-handler and invokes its get method, passing an ObjectFactory
object that knows how to create an instance from the bean definition it
has already located.

For the request and session scopes, the scope-handlers first look in the
request or session - but will never find anything, otherwise the JSF
var-resolver would have found it earlier. So they use the ObjectFactory
to create the bean and store it in the request/session. On later
attempts by JSF to look up this bean, the standard JSF var-resolver will
find it immediately in the request/session which is nice and efficient.

For the "conversation" scope, however, things are not so efficient. The
JSF variable resolver will never find the bean in request/session. The
AbstractBeanFactory.getBean method will not find the object in the
singleton cache either. It will therefore have to locate the bean
definition, then invoke the 
o.a.m.orchestra.conversation.spring.SpringConversationScope.get method.
This method locates the spring bean definition *again* in order to find
the conversation name, then retrieves the current ConversationContext,
from that the right conversation, and then from the conversation the
actual bean. When the bean already exists, it is then returned and
otherwise it is created and added to the conversation.

This does seem a pretty slow process to go through for every EL
reference to a conversation-scoped bean. 

I don't mean to criticise, and I certainly don't have any optimisations
to suggest ATM; I would just like to know if I've understood this right,
or whether I have missed something that optimises access to
conversation-scoped beans. It seems to me that:
* access to Prototypes can't really be optimised as they are created
each time by definition
* access to Singletons is efficient as they are cached
* access to request/session vars is not very good when using Spring
alone, but because the JSF var-resolver looks into request and session
objects this allows the objects to be retrieved without passing through
spring at all.
* access to conversation vars is going to be slow because every lookup
requires a pass through Spring, resulting in quite a lot of processing -
including lookup of the bean def, which can be quite complicated.

Regards,

Simon

Reply via email to