org.apache.myfaces.orchestra.conversation.spring
Class AbstractSpringOrchestraScope

java.lang.Object
  extended by org.apache.myfaces.orchestra.conversation.spring.AbstractSpringOrchestraScope
All Implemented Interfaces:
ConversationFactory, org.springframework.beans.factory.BeanFactoryAware, org.springframework.beans.factory.config.Scope, org.springframework.context.ApplicationContextAware
Direct Known Subclasses:
SpringConversationScope, SpringViewControllerScope

public abstract class AbstractSpringOrchestraScope
extends Object
implements ConversationFactory, org.springframework.beans.factory.config.Scope, org.springframework.beans.factory.BeanFactoryAware, org.springframework.context.ApplicationContextAware

Abstract basis class for all the Orchestra scopes.

A scope object has two quite different roles:

  1. It handles the lookup of beans in a scope, and creates them if needed
  2. It handles the creation of Conversation objects, using the spring properties configured on the scope object.

This base class handles item 1 above, and leaves item 2 to a subclass. The declaration of interface ConversationFactory needs to be on this class, however, as the createBean method needs to invoke it.


Constructor Summary
AbstractSpringOrchestraScope()
           
 
Method Summary
protected  void assertSameScope(String beanName, Conversation conversation)
          Verify that the specified conversation was created by this scope object.
protected  String buildBeanName(String name)
          Deprecated. Should not be necessary in user code.
 void defineBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory cbf)
          Register any BeanPostProcessors that are needed by this scope.
 Object get(String name, org.springframework.beans.factory.ObjectFactory objectFactory)
          This is invoked by Spring whenever someone calls getBean(name) on a bean-factory and the bean-definition for that bean has a scope attribute that maps to an instance of this class.
protected  org.aopalliance.aop.Advice[] getAdvices()
           
protected  org.springframework.context.ConfigurableApplicationContext getApplicationContext()
           
protected  Conversation getConversationForBean(String beanDefName)
          Get the conversation for the given beanName.
 String getConversationId()
          Return the conversation context id.
 String getConversationNameForBean(String beanName)
          Get the conversation-name for bean instances created using the specified bean definition.
protected  String getExplicitConversationName(org.springframework.beans.factory.config.BeanDefinition beanDef)
          Return the explicit conversation name for this bean definition, or null if there is none.
protected  Object getProxy(String beanName, org.springframework.beans.factory.ObjectFactory objectFactory)
          Return a CGLIB-generated proxy class for the beanclass that is specified by the provided beanName.
protected  Object getRealBean(String conversationName, String beanName, org.springframework.beans.factory.ObjectFactory objectFactory)
          Get a real bean instance (not a scoped-proxy).
protected  void notifyAccessConversation(Conversation conversation)
           
 void registerDestructionCallback(String name, Runnable runnable)
          Add the given runnable wrapped within an ConversationBindingListener to the conversation map.
 Object remove(String name)
           
 void setAdvices(org.aopalliance.aop.Advice[] advices)
          The advices (interceptors) which will be applied to the conversation scoped bean.
 void setApplicationContext(org.springframework.context.ApplicationContext applicationContext)
          Get an ApplicationContext injected by Spring.
 void setAutoProxy(boolean state)
          Configuration for a scope object to control whether "scoped proxy" objects are automatically wrapped around each conversation bean.
 void setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory)
          Invoked by Spring to notify this object of the BeanFactory it is associated with.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface org.apache.myfaces.orchestra.conversation.ConversationFactory
createConversation
 

Constructor Detail

AbstractSpringOrchestraScope

public AbstractSpringOrchestraScope()
Method Detail

setAdvices

public void setAdvices(org.aopalliance.aop.Advice[] advices)
The advices (interceptors) which will be applied to the conversation scoped bean. These are applied whenever a method is invoked on the bean [1].

