Added a method to set properties on the spring component.
authorErik Brakkee <erik@brakkee.org>
Mon, 31 Mar 2008 18:26:05 +0000 (18:26 +0000)
committerErik Brakkee <erik@brakkee.org>
Mon, 31 Mar 2008 18:26:05 +0000 (18:26 +0000)
system/spring/pom.xml
system/spring/src/main/java/org/wamblee/system/spring/PropertySetter.java [new file with mode: 0644]
system/spring/src/main/java/org/wamblee/system/spring/ProvidedServiceBean.java [deleted file]
system/spring/src/main/java/org/wamblee/system/spring/RequiredServiceBean.java [new file with mode: 0644]
system/spring/src/main/java/org/wamblee/system/spring/SpringComponent.java [moved from system/spring/src/main/java/org/wamblee/system/spring/SpringSystem.java with 77% similarity]
system/spring/src/main/java/org/wamblee/system/spring/StringResource.java [new file with mode: 0644]
system/spring/src/test/java/org/wamblee/system/spring/SpringComponentTest.java [moved from system/spring/src/test/java/org/wamblee/system/spring/SpringSystemTest.java with 72% similarity]
system/spring/src/test/resources/test.org.wamblee.system.spring.properties [new file with mode: 0644]
system/spring/src/test/resources/test.org.wamblee.system.springWithProperties.xml [new file with mode: 0644]

index 0ee69c1d6b0a7f1dbe5a16dfaad40aad1165e389..5119243e1e8d60cb68cebcedbc35df0cb21dec2f 100644 (file)
     <name>wamblee.org system spring</name>
     <url>http://wamblee.org</url>
     <dependencies>
+        <dependency>
+            <groupId>org.wamblee</groupId>
+            <artifactId>wamblee-support</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <dependency>
             <groupId>org.wamblee</groupId>
             <artifactId>wamblee-system-general</artifactId>
diff --git a/system/spring/src/main/java/org/wamblee/system/spring/PropertySetter.java b/system/spring/src/main/java/org/wamblee/system/spring/PropertySetter.java
new file mode 100644 (file)
index 0000000..e71b655
--- /dev/null
@@ -0,0 +1,31 @@
+package org.wamblee.system.spring;
+
+import java.util.Properties;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
+
+/**
+ * Bean that provides postprocessing of the bean factory based on 
+ * a given set of properties. 
+ * 
+ * @author Erik Brakkee
+ */
+class PropertySetter extends PropertyPlaceholderConfigurer {
+
+       /**
+        * Constructs the property setter. 
+        * @param aProps Properties. 
+        */
+       public PropertySetter(Properties aProps) { 
+                StringBuffer buf = new StringBuffer();  
+                for (Object key: aProps.keySet()) {  
+                        buf.append(key);
+                        buf.append("=");
+                        buf.append(aProps.get(key));
+                        buf.append("\n");
+                } 
+                setLocation(new StringResource(buf.toString()));
+       }
+}
diff --git a/system/spring/src/main/java/org/wamblee/system/spring/ProvidedServiceBean.java b/system/spring/src/main/java/org/wamblee/system/spring/ProvidedServiceBean.java
deleted file mode 100644 (file)
index 31dd576..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-package org.wamblee.system.spring;
-
-import org.springframework.beans.factory.FactoryBean;
-
-public class ProvidedServiceBean implements FactoryBean {
-       
-       private String _id;
-       
-       public ProvidedServiceBean(String aId) { 
-               _id = aId; 
-       }
-
-       @Override
-       public Object getObject() throws Exception {
-               return SpringSystem.REGISTRY.get().find(_id).reference(Object.class);
-       }
-
-       @Override
-       public Class getObjectType() {
-               return null;
-       }
-
-       @Override
-       public boolean isSingleton() {
-               return true; 
-       }
-
-}
diff --git a/system/spring/src/main/java/org/wamblee/system/spring/RequiredServiceBean.java b/system/spring/src/main/java/org/wamblee/system/spring/RequiredServiceBean.java
new file mode 100644 (file)
index 0000000..eaf5533
--- /dev/null
@@ -0,0 +1,38 @@
+package org.wamblee.system.spring;
+
+import org.springframework.beans.factory.FactoryBean;
+
+/**
+ * Bean which adds a service required by the spring component to 
+ * the application context so that other spring beans can use it.  
+ *  
+ * @author Erik Brakkee
+ */
+class RequiredServiceBean implements FactoryBean {
+       
+       private String _id;
+       
+       /**
+        * Constructs the bean. 
+        * @param aId Id of the bean in the service registry.  
+        */
+       public RequiredServiceBean(String aId) { 
+               _id = aId; 
+       }
+
+       @Override
+       public Object getObject() throws Exception {
+               return SpringComponent.REGISTRY.get().find(_id).reference(Object.class);
+       }
+
+       @Override
+       public Class getObjectType() {
+               return null;
+       }
+
+       @Override
+       public boolean isSingleton() {
+               return true; 
+       }
+
+}
similarity index 77%
rename from system/spring/src/main/java/org/wamblee/system/spring/SpringSystem.java
rename to system/spring/src/main/java/org/wamblee/system/spring/SpringComponent.java
index 05731af829aa0b7ae24aafa2d79243af3fa247f2..633050cbfecacee89b2cd5a723762ec8d520b970 100644 (file)
@@ -1,6 +1,8 @@
 package org.wamblee.system.spring;
 
 import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
 
 import org.springframework.beans.MutablePropertyValues;
 import org.springframework.beans.factory.config.BeanDefinition;
