ServiceREgistry eliminated as well as Service and DefaultService.
There is now a many-to-one relation from required to provided service
which leads to a more natural design.
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
-import java.util.Map;
+import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.wamblee.system.Component.Status;
/**
* Abstract subsystem class making it easy to implement new subsystems.
private static final Log LOG = LogFactory.getLog(AbstractComponent.class);
private Status _status;
- private String _name;
- private ServiceRegistry _registry;
+ private String _name;
private List<ProvidedInterface> _provided;
private List<RequiredInterface> _required;
- private Map<ProvidedInterface, Service> _running;
+ private Set<ProvidedInterface> _running;
/**
* Constructs the subsystem.
- *
- * @param aRegistry
- * Registry of services.
+ *
* @param aName
* Name of the system.
* @param aProvided
* @param aRequired
* Required services.
*/
- protected AbstractComponent(String aName, ServiceRegistry aRegistry, ProvidedInterface[] aProvided,
+ protected AbstractComponent(String aName, ProvidedInterface[] aProvided,
RequiredInterface[] aRequired) {
_status = Status.NOT_STARTED;
_name = aName;
- _registry = aRegistry;
_provided = new ArrayList<ProvidedInterface>();
_provided.addAll(Arrays.asList(aProvided));
_required = new ArrayList<RequiredInterface>();
_required.addAll(Arrays.asList(aRequired));
- _running = new HashMap<ProvidedInterface, Service>();
+ _running = new HashSet<ProvidedInterface>();
}
@Override
public final String getName() {
return _name;
}
-
- public ServiceRegistry getRegistry() {
- return _registry;
- }
@Override
public final ProvidedInterface[] getProvidedServices() {
}
@Override
- public final Service[] start(String aContext,
- Service[] aRequiredServices) {
- LOG.info("Initializing '" + aContext + "." + _name + "' with "
- + Arrays.asList(aRequiredServices));
- doStart(aContext + "." + getName(), aRequiredServices);
+ public final void start(String aContext) {
+ LOG.info("Initializing '" + aContext + "." + _name + "'");
+ doStart(aContext + "." + getName());
_status = Status.RUNNING;
- return _running.values().toArray(new Service[0]);
}
/**
* Must be implemented for initializing the subsystem. The implementation
* must call {@link #addService(Service)} for each service that is started.
- *
- * @param aRequiredServices
- * Services that are already running from other subsystems that
- * may be used.
*/
- protected abstract void doStart(String aContext,
- Service[] aRequiredServices);
+ protected abstract void doStart(String aContext);
/**
* Implementations must call this method to indicate that a new service has
protected final void addService(String aContext,
ProvidedInterface aDescriptor, Object aService) {
LOG.info(aContext + ": service '" + aService + "' started.");
- Service svc = getRegistry().register(aDescriptor, aService);
- _running.put(svc.getDescriptor(), svc);
+ _running.add(aDescriptor);
+ aDescriptor.publish(aService);
}
@Override
- public Service[] getRunningServices() {
- return _running.values().toArray(new Service[0]);
+ public ProvidedInterface[] getRunningServices() {
+ return _running.toArray(new ProvidedInterface[0]);
}
@Override
public void stop() {
doStop();
- for (Service svc: _running.values()) {
- getRegistry().remove(svc);
- }
_status = Status.STOPPED;
}
/**
* Initialises the subsytem by starting all the services that
* it described as provided.
- * @param aContext Unique name for the subsystem.
- * @param aRequiredServices Running services from other
- * subsystems that are required by this subsystem.
- * @return Services that are running in the subsystem.
+ * @param aContext Unique name for the subsystem.
*/
- Service[] start(String aContext, Service[] aRequiredServices);
+ void start(String aContext);
/**
* Stops a subsystem.
* {@link #initialize(String, Service[])} has been called.
* @return
*/
- Service[] getRunningServices();
+ ProvidedInterface[] getRunningServices();
}
* @param aProvided Provided services of the system.
* @param aRequired Required services by the system.
*/
- public Container(String aName, ServiceRegistry aRegistry, Component[] aSystems,
+ public Container(String aName, Component[] aSystems,
ProvidedInterface[] aProvided, RequiredInterface[] aRequired) {
- super(aName, aRegistry, aProvided, aRequired);
+ super(aName, aProvided, aRequired);
_systems = aSystems;
- validate();
+ validate(aRequired);
}
/**
* no services in the provided list that cannot be provided.
* Also logs a warning in case of superfluous requirements.
*/
- private void validate() {
+ private void validate(RequiredInterface[] aRequired) {
List<ProvidedInterface> provided = new ArrayList<ProvidedInterface>();
for (Component system : _systems) {
provided.addAll(Arrays.asList(system.getProvidedServices()));
List<RequiredInterface> reallyRequired = new ArrayList<RequiredInterface>(
required);
+ // Compute all required interfaces that are not provided
for (ProvidedInterface service : provided) {
- reallyRequired.remove(service);
- }
- for (RequiredInterface service: getRequiredServices()) {
- reallyRequired.remove(service);
+ List<RequiredInterface> fulfilled =
+ Arrays.asList(SystemAssembler.filterRequiredServices(service,
+ reallyRequired));
+ reallyRequired.removeAll(fulfilled);
}
+ // Now the remaining interfaces should be covered by the required
+ // list.
+ reallyRequired.removeAll(Arrays.asList(aRequired));
+
String missingRequired = "";
for (RequiredInterface service: reallyRequired) {
missingRequired += service + "\n";
}
@Override
- protected void doStart(String aContext, Service[] aRequiredServices) {
- List<ProvidedInterface> descriptors = new ArrayList<ProvidedInterface>();
- for (Service service : aRequiredServices) {
- descriptors.add(service.getDescriptor());
+ protected void doStart(String aContext) {
+ List<ProvidedInterface> provided = new ArrayList<ProvidedInterface>();
+
+ // all interfaces from the required list of this container are
+ // provided to the components inside it.
+ RequiredInterface[] required = getRequiredServices();
+ for (RequiredInterface intf: required) {
+ ProvidedInterface provider = intf.getProvider();
+ if ( provider == null ) {
+ throw new SystemAssemblyException(aContext + ": required interface '" + intf +"' is not provided");
+ }
+ provided.add(intf.getProvider());
}
- SystemAssembler assembler = new SystemAssembler(aContext + "." + getName(), _systems,
- descriptors.toArray(new ProvidedInterface[0]));
- assembler.start(getRegistry(), aRequiredServices);
+
+ SystemAssembler assembler = new SystemAssembler( _systems,
+ provided.toArray(new ProvidedInterface[0]));
+ assembler.start();
}
@Override
public class DefaultProvidedInterfaceDescriptor implements ProvidedInterface {
private String _name;
- private Class[] _interfaces;
+ private Class[] _interfaces;
+ private Object _implementation;
/**
* Constructs the descriptor.
return _interfaces;
}
+ @Override
+ public void publish(Object aImplementation) {
+ _implementation = aImplementation;
+ }
+
+ @Override
+ public Object getImplementation() {
+ return _implementation;
+ }
+
@Override
public boolean equals(Object obj) {
if ( !(obj instanceof DefaultProvidedInterfaceDescriptor)) {
package org.wamblee.system;
-public class DefaultRequiredInterfaceDescriptor extends DefaultProvidedInterfaceDescriptor
- implements RequiredInterface {
+import java.util.Arrays;
+public class DefaultRequiredInterfaceDescriptor implements RequiredInterface {
+
+ private String _name;
+ private Class[] _required;
+ private ProvidedInterface _provider;
+
public DefaultRequiredInterfaceDescriptor(String aName, Class aInterface) {
- super(aName, aInterface);
+ this(aName, new Class[] { aInterface });
}
public DefaultRequiredInterfaceDescriptor(String aName, Class[] aInterfaces) {
- super(aName, aInterfaces);
+ _name = aName;
+ _required = aInterfaces;
}
+ @Override
+ public String getName() {
+ return _name;
+ }
+
@Override
public boolean implementedBy(ProvidedInterface aDescriptor) {
Class[] provided = aDescriptor.getInterfaceTypes();
- for (Class required : getInterfaceTypes()) {
+ for (Class required : _required) {
if ( !serviceProvided(required, provided)) {
return false;
}
}
return false;
}
+
+ @Override
+ public ProvidedInterface getProvider() {
+ return _provider;
+ }
+
+ @Override
+ public void setProvider(ProvidedInterface aProvider) {
+ _provider = aProvider;
+ }
+
+ @Override
+ public <T> T getImplementation(Class<T> aClass) {
+ return (T)_provider.getImplementation();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if ( !(obj instanceof DefaultRequiredInterfaceDescriptor)) {
+ return false;
+ }
+ DefaultRequiredInterfaceDescriptor descr = (DefaultRequiredInterfaceDescriptor)obj;
+ if ( _required.length != descr._required.length ) {
+ return false;
+ }
+ String[] interfaces1 = new String[_required.length];
+ String[] interfaces2 = new String[_required.length];
+ for (int i = 0; i < _required.length; i++) {
+ interfaces1[i] = _required[i].getName();
+ interfaces2[i] = descr._required[i].getName();
+ }
+ Arrays.sort(interfaces1);
+ Arrays.sort(interfaces2);
+ return Arrays.equals(interfaces1, interfaces2);
+ }
+ @Override
+ public int hashCode() {
+ return _required.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buf = new StringBuffer();
+ for (Class intf: _required) {
+ buf.append("." + intf.getName());
+ }
+ return buf.toString();
+ }
}
+++ /dev/null
-package org.wamblee.system;
-
-/**
- * Default service implementation.
- *
- * @author Erik Brakkee
- */
-public class DefaultService implements Service {
-
- private String _id;
- private ProvidedInterface _descriptor;
- private Object _service;
-
- /**
- * Constructs the service.
- *
- * @param aDescriptor
- * Descriptor to use.
- * @param aService
- * Service.
- */
- public DefaultService(String aId, ProvidedInterface aDescriptor,
- Object aService) {
- _id = aId;
- _descriptor = aDescriptor;
- _service = aService;
- }
-
- @Override
- public String getId() {
- return _id;
- }
-
- @Override
- public ProvidedInterface getDescriptor() {
- return _descriptor;
- }
-
- @Override
- public <T> T reference(Class<T> aClass) {
- return (T) _service;
- }
-
- @Override
- public String toString() {
- return "(" + _descriptor + ", " + _service + ")";
- }
-}
+++ /dev/null
-package org.wamblee.system;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-public class DefaultServiceRegistry implements ServiceRegistry {
-
- private int _count;
- private Map<String, Service> _services;
-
- public DefaultServiceRegistry() {
- _count = 0;
- _services = new HashMap<String, Service>();
- }
-
- @Override
- public synchronized Service register(ProvidedInterface aDescriptor,
- Object aService) {
- _count++;
- String id = "" + _count;
- Service svc = new DefaultService(id, aDescriptor, aService);
- _services.put(id, svc);
- return svc;
- }
-
- @Override
- public void remove(Service aService) {
- Service svc = _services.remove(aService.getId());
- if ( svc == null ) {
- throw new IllegalArgumentException("Service '" + aService.getId() + "' does not exist");
- }
- }
-
- @Override
- public synchronized Service find(String aId) {
- return _services.get(aId);
- }
-
- @Override
- public Service[] listAllServices() {
- return new ArrayList<Service>(_services.values())
- .toArray(new Service[0]);
- }
-}
* @return Service type.
*/
Class[] getInterfaceTypes();
+
+ /**
+ * Publish an implementation of the interface.
+ * @param aImplementation
+ */
+ void publish(Object aImplementation);
+
+ /**
+ * Gets the implementation.
+ * @return Implementation or null if not started.
+ */
+ Object getImplementation();
}
* @return
*/
boolean implementedBy(ProvidedInterface aInterface);
+
+ /**
+ * Sets the provider of this interface.
+ * @param aProvider Provider.
+ */
+ void setProvider(ProvidedInterface aProvider);
+
+ /**
+ * Getst the provider interface.
+ * @return Provider or null if not set.
+ */
+ ProvidedInterface getProvider();
+
+ /**
+ * Gets the implementation of the required interface.
+ * @param <T>
+ * @param aClass Interface type.
+ * @return Interface implementation or null if not known yet.
+ */
+ <T> T getImplementation(Class<T> aClass);
}
+++ /dev/null
-package org.wamblee.system;
-
-/**
- * Represents a running service.
- *
- * @author Erik Brakkee
- */
-public interface Service {
-
- /**
- * Gets the ide of the service in the registry.
- * @return Service id.
- */
- String getId();
-
- /**
- * Gets the descriptor of the service.
- * @return Descriptor.
- */
- ProvidedInterface getDescriptor();
-
- /**
- * Returns a reference to the running service.
- * @return Service.
- */
- <T> T reference(Class<T> aClass);
-}
+++ /dev/null
-package org.wamblee.system;
-
-public interface ServiceRegistry {
-
- Service register(ProvidedInterface aDescriptor, Object aService);
-
- void remove(Service aService);
-
- Service find(String aId);
-
- Service[] listAllServices();
-}
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
private static final String ROOT_CONTEXT_NAME = "root";
private String _context;
private Component[] _systems;
+ private ProvidedInterface[] _required;
public static RequiredInterface[] filterRequiredServices(
ProvidedInterface aProvided,
ProvidedInterface[] aAvailableServices) {
_context = aContext;
_systems = aSystems;
- validate(aAvailableServices);
+ _required = aAvailableServices;
+ validate();
}
/**
* Determines if the systems are ordered appropriately so that all
* dependencies are met.
*/
- private void validate(ProvidedInterface[] aDescriptors)
+ private void validate()
throws SystemAssemblyException {
List<ProvidedInterface> allProvided = new ArrayList<ProvidedInterface>();
- for (ProvidedInterface descriptor : aDescriptors) {
+ for (ProvidedInterface descriptor : _required) {
allProvided.add(descriptor);
}
for (Component system : _systems) {
/**
* Starts the subsystems.
*
- * @param aRegistry
- * Service registry to which created services must be registered.
* @param aRequiredServices
* Services that are available from other systems that have been
* started before.
*/
- public void start(ServiceRegistry aRegistry, Service[] aRequiredServices) {
+ public void start() {
LOG.info("Starting '" + _context + "'");
- Map<ProvidedInterface, Service> allProvided = new HashMap<ProvidedInterface, Service>();
-
- for (Service service : aRequiredServices) {
- allProvided.put(service.getDescriptor(), service);
- }
+ Set<ProvidedInterface> allProvided = new HashSet<ProvidedInterface>();
+ allProvided.addAll(Arrays.asList(_required));
+
for (Component system : _systems) {
// Compose a list of the required services required for the subsystem.
RequiredInterface[] descriptors = system
.getRequiredServices();
- List<Service> services = new ArrayList<Service>();
- for (RequiredInterface descriptor : descriptors) {
+ List<ProvidedInterface> services = new ArrayList<ProvidedInterface>();
+ for (RequiredInterface required : descriptors) {
ProvidedInterface[] provided = filterProvidedServices(
- descriptor, allProvided.keySet());
- services.add(allProvided.get(provided[0]));
+ required, allProvided);
+ assert provided.length == 1;
+ services.add(provided[0]);
+ required.setProvider(provided[0]);
}
// Start the service.
- Service[] provided = system.start(_context, services
- .toArray(new Service[0]));
+ system.start(_context);
- // Add started services to the map of started services.
- for (Service service : provided) {
- allProvided.put(service.getDescriptor(), service);
+ // Add started services to the set of started services.
+ for (ProvidedInterface service : system.getProvidedServices()) {
+ allProvided.add(service);
}
}
import javax.sql.DataSource;
public class Application extends AbstractComponent {
- private static final RequiredInterface[] REQUIRED =
+ private static RequiredInterface[] required() {
+ return
new RequiredInterface[] {
new DefaultRequiredInterfaceDescriptor("datasource", DataSource.class),
new DefaultRequiredInterfaceDescriptor("integer", Integer.class)
};
+ }
- public Application(ServiceRegistry aRegistry) {
- super("application", aRegistry, new ProvidedInterface[0], REQUIRED);
+ public Application() {
+ super("application", new ProvidedInterface[0], required());
}
@Override
- protected void doStart(String aContext, Service[] aRequiredServices) {
+ protected void doStart(String aContext) {
// Empty, no services provided externally.
}
public class Environment extends AbstractComponent {
- private static final ProvidedInterface[] PROVIDED =
- new ProvidedInterface[] {
+ private static final ProvidedInterface[] provided() {
+ return new ProvidedInterface[] {
new DefaultProvidedInterfaceDescriptor("datasource", DataSource.class),
new DefaultProvidedInterfaceDescriptor("integer", Integer.class)
};
+ }
- public Environment(ServiceRegistry aRegistry) {
- super("environment", aRegistry, PROVIDED, new RequiredInterface[0]);
+ public Environment() {
+ super("environment", provided(), new RequiredInterface[0]);
}
@Override
- protected void doStart(String aContext, Service[] aRequiredServices) {
- addService(aContext, PROVIDED[0], new Integer(1));
- addService(aContext, PROVIDED[1], new Integer(2));
+ protected void doStart(String aContext) {
+ addService(aContext, getProvidedServices()[0], new Integer(1));
+ addService(aContext, getProvidedServices()[1], new Integer(2));
}
@Override
public class SystemAssemblerTest extends TestCase {
- private ServiceRegistry _registry;
-
@Override
protected void setUp() throws Exception {
super.setUp();
- _registry = new DefaultServiceRegistry();
}
private static class MyMultiple implements Serializable, Runnable {
}
public void testFilterProvided() {
- RequiredInterface req1 = new DefaultRequiredInterfaceDescriptor(
- "name", Runnable.class);
- RequiredInterface req2 = new DefaultRequiredInterfaceDescriptor(
- "name", Serializable.class);
+ RequiredInterface req1 = new DefaultRequiredInterfaceDescriptor("name",
+ Runnable.class);
+ RequiredInterface req2 = new DefaultRequiredInterfaceDescriptor("name",
+ Serializable.class);
ProvidedInterface prov1 = new DefaultProvidedInterfaceDescriptor(
"name", Runnable.class);
ProvidedInterface prov2 = new DefaultProvidedInterfaceDescriptor(
SystemAssembler.filterRequiredServices(prov1, Arrays
.asList(new RequiredInterface[] { req1 })));
AssertionUtils.assertEquals(new RequiredInterface[] { req1 },
- SystemAssembler.filterRequiredServices(prov1,
- Arrays.asList(new RequiredInterface[] { req1,
- req2 })));
- AssertionUtils.assertEquals(new RequiredInterface[] { req1,
- req2 }, SystemAssembler.filterRequiredServices(prov3, Arrays
- .asList(new RequiredInterface[] { req1, req2 })));
-
- AssertionUtils.assertEquals(
- new ProvidedInterface[] { prov1 },
+ SystemAssembler.filterRequiredServices(prov1, Arrays
+ .asList(new RequiredInterface[] { req1, req2 })));
+ AssertionUtils.assertEquals(new RequiredInterface[] { req1, req2 },
+ SystemAssembler.filterRequiredServices(prov3, Arrays
+ .asList(new RequiredInterface[] { req1, req2 })));
+
+ AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 },
SystemAssembler.filterProvidedServices(req1, Arrays
.asList(new ProvidedInterface[] { prov1 })));
- AssertionUtils.assertEquals(
- new ProvidedInterface[] { prov1 }, SystemAssembler
- .filterProvidedServices(req1, Arrays
- .asList(new ProvidedInterface[] {
- prov1, prov2 })));
- AssertionUtils.assertEquals(new ProvidedInterface[] { prov1,
- prov3 }, SystemAssembler.filterProvidedServices(req1, Arrays
- .asList(new ProvidedInterface[] { prov1, prov3 })));
+ AssertionUtils.assertEquals(new ProvidedInterface[] { prov1 },
+ SystemAssembler.filterProvidedServices(req1, Arrays
+ .asList(new ProvidedInterface[] { prov1, prov2 })));
+ AssertionUtils.assertEquals(new ProvidedInterface[] { prov1, prov3 },
+ SystemAssembler.filterProvidedServices(req1, Arrays
+ .asList(new ProvidedInterface[] { prov1, prov3 })));
}
public void testEnvironmentApplication() {
- Component environment = new Environment(_registry);
- Component application = new Application(_registry);
+ Component environment = new Environment();
+ Component application = new Application();
SystemAssembler assembler = new SystemAssembler(new Component[] {
environment, application }, new ProvidedInterface[0]);
- assembler.start(_registry, new Service[0]);
- Service[] envServices = environment.getRunningServices();
+ assembler.start();
+ ProvidedInterface[] envServices = environment.getRunningServices();
assertEquals(2, envServices.length);
- Service[] appServices = environment.getRunningServices();
+ ProvidedInterface[] appServices = environment.getRunningServices();
assertEquals(2, appServices.length);
- assertEquals(2, _registry.listAllServices().length);
+ // TODO test stopping!!!!!!
environment.stop();
- assertEquals(0, _registry.listAllServices().length);
-
application.stop();
- assertEquals(0, _registry.listAllServices().length);
}
public void testApplicationEnvironment() {
try {
- Component environment = new Environment(_registry);
- Component application = new Application(_registry);
+ Component environment = new Environment();
+ Component application = new Application();
SystemAssembler assembler = new SystemAssembler(new Component[] {
- application, environment },
- new ProvidedInterface[0]);
- assembler.start(_registry, new Service[0]);
+ application, environment }, new ProvidedInterface[0]);
+ assembler.start();
} catch (SystemAssemblyException e) {
// e.printStackTrace();
return;
}
public void testComposite() {
- Component environment = new Environment(_registry);
- Component application = new Application(_registry);
+ Component environment = new Environment();
+ Component application = new Application();
assertEquals(Status.NOT_STARTED, environment.getStatus());
assertEquals(Status.NOT_STARTED, application.getStatus());
- Container system = new Container("all", _registry, new Component[] {
- environment, application }, new ProvidedInterface[0],
+ Container system = new Container("all", new Component[] { environment,
+ application }, new ProvidedInterface[0],
new RequiredInterface[0]);
assertEquals(Status.NOT_STARTED, system.getStatus());
- system.start("root", new Service[0]);
+ system.start("root");
RequiredInterface[] required = system.getRequiredServices();
assertEquals(0, required.length);
ProvidedInterface[] provided = system.getProvidedServices();
public void testCompositeWithWrongProvidedInfo() {
try {
- Component environment = new Environment(_registry);
- Component application = new Application(_registry);
+ Component environment = new Environment();
+ Component application = new Application();
Container system = new Container(
"all",
- _registry,
new Component[] { environment, application },
new ProvidedInterface[] { new DefaultProvidedInterfaceDescriptor(
"string", String.class) },
fail();
}
+ public void testCompositeRequiredInterfaceNotProvided() {
+ try {
+ Component environment = new Environment();
+ Component application = new Application();
+ Container system = new Container(
+ "all",
+ new Component[] { environment, application },
+ new ProvidedInterface[0],
+ new RequiredInterface[] { new DefaultRequiredInterfaceDescriptor(
+ "string", String.class) });
+ system.start("root");
+ } catch (SystemAssemblyException e) {
+ return;
+ }
+ fail();
+ }
+
public void testCompositeWithSuperfluousRequiredInfo() {
- Component environment = new Environment(_registry);
- Component application = new Application(_registry);
+ Component environment = new Environment();
+ Component application = new Application();
Container system = new Container(
"all",
- _registry,
new Component[] { environment, application },
new ProvidedInterface[0],
new RequiredInterface[] { new DefaultRequiredInterfaceDescriptor(
"string", String.class) });
- system.start("root", new Service[0]);
+ system.getRequiredServices()[0].setProvider(
+ new DefaultProvidedInterfaceDescriptor("hallo", String.class));
+ system.start("root");
RequiredInterface[] required = system.getRequiredServices();
assertEquals(1, required.length);
ProvidedInterface[] provided = system.getProvidedServices();
public void testCompositeWithExternalDependencesNotProvided() {
try {
- Component environment = new Environment(_registry);
- Component application = new Application(_registry);
- Container system = new Container("all", _registry,
- new Component[] { application },
- new ProvidedInterface[0], application
- .getRequiredServices());
- system.start("root", new Service[0]);
+ Component environment = new Environment();
+ Component application = new Application();
+ Container system = new Container("all",
+ new Component[] { application }, new ProvidedInterface[0],
+ application.getRequiredServices());
+ system.start("root");
} catch (SystemAssemblyException e) {
return;
}
public void testCompositeWithExternalDependencesProvided() {
- Component environment = new Environment(_registry);
- Component application = new Application(_registry);
- Container system = new Container("all", _registry,
- new Component[] { application },
- new ProvidedInterface[0], application
- .getRequiredServices());
- Service[] envServices = environment.start("env", new Service[0]);
- system.start("root", envServices);
+ Component environment = new Environment();
+ Component application = new Application();
+ Container system = new Container("all",
+ new Component[] { application }, new ProvidedInterface[0],
+ application.getRequiredServices());
+ environment.start("env");
+ system.getRequiredServices()[0].setProvider(environment.getProvidedServices()[0]);
+ system.getRequiredServices()[1].setProvider(environment.getProvidedServices()[1]);
+
+ system.start("root");
RequiredInterface[] required = system.getRequiredServices();
assertEquals(2, required.length);
ProvidedInterface[] provided = system.getProvidedServices();
public void testAmbiguousInterfaces() {
try {
- Component environment1 = new Environment(_registry);
- Component environment2 = new Environment(_registry);
- Component application = new Application(_registry);
+ Component environment1 = new Environment();
+ Component environment2 = new Environment();
+ Component application = new Application();
SystemAssembler assembler = new SystemAssembler(new Component[] {
environment1, environment2, application },
new ProvidedInterface[0]);
- assembler.start(_registry, new Service[0]);
+ assembler.start();
} catch (SystemAssemblyException e) {
return;
public void testIncompleteRequirements() {
try {
- Component application = new Application(_registry);
- Container system = new Container("all", _registry,
- new Component[] { application },
- new ProvidedInterface[0],
+ Component application = new Application();
+ Container system = new Container("all",
+ new Component[] { application }, new ProvidedInterface[0],
new RequiredInterface[0]);
- system.start("root", new Service[0]);
+ system.start("root");
} catch (SystemAssemblyException e) {
return;
}
package org.wamblee.system.spring;
import org.springframework.beans.factory.FactoryBean;
+import org.wamblee.system.ProvidedInterface;
+import org.wamblee.system.RequiredInterface;
+import org.wamblee.system.SystemAssemblyException;
/**
* Bean which adds a service required by the spring component to
*/
class RequiredServiceBean implements FactoryBean {
- private String _id;
+ private RequiredInterface _required;
/**
* Constructs the bean.
* @param aId Id of the bean in the service registry.
*/
public RequiredServiceBean(String aId) {
- _id = aId;
+ RequiredInterface[] required = SpringComponent.THIS.get().getRequiredServices();
+ for ( RequiredInterface intf: required) {
+ if ( intf.getName().equals(aId)) {
+ _required = intf;
+ return;
+ }
+ }
+ throw new SystemAssemblyException("Cannot resolve provided component '" + aId + "'");
}
@Override
public Object getObject() throws Exception {
- return SpringComponent.REGISTRY.get().find(_id).reference(Object.class);
+ return _required.getImplementation(Object.class);
}
@Override
import org.wamblee.system.ProvidedInterface;
import org.wamblee.system.RequiredInterface;
import org.wamblee.system.Service;
-import org.wamblee.system.ServiceRegistry;
import org.wamblee.system.SystemAssembler;
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.
- *
+ * 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 SpringComponent extends AbstractComponent {
- /**
- * Singleton access to the service registry. Required while starting up.
- */
- static ThreadLocal<ServiceRegistry> REGISTRY = new ThreadLocal<ServiceRegistry>();
+ static final ThreadLocal<SpringComponent> THIS = new ThreadLocal<SpringComponent>();
- private Properties _properties;
+ private Properties _properties;
private String[] _configFiles;
private Map<String, ProvidedInterface> _provided;
private Map<RequiredInterface, String> _required;
* names that the spring config files use for each required
* service.
*/
- public SpringComponent(String aName, ServiceRegistry aRegistry, String[] aConfigFiles,
+ public SpringComponent(String aName, String[] aConfigFiles,
Map<String, ProvidedInterface> aProvided,
Map<RequiredInterface, String> aRequired) {
- super(aName, aRegistry, aProvided.values().toArray(new ProvidedInterface[0]),
+ super(aName, aProvided.values().toArray(new ProvidedInterface[0]),
aRequired.keySet().toArray(new RequiredInterface[0]));
- _properties = new Properties();
+ _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.
+ * 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) {
+ 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));
+
+ 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 oldRegistry = REGISTRY.get();
- try {
- REGISTRY.set(getRegistry());
- try {
- _parentContext = new GenericApplicationContext();
-
- registerRequiredServices(aRequiredServices);
-
- _parentContext.refresh();
-
- parseConfigFiles();
-
- _context.addBeanFactoryPostProcessor(new PropertySetter(_properties));
- _context.refresh();
-
- exposeProvidedServices(aContext);
- } catch (Exception e) {
- throw new SystemAssemblyException(
- "Failed to assemble spring system", e);
- }
+ protected void doStart(String aContext) {
+
+ SpringComponent old = THIS.get();
+ THIS.set(this);
+ try {
+ _parentContext = new GenericApplicationContext();
+
+ registerRequiredServices();
+
+ _parentContext.refresh();
+
+ parseConfigFiles();
+
+ _context
+ .addBeanFactoryPostProcessor(new PropertySetter(_properties));
+ _context.refresh();
+
+ exposeProvidedServices(aContext);
+ } catch (Exception e) {
+ throw new SystemAssemblyException(
+ "Failed to assemble spring system", e);
} finally {
- REGISTRY.set(oldRegistry);
+ THIS.set(old);
}
}
_parentContext);
}
- private void registerRequiredServices(Service[] aRequiredServices) {
+ private void registerRequiredServices() {
// Register required services in a parent context
-
- for (Service svc: aRequiredServices) {
- String id = svc.getId();
- ProvidedInterface descriptor = svc.getDescriptor();
- RequiredInterface[] requiredServices = SystemAssembler.filterRequiredServices(descriptor,
- _required.keySet());
- for (RequiredInterface required: requiredServices) {
- String beanName = _required.get(required);
- ConstructorArgumentValues cargs = new ConstructorArgumentValues();
- cargs.addGenericArgumentValue(id);
- BeanDefinition definition = new RootBeanDefinition(RequiredServiceBean.class, cargs,
- new MutablePropertyValues());
- _parentContext.registerBeanDefinition(beanName, definition);
- }
+ for (RequiredInterface required: getRequiredServices()) {
+ 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);
}
}
@Override
protected void doStop() {
- _context.close();
+ _context.close();
}
}
import org.wamblee.io.ClassPathResource;
import org.wamblee.system.DefaultProvidedInterfaceDescriptor;
import org.wamblee.system.DefaultRequiredInterfaceDescriptor;
-import org.wamblee.system.DefaultServiceRegistry;
+import org.wamblee.system.DefaultService;
import org.wamblee.system.ProvidedInterface;
import org.wamblee.system.RequiredInterface;
import org.wamblee.system.Service;
-import org.wamblee.system.ServiceRegistry;
import org.wamblee.system.SystemAssemblyException;
public class SpringComponentTest extends TestCase {
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;
-
@Override
protected void setUp() throws Exception {
super.setUp();
- _registry = new DefaultServiceRegistry();
}
public void testBlackboxSystem() {
- SpringComponent system = new SpringComponent("system", _registry,
+ SpringComponent system = new SpringComponent("system",
new String[] { HELLO_SERVICE_SPRING_XML },
new HashMap<String, ProvidedInterface>(),
new HashMap<RequiredInterface, String>());
- system.start("Hello", new Service[0]);
- Service[] services = system.getRunningServices();
+ system.start("Hello");
+ ProvidedInterface[] services = system.getRunningServices();
assertEquals(0, services.length);
system.stop();
provided.put("helloService", new DefaultProvidedInterfaceDescriptor(
"hello", HelloService.class));
- SpringComponent system = new SpringComponent("system", _registry,
+ SpringComponent system = new SpringComponent("system",
new String[] { HELLO_SERVICE_SPRING_XML }, provided,
new HashMap<RequiredInterface, String>());
- system.start("Hello", new Service[0]);
- Service[] services = system.getRunningServices();
+ system.start("Hello");
+ ProvidedInterface[] services = system.getRunningServices();
assertEquals(1, services.length);
- assertTrue(services[0].reference(HelloService.class) instanceof HelloService);
- assertEquals("Hello world!", services[0].reference(HelloService.class)
+ assertTrue(services[0].getImplementation() instanceof HelloService);
+ assertEquals("Hello world!", ((HelloService)services[0].getImplementation())
.say());
system.stop();
}
Map<String, ProvidedInterface> provided = new HashMap<String, ProvidedInterface>();
provided.put("helloService", new DefaultProvidedInterfaceDescriptor(
"hello", HelloService.class));
- SpringComponent system = new SpringComponent("system", _registry,
+ SpringComponent system = new SpringComponent("system",
new String[] { HELLO_SERVICE_SPRING_WITH_PROPERTIES_XML },
provided,
new HashMap<RequiredInterface, String>());
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());
+ system.start("Hello");
+ ProvidedInterface[] services = system.getRunningServices();
+ assertEquals("Property Value",
+ ((HelloService)services[0].getImplementation()).say());
}
public void testWithMissingRequirement() {
try {
- SpringComponent system = new SpringComponent("system", _registry,
+ SpringComponent system = new SpringComponent("system",
new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML },
new HashMap<String, ProvidedInterface>(),
new HashMap<RequiredInterface, String>());
- system.start("Bla", new Service[0]);
+ system.start("Bla");
} catch (SystemAssemblyException e) {
//e.printStackTrace();
return;
Map<RequiredInterface, String> required = new HashMap<RequiredInterface, String>();
required.put(new DefaultRequiredInterfaceDescriptor("hello", HelloService.class),
"helloService");
- SpringComponent system = new SpringComponent("system", _registry,
+ SpringComponent system = new SpringComponent("system",
new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML },
new HashMap<String, ProvidedInterface>(), required);
HelloService helloObject = new HelloService("ladida");
- Service helloService = _registry.register(new DefaultProvidedInterfaceDescriptor("hello", HelloService.class), helloObject);
- system.start("Bla", new Service[] { helloService } );
+ ProvidedInterface helloService = new DefaultProvidedInterfaceDescriptor("hello", HelloService.class);
+ helloService.publish(helloObject);
+ system.getRequiredServices()[0].setProvider(helloService);
+
+ system.start("Bla");
system.stop();
}
provided.put("blaService", new DefaultProvidedInterfaceDescriptor("bla",
BlaService.class));
- SpringComponent system = new SpringComponent("system", _registry,
+ SpringComponent system = new SpringComponent("system",
new String[] { HELLO_SERVICE_SPRING_WITH_REQS_XML },
provided, required);
HelloService helloObject = new HelloService("ladida");
- Service helloService = _registry.register(new DefaultProvidedInterfaceDescriptor("hello", HelloService.class), helloObject);
- Service[] services = system.start("Bla", new Service[] { helloService } );
- assertEquals(1, services.length);
+ ProvidedInterface helloService =
+ new DefaultProvidedInterfaceDescriptor("hello", HelloService.class);
+ helloService.publish(helloObject);
+ system.getRequiredServices()[0].setProvider(helloService);
+ system.start("Bla");
+ ProvidedInterface started = system.getProvidedServices()[0];
- assertTrue(services[0].reference(BlaService.class) instanceof BlaService);
- assertEquals("ladida", services[0].reference(BlaService.class)
- .execute());
+ assertNotNull(started.getImplementation());
+ assertTrue(started.getImplementation() instanceof BlaService);
+ assertEquals("ladida",
+ ((BlaService)started.getImplementation()).execute());
system.stop();
}