An application's spring configuration uses this method to control what advices are applied to beans generated from this scope. One commonly applied advice is the Orchestra persistence interceptor, which ensures that whenever a method on a conversation-scoped bean is invoked the "global persistence context" is set to the context for the conversation that bean is in.

Note [1]: the advices are only applied when the bean is invoked via its proxy. If invoked via the "this" pointer of the object the interceptors will not run. This is generally a good thing, as they are not wanted when a method on the bean invokes another method on the same bean. However it is bad if the bean passes "this" as a parameter to some other object that makes a callback on it at some later time. In that case, the bean must take care to pass its proxy to the remote object, not itself. See method ConversationUtils.getCurrentBean().


getAdvices

protected org.aopalliance.aop.Advice[] getAdvices()
Since:
1.1

setAutoProxy

public void setAutoProxy(boolean state)
Configuration for a scope object to control whether "scoped proxy" objects are automatically wrapped around each conversation bean.

Automatically applying scope proxies solves a lot of tricky problems with "stale" beans, and should generally be used. However it does require CGLIB to be present in the classpath. It also can impact performance in some cases. Where this is a problem, this flag can turn autoproxying off. Note that the standard spring aop:scoped-proxy bean can then be used on individual beans to re-enable proxying for specific beans if desired.

This defaults to true.

Since:
1.1

getConversationId

public String getConversationId()
Return the conversation context id.

Note: This conversationId is something spring requires. It has nothing to do with the Orchestra conversation id.

TODO: what does Spring use this for????

Specified by:
getConversationId in interface org.springframework.beans.factory.config.Scope

get

public Object get(String name,
                  org.springframework.beans.factory.ObjectFactory objectFactory)
This is invoked by Spring whenever someone calls getBean(name) on a bean-factory and the bean-definition for that bean has a scope attribute that maps to an instance of this class.

In the normal case, this method returns an internally-created proxy object that fetches the "real" bean every time a method is invoked on the proxy (see method getRealBean). This does obviously have some performance impact. However it is necessary when beans from one conversation are referencing beans from another conversation as the conversation lifetimes are not the same; without this proxying there are many cases where "stale" references end up being used. Most references to conversation-scoped objects are made via EL expressions, and in this case the performance impact is not significant relative to the overhead of EL. Note that there is one case where this proxying is not "transparent" to user code: if a proxied object passes a "this" pointer to a longer-lived object that retains that pointer then that reference can be "stale", as it points directly to an instance rather than to the proxy.

When the Spring aop:scoped-proxy feature is applied to conversation-scoped beans, then this functionality is disabled as aop:scoped-proxy has a very similar effect. Therefore, when this method detects that it has been invoked by a proxy object generated by aop:scoped-proxy then it returns the real object (see getRealBean) rather than another proxy. Using aop:scoped-proxy is somewhat less efficient than Orchestra's customised proxying.

And when the orchestra proxy needs to access the real object, it won't call this method; instead, getRealBean is called directly. See class ScopedBeanTargetSource.

Specified by:
get in interface org.springframework.beans.factory.config.Scope

getProxy

protected Object getProxy(String beanName,
                          org.springframework.beans.factory.ObjectFactory objectFactory)
Return a CGLIB-generated proxy class for the beanclass that is specified by the provided beanName.

When any method is invoked on this proxy, it invokes method getRealBean on this same instance in order to locate a proper instance, then forwards the method call to it.

There is a separate proxy instance per beandef (shared across all instances of that bean). This instance is created when first needed, and cached for reuse.

Since:
1.1

getRealBean

protected Object getRealBean(String conversationName,
                             String beanName,
                             org.springframework.beans.factory.ObjectFactory objectFactory)
Get a real bean instance (not a scoped-proxy).

The appropriate Conversation is retrieved; if it does not yet exist then it is created and started. The conversation name is either specified on the bean-definition via a custom attribute, or defaults to the bean name.

Then if the bean already exists in the Conversation it is returned. Otherwise a new instance is created, stored into the Conversation and returned.