@@ -22,16 +24,19 @@ import org.wamblee.system.SystemAssemblyException;
 
 /**
  * Represents a system configured based on spring.
+ * The spring config files that are configured should not contain any PropertyPlaceholderConfigurer 
+ * objects. 
  *
  * @author Erik Brakkee
  */
-public class SpringSystem extends AbstractComponent {
+public class SpringComponent extends AbstractComponent {
 
        /**
         * Singleton access to the service registry. Required while starting up.
         */
        static ThreadLocal<ServiceRegistry> REGISTRY = new ThreadLocal<ServiceRegistry>();
 
+       private Properties _properties; 
        private String[] _configFiles;
        private Map<String, ProvidedInterfaceDescriptor> _provided;
        private Map<RequiredInterfaceDescriptor, String> _required;
@@ -46,11 +51,11 @@ public class SpringSystem extends AbstractComponent {
        private AbstractApplicationContext _context;
 
        /**
-        * Construcst a spring system.
+        * Constructs a spring system.
         * 
         * @param aName
         *            Name of the system.
-        * @param aConfigFiles
+        * @param aConfigFil
         *            Spring config files to read.
         * @param aProvided
         *            Map of bean name to service descriptor describing the bean
@@ -61,27 +66,49 @@ public class SpringSystem extends AbstractComponent {
         *            names that the spring config files use for each required
         *            service.
         */
-       public SpringSystem(String aName, ServiceRegistry aRegistry, String[] aConfigFiles,
+       public SpringComponent(String aName, ServiceRegistry aRegistry, String[] aConfigFiles,
                        Map<String, ProvidedInterfaceDescriptor> aProvided,
                        Map<RequiredInterfaceDescriptor, String> aRequired) {
                super(aName, aRegistry, aProvided.values().toArray(new InterfaceDescriptor[0]),
                                aRequired.keySet().toArray(new InterfaceDescriptor[0]));
+               _properties = new Properties(); 
                _configFiles = aConfigFiles;
                _provided = aProvided;
                _required = aRequired;
        }
+       
+       /**
+        * Must be called to make a property available in the application context. 
+        * @param aKey Property key. 
+        * @param aValue Property value. 
+        */
+       public void setProperty(String aKey, String aValue) { 
+               _properties.put(aKey, aValue);
+       }
+       
+       public void addProperties(Properties aProperties) { 
+               for (Object key: aProperties.keySet()) { 
+                       setProperty((String)key, aProperties.getProperty((String)key));
+               }
+       }
 
        @Override
        protected void doStart(String aContext, 
                        Service[] aRequiredServices) {
-               ServiceRegistry old = REGISTRY.get(); 
+               ServiceRegistry oldRegistry = REGISTRY.get();
                try {   
-                       REGISTRY.set(getRegistry()); 
+                       REGISTRY.set(getRegistry());
                        try {
+                               _parentContext = new GenericApplicationContext();
 
                                registerRequiredServices(aRequiredServices);
+                               
+                               _parentContext.refresh();
 
                                parseConfigFiles();
+                               
+                               _context.addBeanFactoryPostProcessor(new PropertySetter(_properties));
+                               _context.refresh(); 
 
                                exposeProvidedServices(aContext);
                        } catch (Exception e) {
@@ -89,7 +116,7 @@ public class SpringSystem extends AbstractComponent {
                                                "Failed to assemble spring system", e);
                        }
                } finally {
-                       REGISTRY.set(old);
+                       REGISTRY.set(oldRegistry);
                }
        }
 
@@ -116,9 +143,6 @@ public class SpringSystem extends AbstractComponent {
        private void registerRequiredServices(Service[] aRequiredServices) {
                // Register required services in a parent context
 
-               // Register the Hibernate mapping files as a bean.
-               _parentContext = new GenericApplicationContext();
-               
                for (Service svc: aRequiredServices) { 
                        String id = svc.getId();
                        ProvidedInterfaceDescriptor descriptor = svc.getDescriptor();
@@ -128,12 +152,11 @@ public class SpringSystem extends AbstractComponent {
                                String beanName = _required.get(required);
                                ConstructorArgumentValues cargs = new ConstructorArgumentValues();
                                cargs.addGenericArgumentValue(id); 
-                               BeanDefinition definition = new RootBeanDefinition(ProvidedServiceBean.class, cargs,
+                               BeanDefinition definition = new RootBeanDefinition(RequiredServiceBean.class, cargs,
                                                new MutablePropertyValues());
                                _parentContext.registerBeanDefinition(beanName, definition);
                        }
                }
-               _parentContext.refresh();
        }
 
        @Override
diff --git a/system/spring/src/main/java/org/wamblee/system/spring/StringResource.java b/system/spring/src/main/java/org/wamblee/system/spring/StringResource.java
new file mode 100644 (file)
index 0000000..1869e57
--- /dev/null
@@ -0,0 +1,59 @@
+package org.wamblee.system.spring;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.springframework.core.io.Resource;
+
+class StringResource implements Resource {
+       
+       private String _value; 
+       
+       public StringResource(String aValue) { 
+               _value = aValue; 
+       }
+
+       @Override
+       public Resource createRelative(String aRelativePath) throws IOException {
+               throw new IOException("No relative resource possible");
+       }
+
+       @Override
+       public boolean exists() {
+               return false;
+       }
+
+       @Override
+       public String getDescription() {
+               return "Properties of a spring component"; 
+       }
+
+       @Override
+       public File getFile() throws IOException {
+               throw new IOException();
+       }
+
+       @Override
+       public String getFilename() {
+               return "springcomponent.properties";
+       }
+
+       @Override
+       public URL getURL() throws IOException {
+               throw new IOException();
+       }
+
+       @Override
+       public boolean isOpen() {
+               return false;
+       }
+
+       @Override
+       public InputStream getInputStream() throws IOException {
+               return new ByteArrayInputStream(_value.getBytes());
+       }
+
+}
similarity index 72%
rename from system/spring/src/test/java/org/wamblee/system/spring/SpringSystemTest.java
rename to system/spring/src/test/java/org/wamblee/system/spring/SpringComponentTest.java
index 1543b7ab8cd39067b6d9a9aa64450c9a733a8669..dc7a5845c659f68c47bbcd7db8f855bd3fa1c5b2 100644 (file)
@@ -1,10 +1,13 @@
 package org.wamblee.system.spring;
 
+import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Properties;
 
 import junit.framework.TestCase;
 
+import org.wamblee.io.ClassPathResource;
 import org.wamblee.system.AbstractInterfaceDescriptor;
 import org.wamblee.system.DefaultProvidedInterfaceDescriptor;
 import org.wamblee.system.DefaultRequiredInterfaceDescriptor;
@@ -16,10 +19,12 @@ import org.wamblee.system.InterfaceDescriptor;
 import org.wamblee.system.ServiceRegistry;
 import org.wamblee.system.SystemAssemblyException;
 
-public class SpringSystemTest extends TestCase {
+public class SpringComponentTest extends TestCase {
 
        private static final String HELLO_SERVICE_SPRING_XML = "test.org.wamblee.system.spring.xml";
        private static final String HELLO_SERVICE_SPRING_WITH_REQS_XML = "test.org.wamblee.system.springWithRequirements.xml";
+       private static final String HELLO_SERVICE_SPRING_WITH_PROPERTIES_XML = "test.org.wamblee.system.springWithProperties.xml";
+    private static final String PROPERTY_FILE = "test.org.wamblee.system.spring.properties";
 
        private ServiceRegistry _registry;
 
@@ -30,7 +35,7 @@ public class SpringSystemTest extends TestCase {
        }
 
        public void testBlackboxSystem() {
-               SpringSystem system = new SpringSystem("system", _registry,
+               SpringComponent system = new SpringComponent("system", _registry,
                                new String[] { HELLO_SERVICE_SPRING_XML },
                                new HashMap<String, ProvidedInterfaceDescriptor>(),
                                new HashMap<RequiredInterfaceDescriptor, String>());
@@ -46,7 +51,7 @@ public class SpringSystemTest extends TestCase {
                provided.put("helloService", new DefaultProvidedInterfaceDescriptor(
                                "hello", HelloService.class));
 
-               SpringSystem system = new SpringSystem("system", _registry,
+               SpringComponent system = new SpringComponent("system", _registry,
                                new String[] { HELLO_SERVICE_SPRING_XML }, provided,
                                new HashMap<RequiredInterfaceDescriptor, String>());
                system.start("Hello", new Service[0]);
@@ -57,10 +62,27 @@ public class SpringSystemTest extends TestCase {
                                .say());
                system.stop();
        }
+       
+       public void testWithProperties() throws IOException {
+               Map<String, ProvidedInterfaceDescriptor> provided = new HashMap<String, ProvidedInterfaceDescriptor>();
+               provided.put("helloService", new DefaultProvidedInterfaceDescriptor(
+                               "hello", HelloService.class));
+               SpringComponent system = new SpringComponent("system", _registry,
+                               new String[] { HELLO_SERVICE_SPRING_WITH_PROPERTIES_XML },
+                               provided,
+                               new HashMap<RequiredInterfaceDescriptor, String>());
+               Properties props = new Properties();
+               props.load(new ClassPathResource(PROPERTY_FILE).getInputStream());
+               system.addProperties(props);
+               
+               system.start("Hello", new Service[0]);
+               Service[] services = system.getRunningServices();
+               assertEquals("Property Value", services[0].reference(HelloService.class).say());
+       }
 
-       public void testWithMissingRequiremnt() {
+       public void testWithMissingRequirement() {
                try {
-                       SpringSystem system = new SpringSystem("system", _registry,
+                       SpringComponent system = new SpringComponent("system", _registry,
                                        new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML },
                                        new HashMap<String, ProvidedInterfaceDescriptor>(),
                                        new HashMap<RequiredInterfaceDescriptor, String>());
@@ -76,7 +98,7 @@ public class SpringSystemTest extends TestCase {
                Map<RequiredInterfaceDescriptor, String> required = new HashMap<RequiredInterfaceDescriptor, String>();
                required.put(new DefaultRequiredInterfaceDescriptor("hello", HelloService.class),
                                "helloService");
-               SpringSystem system = new SpringSystem("system", _registry,
+               SpringComponent system = new SpringComponent("system", _registry,
                                new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML },
                                new HashMap<String, ProvidedInterfaceDescriptor>(), required);
                
@@ -94,7 +116,7 @@ public class SpringSystemTest extends TestCase {
                provided.put("blaService", new DefaultProvidedInterfaceDescriptor("bla",
                                BlaService.class));
 
-               SpringSystem system = new SpringSystem("system", _registry,
+               SpringComponent system = new SpringComponent("system", _registry,
                                new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML },
                                provided, required);
                
diff --git a/system/spring/src/test/resources/test.org.wamblee.system.spring.properties b/system/spring/src/test/resources/test.org.wamblee.system.spring.properties
new file mode 100644 (file)
index 0000000..747a033
--- /dev/null
@@ -0,0 +1 @@
+myproperty=Property Value
diff --git a/system/spring/src/test/resources/test.org.wamblee.system.springWithProperties.xml b/system/spring/src/test/resources/test.org.wamblee.system.springWithProperties.xml
new file mode 100644 (file)
index 0000000..1ece7d1
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans
+    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
+
+    <bean id="helloService" class="org.wamblee.system.spring.HelloService">
+        <constructor-arg>
+            <value>${myproperty}</value>
+        </constructor-arg>
+    </bean>
+
+</beans>