X-Git-Url: http://wamblee.org/gitweb/?a=blobdiff_plain;f=system%2Fspring%2Fsrc%2Fmain%2Fjava%2Forg%2Fwamblee%2Fsystem%2Fspring%2FSpringComponent.java;h=0e4c62eb1fe26ae2ccb858342053d818e9af0749;hb=0d8d8f24656e585ee75558cfd6a4c661f8f14985;hp=09ef341175657aae0e7da781a6299c2b5cf0a95e;hpb=98dc838908507748b413ad0d93e9050cbb6ecdeb;p=utils diff --git a/system/spring/src/main/java/org/wamblee/system/spring/SpringComponent.java b/system/spring/src/main/java/org/wamblee/system/spring/SpringComponent.java index 09ef3411..0e4c62eb 100644 --- a/system/spring/src/main/java/org/wamblee/system/spring/SpringComponent.java +++ b/system/spring/src/main/java/org/wamblee/system/spring/SpringComponent.java @@ -15,6 +15,7 @@ */ package org.wamblee.system.spring; +import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -26,8 +27,10 @@ import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.wamblee.system.core.AbstractComponent; +import org.wamblee.system.core.DefaultScope; import org.wamblee.system.core.ProvidedInterface; import org.wamblee.system.core.RequiredInterface; +import org.wamblee.system.core.Scope; import org.wamblee.system.core.SystemAssemblyException; /** @@ -36,23 +39,18 @@ import org.wamblee.system.core.SystemAssemblyException; * * @author Erik Brakkee */ -public class SpringComponent extends AbstractComponent { +public class SpringComponent extends AbstractComponent { - static final ThreadLocal THIS = new ThreadLocal(); + private static final String CONTEXT_KEY = "context"; - private Properties _properties; - private String[] _configFiles; - private Map _provided; - private Map _required; - /** - * Parent application context containing required services. - */ - private GenericApplicationContext _parentContext; + static final ThreadLocal THIS = new ThreadLocal(); + static final ThreadLocal SCOPE = new ThreadLocal(); - /** - * Application context containing parsed objects. - */ - private AbstractApplicationContext _context; + private Properties properties; + private String[] configFiles; + private Map provided; + private Map required; + private Map propertyObjects; /** * Constructs a spring system. @@ -75,10 +73,12 @@ public class SpringComponent extends AbstractComponent { Map aRequired) { super(aName, aProvided.values().toArray(new ProvidedInterface[0]), aRequired.keySet().toArray(new RequiredInterface[0])); - _properties = new Properties(); - _configFiles = aConfigFiles; - _provided = aProvided; - _required = aRequired; + properties = new Properties(); + configFiles = aConfigFiles; + provided = aProvided; + required = aRequired; + propertyObjects = new HashMap(); + } /** @@ -90,7 +90,7 @@ public class SpringComponent extends AbstractComponent { * Property value. */ public void setProperty(String aKey, String aValue) { - _properties.put(aKey, aValue); + properties.put(aKey, aValue); } public void addProperties(Properties aProperties) { @@ -98,69 +98,105 @@ public class SpringComponent extends AbstractComponent { setProperty((String) key, aProperties.getProperty((String) key)); } } + + public void addProperties(String aBeanname, Properties aProperties) { + propertyObjects.put(aBeanname, aProperties); + } + + public Properties getProperties(String aBeanname) { + return propertyObjects.get(aBeanname); + } @Override - protected void doStart() { + protected Scope doStart(Scope aExternalScope) { SpringComponent old = THIS.get(); + Scope oldScope = SCOPE.get(); THIS.set(this); + Scope scope = new DefaultScope(getProvidedInterfaces().toArray(new ProvidedInterface[0]), aExternalScope); + SCOPE.set(scope); try { - _parentContext = new GenericApplicationContext(); - - registerRequiredServices(); + GenericApplicationContext parentContext = new GenericApplicationContext(); - _parentContext.refresh(); + registerRequiredServices(parentContext); + registerPropertyObjects(parentContext); - parseConfigFiles(); + parentContext.refresh(); + + System.out.println("Parent context " + parentContext); + + AbstractApplicationContext context = parseConfigFiles(parentContext); - _context - .addBeanFactoryPostProcessor(new PropertySetter(_properties)); - _context.refresh(); + context + .addBeanFactoryPostProcessor(new PropertySetter(properties)); + context.refresh(); - exposeProvidedServices(); + exposeProvidedServices(context, aExternalScope); + + scope.put(CONTEXT_KEY, context); + return scope; } catch (Exception e) { throw new SystemAssemblyException( - "Failed to assemble spring system", e); + "Failed to assemble spring system " + getName(), e); } finally { THIS.set(old); + SCOPE.set(oldScope); } } - private void exposeProvidedServices() { + private void exposeProvidedServices(AbstractApplicationContext aContext, Scope aScope) { // Call addService for each provided service. - for (String name : _provided.keySet()) { - Object svc = _context.getBean(name); + for (String name : provided.keySet()) { + Object svc = aContext.getBean(name); if (svc == null) { throw new IllegalArgumentException(getQualifiedName() + ": service '" + name + "' is null"); } - addService(_provided.get(name), svc); + addInterface(provided.get(name), svc, aScope); + System.out.println("addService " + provided.get(name) + " " + svc); } } - private void parseConfigFiles() { + private AbstractApplicationContext parseConfigFiles(GenericApplicationContext aParentContext) { // Parse spring config files - _context = new ClassPathXmlApplicationContext((String[]) _configFiles, - _parentContext); + return new ClassPathXmlApplicationContext((String[]) configFiles, + false, aParentContext); } - private void registerRequiredServices() { + private void registerRequiredServices(GenericApplicationContext aParentContext) { // Register required services in a parent context - for (RequiredInterface required: getRequiredInterfaces()) { - String beanName = _required.get(required); - ConstructorArgumentValues cargs = new ConstructorArgumentValues(); - cargs.addGenericArgumentValue(required.getName()); - BeanDefinition definition = new RootBeanDefinition( - RequiredServiceBean.class, cargs, - new MutablePropertyValues()); - _parentContext.registerBeanDefinition(beanName, definition); + for (RequiredInterface requiredIntf: getRequiredInterfaces()) { + String beanName = required.get(requiredIntf); + if ( beanName != null && beanName.length() > 0) { + ConstructorArgumentValues cargs = new ConstructorArgumentValues(); + cargs.addGenericArgumentValue(requiredIntf.getName()); + BeanDefinition definition = new RootBeanDefinition( + RequiredServiceBean.class, cargs, + new MutablePropertyValues()); + aParentContext.registerBeanDefinition(beanName, definition); + } else { + // The required interface is not required by the spring config but by the sub-class directly. + } } } + + private void registerPropertyObjects(GenericApplicationContext aParentContext) { + for (String beanName: propertyObjects.keySet()) { + ConstructorArgumentValues cargs = new ConstructorArgumentValues(); + cargs.addGenericArgumentValue(PropertySetter.createPropertyFile(propertyObjects.get(beanName))); + BeanDefinition definition = new RootBeanDefinition( + ConfiguredProperties.class, cargs, + new MutablePropertyValues()); + aParentContext.registerBeanDefinition(beanName, definition); + } + } + @Override - protected void doStop() { - _context.close(); + protected void doStop(Scope aRuntime) { + AbstractApplicationContext context = (AbstractApplicationContext)aRuntime.get(CONTEXT_KEY); + context.close(); } }