[jboss-cvs] jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring ...
Ales Justin
ales.justin at genera-lynx.com
Fri Feb 9 12:37:18 EST 2007
User: alesj
Date: 07/02/09 12:37:18
Added: examples/spring/src/org/jboss/seam/ioc/spring
SpringComponent.java SeamScope.java
SeamNamespaceHandler.java spring.xsd
SeamPostProcessor.java SeamFactoryBean.java
Log:
Added youngm's Spring code + my initial MC code (need to write scopes first in MC in order to fully support integration with Seam).
Revision Changes Path
1.1 date: 2007/02/09 17:37:18; author: alesj; state: Exp;jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SpringComponent.java
Index: SpringComponent.java
===================================================================
package org.jboss.seam.ioc.spring;
import org.jboss.seam.ScopeType;
import org.jboss.seam.ioc.IoCComponent;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectFactory;
/**
* An extension of Component that allows spring to provide the base instance for
* a seam component.
*
* @author youngm
*/
public class SpringComponent extends IoCComponent
{
public static final String DESTRUCTION_CALLBACK_NAME_PREFIX = IoCComponent.class.getName()
+ ".DESTRUCTION_CALLBACK.";
private BeanFactory beanfactory;
private static final ThreadLocal<ObjectFactory> factoryBean = new ThreadLocal<ObjectFactory>();
/**
* Creates a Spring Seam Component given a beanFactory.
*
* @param clazz class
* @param name component name
* @param scope component scope
* @param factory factory
*/
public SpringComponent(Class clazz, String name, ScopeType scope, BeanFactory factory)
{
super(clazz, name, scope);
this.beanfactory = factory;
}
public static ObjectFactory getFactoryBean()
{
return factoryBean.get();
}
public static void setFactoryBean(ObjectFactory bean)
{
factoryBean.set(bean);
}
protected String getIoCName()
{
return "Spring";
}
protected Object instantiateIoCBean() throws Exception
{
ObjectFactory objectFactory = getFactoryBean();
if (objectFactory == null)
{
return beanfactory.getBean(getName());
}
setFactoryBean(null);
return objectFactory.getObject();
}
/**
* Calls the spring destroy callback when seam destroys the component
*
* @see org.jboss.seam.Component#callDestroyMethod(Object)
*/
@Override
public void callDestroyMethod(Object instance)
{
super.callDestroyMethod(instance);
// Cannot call the callback on a STATELESS bean
if (getScope() != ScopeType.STATELESS)
{
Runnable callback = (Runnable)getScope().getContext().get(DESTRUCTION_CALLBACK_NAME_PREFIX + getName());
if (callback != null)
{
callback.run();
}
}
}
/**
* Registers a destruction callback with this bean.
*
* @param name bean name
* @param destroy the destroy to set
*/
public void registerDestroyCallback(String name, Runnable destroy)
{
// Not sure yet how to register a stateless bean's Destruction callback.
if (getScope() != ScopeType.STATELESS)
{
getScope().getContext().set(DESTRUCTION_CALLBACK_NAME_PREFIX + name, destroy);
}
}
}
1.1 date: 2007/02/09 17:37:18; author: alesj; state: Exp;jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamScope.java
Index: SeamScope.java
===================================================================
package org.jboss.seam.ioc.spring;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.core.Events;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
/**
* Allows for the creation of seam scoped component in spring. Seam scopes are
* automatically made available if the SeamPostProcessor is declared in the
* current BeanFactory.
*
* @author youngm
* @see SeamPostProcessor
*/
public class SeamScope implements Scope
{
private static final LogProvider log = Logging.getLogProvider(SeamScope.class);
private ScopeType scope;
public SeamScope(ScopeType scope)
{
this.scope = scope;
}
/**
* Gets an instance of a Seam component providing the current ObjectFactory
* if needed.
*
* @see org.springframework.beans.factory.config.Scope#get(java.lang.String,
*org.springframework.beans.factory.ObjectFactory)
*/
public Object get(String name, ObjectFactory objectFactory)
{
try
{
SpringComponent.setFactoryBean(objectFactory);
return Component.getInstance(name, scope);
}
finally
{
SpringComponent.setFactoryBean(null);
}
}
/**
* Not used yet.
*
* @see org.springframework.beans.factory.config.Scope#getConversationId()
*/
public String getConversationId()
{
return null;
}
/**
* @see org.springframework.beans.factory.config.Scope#registerDestructionCallback(java.lang.String,
*java.lang.Runnable)
*/
public void registerDestructionCallback(String name, Runnable callback)
{
((SpringComponent)Component.forName(name)).registerDestroyCallback(name, callback);
}
/**
* On remove destroys the seam component.
*
* @see org.springframework.beans.factory.config.Scope#remove(java.lang.String)
*/
public Object remove(String name)
{
log.debug("destroying: " + name);
Component component = Component.forName(name);
Object bean = scope.getContext().get(name);
if (component != null)
{
if (bean != null) // in a portal environment, this is possible
{
if (Events.exists())
Events.instance().raiseEvent("org.jboss.seam.preDestroy." + name);
try
{
if (component.hasDestroyMethod())
{
component.callComponentMethod(bean, component.getDestroyMethod());
}
}
catch (Exception e)
{
log.warn("Could not destroy component: " + name, e);
}
}
}
Contexts.getEventContext().remove(name);
return bean;
}
}
1.1 date: 2007/02/09 17:37:18; author: alesj; state: Exp;jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamNamespaceHandler.java
Index: SeamNamespaceHandler.java
===================================================================
package org.jboss.seam.ioc.spring;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
import org.w3c.dom.Element;
/**
* @author youngm
*/
public class SeamNamespaceHandler extends NamespaceHandlerSupport
{
/**
* @see org.springframework.beans.factory.xml.NamespaceHandler#init()
*/
public void init()
{
registerBeanDefinitionParser("instance", new SeamBeanBeanDefinitionParser());
}
private static class SeamBeanBeanDefinitionParser extends AbstractSimpleBeanDefinitionParser
{
protected Class getBeanClass(Element element)
{
return SeamFactoryBean.class;
}
/* protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {
String id = super.resolveId(element, definition, parserContext);
return id;
}*/
}
}
1.1 date: 2007/02/09 17:37:18; author: alesj; state: Exp;jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/spring.xsd
Index: spring.xsd
===================================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<xsd:schema xmlns="http://jboss.com/products/seam/spring" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://jboss.com/products/seam/spring"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/tool"
schemaLocation="http://www.springframework.org/schema/tool/spring-tool-2.0.xsd"/>
<xsd:element name="instance">
<xsd:annotation>
<xsd:documentation>
Obtains an instance of a seam
</xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
<xsd:complexType>
<xsd:attribute name="id" type="xsd:ID"/>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="scope" use="optional">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="STATELESS"/>
<xsd:enumeration value="METHOD"/>
<xsd:enumeration value="EVENT"/>
<xsd:enumeration value="PAGE"/>
<xsd:enumeration value="CONVERSATION"/>
<xsd:enumeration value="SESSION"/>
<xsd:enumeration value="APPLICATION"/>
<xsd:enumeration value="BUSINESS_PROCESS"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="create" type="xsd:boolean" use="optional"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
1.1 date: 2007/02/09 17:37:18; author: alesj; state: Exp;jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamPostProcessor.java
Index: SeamPostProcessor.java
===================================================================
package org.jboss.seam.ioc.spring;
import org.jboss.seam.ScopeType;
import org.jboss.seam.contexts.Context;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.contexts.Lifecycle;
import org.jboss.seam.init.Initialization;
import org.jboss.seam.log.LogProvider;
import org.jboss.seam.log.Logging;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.util.ClassUtils;
/**
* Post processor that makes all of the seam scopes available in spring and
* takes all of the beans with those scopes and creates Seam Components out of
* them.
* <p/>
* To use simply define this bean in one of your context files.
*
* @author youngm
*/
public class SeamPostProcessor implements BeanFactoryPostProcessor, InitializingBean
{
private static final LogProvider log = Logging.getLogProvider(SeamPostProcessor.class);
/**
* Default seam scope prefix.
*/
public static final String DEFAULT_SCOPE_PREFIX = "seam.";
private String scopePrefix;
/**
* Null is not a valid scopePrefix so make it the default is used if null or empty.
*
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception
{
if (scopePrefix == null || "".equals(scopePrefix))
{
scopePrefix = DEFAULT_SCOPE_PREFIX;
}
}
/**
* Add all of the seam scopes to this beanFactory.
*
* @see org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
*/
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
{
for (ScopeType scope : ScopeType.values())
{
// Don't create a scope for UnSpecified
if (scope != ScopeType.UNSPECIFIED)
{
beanFactory.registerScope(scopePrefix + scope.name(), new SeamScope(scope));
}
}
// Create a mock application context if not available.
boolean unmockApplication = false;
if (!Contexts.isApplicationContextActive())
{
Lifecycle.mockApplication();
unmockApplication = true;
}
try
{
Context applicationContext = Contexts.getApplicationContext();
// Iterate through all the beans in the factory
for (String beanName : beanFactory.getBeanDefinitionNames())
{
BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
Class beanClass;
ScopeType scope;
if (definition.getScope().startsWith(scopePrefix))
{
scope = ScopeType.valueOf(definition.getScope().replaceFirst(scopePrefix, "").toUpperCase());
}
else
{
if (log.isDebugEnabled())
{
log.debug("No scope could be derived for bean with name: " + beanName);
}
continue;
}
if (scope == ScopeType.UNSPECIFIED)
{
if (log.isDebugEnabled())
{
log.debug("Discarding bean with scope UNSPECIFIED. Spring will throw an appropriate error later: " + beanName);
}
continue;
}
// Cannot be a seam component without a class maybe later
if (definition.getBeanClassName() == null)
{
throw new FatalBeanException("Seam scoped bean must explicitly define a class.");
}
else
{
try
{
beanClass = ClassUtils.forName(definition.getBeanClassName());
}
catch (ClassNotFoundException e)
{
throw new FatalBeanException("Error", e);
}
}
// Add the component to seam
applicationContext.set(beanName + Initialization.COMPONENT_SUFFIX, new SpringComponent(beanClass, beanName, scope, beanFactory));
}
}
finally
{
if (unmockApplication)
{
Lifecycle.unmockApplication();
}
}
}
/**
* @param scopePrefix the prefix to use to identify seam scopes for spring
* beans
*/
public void setScopePrefix(String scopePrefix)
{
this.scopePrefix = scopePrefix;
}
}
1.1 date: 2007/02/09 17:37:18; author: alesj; state: Exp;jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamFactoryBean.java
Index: SeamFactoryBean.java
===================================================================
package org.jboss.seam.ioc.spring;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.AbstractFactoryBean;
/**
* Provides an instance of a Seam Component in the current context given the name.
*
* @author youngm
*/
public class SeamFactoryBean extends AbstractFactoryBean implements InitializingBean
{
public SeamFactoryBean()
{
setSingleton(false);
}
private ScopeType scope;
private String name;
private Boolean create;
/**
* Ensure name is not null
*
* @see org.springframework.beans.factory.config.AbstractFactoryBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception
{
if (name == null)
{
throw new IllegalArgumentException("name must not be null");
}
super.afterPropertiesSet();
}
/**
* Return the current instance of a Seam component given the current context.
*
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
*/
@Override
protected Object createInstance() throws Exception
{
if (scope == null && create == null)
{
return Component.getInstance(name);
}
else if (scope == null)
{
return Component.getInstance(name, create);
}
else if (create == null)
{
return Component.getInstance(name, scope);
}
else
{
return Component.getInstance(name, scope, create);
}
}
/**
* Return the type of the component if it is available.
*
* @see org.springframework.beans.factory.config.AbstractFactoryBean#getObjectType()
*/
@Override
public Class getObjectType()
{
Component component = Component.forName(name);
if (component == null)
{
return null;
}
return component.getBeanClass();
}
/**
* The seam component name
*
* @param name the name to set
*/
public void setName(String name)
{
this.name = name;
}
/**
* The seam component scope (optional)
*
* @param scope the scope to set
*/
public void setScope(ScopeType scope)
{
this.scope = scope;
}
/**
* Weather to create an instance of the component if one doesn't already exist in this context.
*
* @param create the create to set
*/
public void setCreate(Boolean create) {
this.create = create;
}
}
More information about the jboss-cvs-commits
mailing list