When a bean is created, a proxy is actually created for it which has one or more AOP "advices" (ie method interceptors). The CurrentConversationAdvice class is always attached. Note that if the bean definition contains the aop:proxy tag (and most do) then the bean that spring creates is already a proxy, ie what is returned is a proxy of a proxy.

Parameters:
conversationName -
beanName - is the key within the conversation of the bean we are interested in.
Since:
1.1

assertSameScope

protected void assertSameScope(String beanName,
                               Conversation conversation)
Verify that the specified conversation was created by this scope object.

Parameters:
beanName - is just used when generating an error message on failure.
conversation - is the conversation to validate.

notifyAccessConversation

protected void notifyAccessConversation(Conversation conversation)

setBeanFactory

public void setBeanFactory(org.springframework.beans.factory.BeanFactory beanFactory)
                    throws org.springframework.beans.BeansException
Invoked by Spring to notify this object of the BeanFactory it is associated with.

This method is redundant as we also have setApplicationContext. However as this method (and the BeanFactoryAware interface on this class) were present in release 1.0 this needs to be kept for backwards compatibility.

Specified by:
setBeanFactory in interface org.springframework.beans.factory.BeanFactoryAware
Throws:
org.springframework.beans.BeansException

defineBeanPostProcessors

public void defineBeanPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory cbf)
                              throws org.springframework.beans.BeansException
Register any BeanPostProcessors that are needed by this scope.

This is an alternative to requiring users to also add an orchestra BeanPostProcessor element to their xml configuration file manually.

When a bean instance is created by Spring, it always runs every single BeanPostProcessor that has been registered with it.

Throws:
org.springframework.beans.BeansException
Since:
1.1

getConversationForBean

protected Conversation getConversationForBean(String beanDefName)
Get the conversation for the given beanName. Returns null if the conversation does not exist.


getConversationNameForBean

public String getConversationNameForBean(String beanName)
Get the conversation-name for bean instances created using the specified bean definition.


getExplicitConversationName

protected String getExplicitConversationName(org.springframework.beans.factory.config.BeanDefinition beanDef)
Return the explicit conversation name for this bean definition, or null if there is none.

This is a separate method so that subclasses can determine conversation names via alternate methods. In particular, a subclass may want to look for an annotation on the class specified by the definition.

Since:
1.1

buildBeanName

protected String buildBeanName(String name)
Deprecated. Should not be necessary in user code.

Strip off any Spring namespace (eg scopedTarget).

This method will simply strip off anything before the first dot.


remove

public Object remove(String name)
Specified by:
remove in interface org.springframework.beans.factory.config.Scope

registerDestructionCallback

public void registerDestructionCallback(String name,
                                        Runnable runnable)
Add the given runnable wrapped within an ConversationBindingListener to the conversation map.

This ensures it will be called during conversation destroy.

Spring calls this method whenever a bean in this scope is created, if that bean has a "destroy method". Note however that it appears that it can also call it even for beans that do not have a destroy method when there is a "destruction aware" BeanPostProcessor attached to the context (spring version 2.5 at least).

When an aop:scoped-proxy has been used inside the bean, then the "new" definition does not have any scope attribute, so orchestra is not invoked for it. However the "renamed" bean does, and so this is called.

Specified by:
registerDestructionCallback in interface org.springframework.beans.factory.config.Scope

setApplicationContext

public void setApplicationContext(org.springframework.context.ApplicationContext applicationContext)
                           throws org.springframework.beans.BeansException
Get an ApplicationContext injected by Spring. See ApplicationContextAware interface.

Specified by:
setApplicationContext in interface org.springframework.context.ApplicationContextAware
Throws:
org.springframework.beans.BeansException

getApplicationContext

protected org.springframework.context.ConfigurableApplicationContext getApplicationContext()
Since:
1.2


Copyright © 2012 The Apache Software Foundation. All Rights Reserved.