From 1ed307765e13f0f768e3a8ef10106c7d1d779535 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Wed, 18 Nov 2009 00:12:15 +0000 Subject: [PATCH] INT-881, Added ControlBusBindingMessageDistributionListener, fixed template.mf (after real OSGi testing), added tests --- .../osgi/IntegrationOSGiConstants.java | 5 ++ ...AbstractOSGiServiceManagingParserUtil.java | 33 ++++++++- .../osgi/config/xml/ConfigParser.java | 36 +++++++-- .../config/xml/SiTypeToJavaTypeMaper.java | 5 +- ...BusBindingMessageDistributionListener.java | 73 +++++++++++++++++++ ...istrationMessageDistributionListener.java} | 33 +++++---- .../IntegrationServiceBindingListener.java | 67 +++++++++++++++++ .../spring/integration-control-bus.xml | 4 +- ...pring-integration-service-extender-1.0.xsd | 10 +-- .../xml/ConfigParserImporterTests-default.xml | 2 +- .../ConfigParserImporterTests-exporter.xml | 18 +++++ .../config/xml/ConfigParserImporterTests.java | 66 ++++++++++++++++- .../template.mf | 3 +- .../controlbus/ControlBusMessageHandler.java | 6 +- 14 files changed, 316 insertions(+), 45 deletions(-) create mode 100644 org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/ControlBusBindingMessageDistributionListener.java rename org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/{IntegrationServiceRegistrationListener.java => ControlBusRegistrationMessageDistributionListener.java} (62%) create mode 100644 org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/IntegrationServiceBindingListener.java create mode 100644 org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests-exporter.xml diff --git a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/IntegrationOSGiConstants.java b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/IntegrationOSGiConstants.java index 1bc5fc78fc..6977cccb4c 100644 --- a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/IntegrationOSGiConstants.java +++ b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/IntegrationOSGiConstants.java @@ -23,4 +23,9 @@ package org.springframework.integration.osgi; */ public interface IntegrationOSGiConstants { public final String OSGI_BEAN_NAME = "org.springframework.osgi.bean.name"; + public final String INTEGRATION_EVENT_TYPE = "INTEGRATION_EVENT_TYPE"; + public final String REGISTRATION = "REGISTRATION"; + public final String UNREGISTRATION = "UNREGISTRATION"; + public final String BINDING = "BINDING"; + public final String UNBINDING= "UNBINDING"; } diff --git a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/AbstractOSGiServiceManagingParserUtil.java b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/AbstractOSGiServiceManagingParserUtil.java index dee3ad4da7..a9e880d406 100644 --- a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/AbstractOSGiServiceManagingParserUtil.java +++ b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/AbstractOSGiServiceManagingParserUtil.java @@ -18,7 +18,8 @@ package org.springframework.integration.osgi.config.xml; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionRegistry; -import org.springframework.integration.osgi.extender.IntegrationServiceRegistrationListener; +import org.springframework.integration.osgi.extender.ControlBusBindingMessageDistributionListener; +import org.springframework.integration.osgi.extender.ControlBusRegistrationMessageDistributionListener; import org.springframework.osgi.service.exporter.support.AutoExport; import org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean; import org.springframework.osgi.service.importer.support.Cardinality; @@ -81,10 +82,14 @@ public class AbstractOSGiServiceManagingParserUtil { if (publishedIntefaces != null && publishedIntefaces.length > 0){ serviceBuilder.addPropertyValue("interfaces", publishedIntefaces); } + // will make sure it uses exporter's bean name when building a relationship with importer serviceBuilder.addPropertyValue("serviceBeanName", beanName); //TODO: pf.setTimeout(timeoutInMillis) +// OsgiServiceProxyFactoryBean b = null; +// b.setListeners(listeners) + return serviceBuilder; } /** @@ -99,15 +104,37 @@ public class AbstractOSGiServiceManagingParserUtil { public static AbstractBeanDefinition defineRegistrationListenerForBus(BeanDefinitionRegistry registry, BeanDefinitionBuilder exporterBuilder, String busBeanName){ + // create listener builder BeanDefinitionBuilder listenerBuilder = - BeanDefinitionBuilder.genericBeanDefinition(IntegrationServiceRegistrationListener.class); + BeanDefinitionBuilder.genericBeanDefinition(ControlBusRegistrationMessageDistributionListener.class); String busGroupName = busBeanName; + // if reference to the bus doesn't exist yet, create one + // corresponding bean is not the actual bus but a ControlBusListentingDecorator if (!registry.containsBeanDefinition(busGroupName)){ ControlBusOSGiUtils.registerImporterForControlBus(registry, busGroupName); } listenerBuilder.addConstructorArgReference(busGroupName); AbstractBeanDefinition listenerDefinition = listenerBuilder.getBeanDefinition(); - exporterBuilder.addPropertyValue("listeners", listenerDefinition); + //exporterBuilder.addPropertyValue("listeners", listenerDefinition); return listenerDefinition; } + + public static AbstractBeanDefinition defineBindingListenerForBus(BeanDefinitionRegistry registry, + BeanDefinitionBuilder exporterBuilder, + String busBeanName){ + // create listener builder + BeanDefinitionBuilder listenerBuilder = + BeanDefinitionBuilder.genericBeanDefinition(ControlBusBindingMessageDistributionListener.class); + String busGroupName = busBeanName; + // if reference to the bus doesn't exist yet, create one + // corresponding bean is not the actual bus but a ControlBusListentingDecorator + if (!registry.containsBeanDefinition(busGroupName)){ + ControlBusOSGiUtils.registerImporterForControlBus(registry, busGroupName); + } + listenerBuilder.addConstructorArgReference(busGroupName); + AbstractBeanDefinition listenerDefinition = listenerBuilder.getBeanDefinition(); + //exporterBuilder.addPropertyValue("listeners", listenerDefinition); + return listenerDefinition; + } + } diff --git a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/ConfigParser.java b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/ConfigParser.java index 714091d027..92e972575e 100644 --- a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/ConfigParser.java +++ b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/ConfigParser.java @@ -16,17 +16,26 @@ package org.springframework.integration.osgi.config.xml; import java.util.List; +import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanReference; +import org.springframework.beans.factory.config.RuntimeBeanNameReference; +import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; -import org.springframework.integration.osgi.extender.IntegrationServiceRegistrationListener; +import org.springframework.integration.osgi.extender.ControlBusBindingMessageDistributionListener; +import org.springframework.integration.osgi.extender.ControlBusRegistrationMessageDistributionListener; +import org.springframework.osgi.service.exporter.OsgiServiceRegistrationListener; +import org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean; import org.springframework.util.Assert; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; @@ -83,6 +92,15 @@ public class ConfigParser implements BeanDefinitionParser { Class[] interfaces = this.discoverInterfaces(serviceName, element); BeanDefinitionBuilder importerBuilder = AbstractOSGiServiceManagingParserUtil.defineServiceImporterFor(serviceName, null, registry, interfaces); + // + if (element.hasAttribute(CONTROL_BUS)){ + String busBeanName = element.getAttribute(CONTROL_BUS); + BeanDefinition listenerDefinition = + AbstractOSGiServiceManagingParserUtil.defineBindingListenerForBus(registry, importerBuilder, busBeanName); + importerBuilder.addPropertyValue("listeners", listenerDefinition); + } + + // registry.registerBeanDefinition(serviceName, importerBuilder.getBeanDefinition()); } /** @@ -114,26 +132,34 @@ public class ConfigParser implements BeanDefinitionParser { private void generateServiceExorterDefinition(String beanName, Element element, BeanDefinitionRegistry registry){ BeanDefinitionBuilder exportedElementBuilder = AbstractOSGiServiceManagingParserUtil.defineServiceExporterFor(beanName, registry); - this.connectWithControlBusIfRequired(element, exportedElementBuilder, registry, beanName); + BeanDefinition controlBusMessageDistributorDefinition = + this.defineControlBusMessageDistributor(element, exportedElementBuilder, registry, beanName); + ManagedList listenerDefinitions = new ManagedList(); + listenerDefinitions.add(controlBusMessageDistributorDefinition); + // NOTE: add more listeners here if needed + exportedElementBuilder.addPropertyValue("listeners", listenerDefinitions); registry.registerBeanDefinition(beanName+EXPORTER_SUFFIX, exportedElementBuilder.getBeanDefinition()); } /** - * If element specifies 'control-bus' attribute, this method will register {@link IntegrationServiceRegistrationListener} + * If element specifies 'control-bus' attribute, this method will register {@link ControlBusRegistrationMessageDistributionListener} * which will send registration messages to the ControlBus */ - private void connectWithControlBusIfRequired(Element originalElement, + private BeanDefinition defineControlBusMessageDistributor(Element originalElement, BeanDefinitionBuilder exportedElementBuilder, BeanDefinitionRegistry registry, String componentName) { + //String beanName = null; + AbstractBeanDefinition listenerDefinition = null; if (originalElement.hasAttribute(CONTROL_BUS)){ String controlBusAttributeValue = originalElement.getAttribute(CONTROL_BUS); Assert.hasText(controlBusAttributeValue, "You must provide control bus name when defining 'control-bus' attribute"); log.trace("Adding registration listener for exported OSGi service for:" + componentName); - AbstractBeanDefinition listenerDefinition = + listenerDefinition = AbstractOSGiServiceManagingParserUtil.defineRegistrationListenerForBus(registry, exportedElementBuilder, controlBusAttributeValue); BeanDefinitionReaderUtils.registerWithGeneratedName(listenerDefinition, registry); } + return listenerDefinition; } /** */ diff --git a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/SiTypeToJavaTypeMaper.java b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/SiTypeToJavaTypeMaper.java index 2f579eebd7..bd2ee3b821 100644 --- a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/SiTypeToJavaTypeMaper.java +++ b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/config/xml/SiTypeToJavaTypeMaper.java @@ -18,8 +18,7 @@ package org.springframework.integration.osgi.config.xml; import java.util.HashMap; import java.util.Map; -import org.springframework.integration.channel.PublishSubscribeChannel; -import org.springframework.osgi.util.internal.ClassUtils; +import org.springframework.integration.channel.SubscribableChannel; import org.springframework.util.Assert; /** @@ -32,7 +31,7 @@ class SiTypeToJavaTypeMaper { private static Map siTypeMappings = new HashMap(); static { - siTypeMappings.put(PUB_SUB_CHANNEL, ClassUtils.getClassHierarchy(PublishSubscribeChannel.class, ClassUtils.INCLUDE_INTERFACES)); + siTypeMappings.put(PUB_SUB_CHANNEL, new Class[]{SubscribableChannel.class}); } public static Class[] mapSiType(String siType){ diff --git a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/ControlBusBindingMessageDistributionListener.java b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/ControlBusBindingMessageDistributionListener.java new file mode 100644 index 0000000000..498ffc48a6 --- /dev/null +++ b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/ControlBusBindingMessageDistributionListener.java @@ -0,0 +1,73 @@ +/* + * Copyright 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.osgi.extender; + +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.integration.controlbus.ControlBus; +import org.springframework.integration.message.MessageBuilder; +import org.springframework.integration.osgi.IntegrationOSGiConstants; +import org.springframework.osgi.service.importer.OsgiServiceLifecycleListener; + +/** + * TODO - insert COMMENT + * @author Oleg Zhurakousky + * @since 2.0 + */ +public class ControlBusBindingMessageDistributionListener implements + OsgiServiceLifecycleListener { + private static final Log log = LogFactory.getLog(ControlBusBindingMessageDistributionListener.class); + private ControlBus controlBus; + + public ControlBusBindingMessageDistributionListener(ControlBus controlBus){ + this.controlBus = controlBus; + } + + /* (non-Javadoc) + * @see org.springframework.osgi.service.importer.OsgiServiceLifecycleListener#bind(java.lang.Object, java.util.Map) + */ + @SuppressWarnings("unchecked") + public void bind(Object service, Map properties) throws Exception { + if (controlBus.isBusAvailable()){ + log.info("Dispatching BINDING Message for: " + properties.get(IntegrationOSGiConstants.OSGI_BEAN_NAME) + + "- " + properties + " to: " + + controlBus.getName()); + MessageBuilder builder = MessageBuilder.withPayload(properties.get(IntegrationOSGiConstants.OSGI_BEAN_NAME)); + builder.copyHeaders(properties); + builder.setHeader(IntegrationOSGiConstants.INTEGRATION_EVENT_TYPE, IntegrationOSGiConstants.BINDING); + controlBus.send(builder.build()); + } + } + + /* (non-Javadoc) + * @see org.springframework.osgi.service.importer.OsgiServiceLifecycleListener#unbind(java.lang.Object, java.util.Map) + */ + @SuppressWarnings("unchecked") + public void unbind(Object service, Map properties) throws Exception { + if (controlBus.isBusAvailable()){ + log.info("Dispatching UNBINDING Message for: " + properties.get(IntegrationOSGiConstants.OSGI_BEAN_NAME) + + "- " + properties + " to: " + + controlBus.getName()); + MessageBuilder builder = MessageBuilder.withPayload(properties.get(IntegrationOSGiConstants.OSGI_BEAN_NAME)); + builder.copyHeaders(properties); + builder.setHeader(IntegrationOSGiConstants.INTEGRATION_EVENT_TYPE, IntegrationOSGiConstants.UNBINDING); + controlBus.send(builder.build()); + } + } + +} diff --git a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/IntegrationServiceRegistrationListener.java b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/ControlBusRegistrationMessageDistributionListener.java similarity index 62% rename from org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/IntegrationServiceRegistrationListener.java rename to org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/ControlBusRegistrationMessageDistributionListener.java index 9d695a07f5..1023cea96a 100644 --- a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/IntegrationServiceRegistrationListener.java +++ b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/ControlBusRegistrationMessageDistributionListener.java @@ -20,7 +20,8 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.integration.controlbus.ControlBus; -import org.springframework.integration.message.StringMessage; +import org.springframework.integration.message.MessageBuilder; +import org.springframework.integration.osgi.IntegrationOSGiConstants; import org.springframework.osgi.service.exporter.OsgiServiceRegistrationListener; /** @@ -30,12 +31,12 @@ import org.springframework.osgi.service.exporter.OsgiServiceRegistrationListener * @author Oleg Zhurakousky * @since 2.0 */ -public class IntegrationServiceRegistrationListener implements OsgiServiceRegistrationListener { - private static final Log log = LogFactory.getLog(IntegrationServiceRegistrationListener.class); - private ControlBusListeningDecorator controlBusDecorator; +public class ControlBusRegistrationMessageDistributionListener implements OsgiServiceRegistrationListener { + private static final Log log = LogFactory.getLog(ControlBusRegistrationMessageDistributionListener.class); + private ControlBus controlBus; - public IntegrationServiceRegistrationListener(ControlBusListeningDecorator controlBusDecorator){ - this.controlBusDecorator = controlBusDecorator; + public ControlBusRegistrationMessageDistributionListener(ControlBus controlBus){ + this.controlBus = controlBus; } /** * Will send a notification message to the named {@link ControlBus} notifying that service @@ -43,11 +44,13 @@ public class IntegrationServiceRegistrationListener implements OsgiServiceRegist */ @SuppressWarnings("unchecked") public void registered(Object service, Map properties){ - if (controlBusDecorator.isBusAvailable()){ + if (controlBus.isBusAvailable()){ log.info("Dispatching REGISTRATION Message for: " + service + "- " + properties + " to: " + - controlBusDecorator.getName()); - //TODO: change to structural message - controlBusDecorator.send(new StringMessage("Dispatching REGISTRATION Message for: " + service + "- " + properties)); + controlBus.getName()); + MessageBuilder builder = MessageBuilder.withPayload(service); + builder.copyHeaders(properties); + builder.setHeader(IntegrationOSGiConstants.INTEGRATION_EVENT_TYPE, IntegrationOSGiConstants.REGISTRATION); + controlBus.send(builder.build()); } } /** @@ -56,11 +59,13 @@ public class IntegrationServiceRegistrationListener implements OsgiServiceRegist */ @SuppressWarnings("unchecked") public void unregistered(Object service, Map properties){ - if (controlBusDecorator.isBusAvailable()){ + if (controlBus.isBusAvailable()){ log.info("Dispatching UN-REGISTRATION Message for: " + service + "- " + properties + " to: " + - controlBusDecorator.getName()); - //TODO: change to structural message - controlBusDecorator.send(new StringMessage("Dispatching UN-REGISTRATION Message for: " + service + "- " + properties)); + controlBus.getName()); + MessageBuilder builder = MessageBuilder.withPayload(service); + builder.copyHeaders(properties); + builder.setHeader(IntegrationOSGiConstants.INTEGRATION_EVENT_TYPE, IntegrationOSGiConstants.UNREGISTRATION); + controlBus.send(builder.build()); } } } diff --git a/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/IntegrationServiceBindingListener.java b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/IntegrationServiceBindingListener.java new file mode 100644 index 0000000000..a886c52599 --- /dev/null +++ b/org.springframework.integration.osgi/src/main/java/org/springframework/integration/osgi/extender/IntegrationServiceBindingListener.java @@ -0,0 +1,67 @@ +/* + * Copyright 2002-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.osgi.extender; + +import java.util.List; +import java.util.Map; + +import org.springframework.context.Lifecycle; +import org.springframework.osgi.service.importer.OsgiServiceLifecycleListener; + +/** + * TODO - insert COMMENT + * @author Oleg Zhurakousky + * @since 2.0 + */ +public class IntegrationServiceBindingListener implements + OsgiServiceLifecycleListener { + private List dependentSources; + + /* (non-Javadoc) + * @see org.springframework.osgi.service.importer.OsgiServiceLifecycleListener#bind(java.lang.Object, java.util.Map) + */ + public void bind(Object service, Map properties) throws Exception { + for (Object dependentSource : dependentSources) { + if (dependentSource instanceof Lifecycle){ + Lifecycle lifecycle = (Lifecycle) dependentSource; + if (lifecycle.isRunning()){ + lifecycle.stop(); + } + } + } + } + + /* (non-Javadoc) + * @see org.springframework.osgi.service.importer.OsgiServiceLifecycleListener#unbind(java.lang.Object, java.util.Map) + */ + public void unbind(Object service, Map properties) throws Exception { + for (Object dependentSource : dependentSources) { + if (dependentSource instanceof Lifecycle){ + Lifecycle lifecycle = (Lifecycle) dependentSource; + if (!lifecycle.isRunning()){ + lifecycle.start(); + } + } + } + } + public List getDependentSources() { + return dependentSources; + } + + public void setDependentSources(List dependentSources) { + this.dependentSources = dependentSources; + } +} diff --git a/org.springframework.integration.osgi/src/main/resources/META-INF/spring/integration-control-bus.xml b/org.springframework.integration.osgi/src/main/resources/META-INF/spring/integration-control-bus.xml index 2be951a774..55aeb6149c 100644 --- a/org.springframework.integration.osgi/src/main/resources/META-INF/spring/integration-control-bus.xml +++ b/org.springframework.integration.osgi/src/main/resources/META-INF/spring/integration-control-bus.xml @@ -24,10 +24,10 @@ - + - + diff --git a/org.springframework.integration.osgi/src/main/resources/org/springframework/integration/osgi/config/xml/spring-integration-service-extender-1.0.xsd b/org.springframework.integration.osgi/src/main/resources/org/springframework/integration/osgi/config/xml/spring-integration-service-extender-1.0.xsd index 98945d934c..eb815230eb 100644 --- a/org.springframework.integration.osgi/src/main/resources/org/springframework/integration/osgi/config/xml/spring-integration-service-extender-1.0.xsd +++ b/org.springframework.integration.osgi/src/main/resources/org/springframework/integration/osgi/config/xml/spring-integration-service-extender-1.0.xsd @@ -75,14 +75,6 @@ - - - - Will export all components of type - <channel> as SI Services - s - - @@ -97,7 +89,7 @@ 'control-bus'. (OPTIONAL if no control is necessary) - + diff --git a/org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests-default.xml b/org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests-default.xml index 5b03a81a19..7a75815ab7 100644 --- a/org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests-default.xml +++ b/org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests-default.xml @@ -10,7 +10,7 @@ http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd"> - + diff --git a/org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests-exporter.xml b/org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests-exporter.xml new file mode 100644 index 0000000000..c4f141e3a5 --- /dev/null +++ b/org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests-exporter.xml @@ -0,0 +1,18 @@ + + + + + + + + + + diff --git a/org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests.java b/org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests.java index 98e2b5b4bd..879fff6ab5 100644 --- a/org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests.java +++ b/org.springframework.integration.osgi/src/test/java/org/springframework/integration/osgi/config/xml/ConfigParserImporterTests.java @@ -18,10 +18,18 @@ package org.springframework.integration.osgi.config.xml; import static org.junit.Assert.assertNotNull; import org.junit.Test; +import org.mockito.Mockito; import org.osgi.framework.BundleContext; import org.springframework.context.ApplicationContext; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.integration.channel.SubscribableChannel; +import org.springframework.integration.controlbus.ControlBus; +import org.springframework.integration.core.Message; +import org.springframework.integration.message.MessageHandler; +import org.springframework.integration.message.StringMessage; import org.springframework.integration.osgi.AbstractSIConfigBundleTestDeployer; import org.springframework.integration.osgi.stubs.SIBundleContextStub; +import org.springframework.osgi.service.ServiceUnavailableException; /** * Tests 'config' element. @@ -32,13 +40,67 @@ import org.springframework.integration.osgi.stubs.SIBundleContextStub; public class ConfigParserImporterTests extends AbstractSIConfigBundleTestDeployer { @Test - public void testBasicSIServiceConfig() throws Exception { + public void testBasicSIServiceConfigNoBackingService() throws Exception { BundleContext bundleContext = SIBundleContextStub.getNewInstance(); ApplicationContext ac = this.deploySIConfig(bundleContext, "org/springframework/integration/osgi/config/xml/", "ConfigParserImporterTests-default.xml"); + SubscribableChannel channel = ac.getBean("channelA", SubscribableChannel.class); + assertNotNull(channel); + } + @Test(expected=ServiceUnavailableException.class) + public void testBasicSIServiceConfigNoBackingServiceError() throws Exception { + BundleContext bundleContext = SIBundleContextStub.getNewInstance(); + ApplicationContext ac = this.deploySIConfig(bundleContext, + "org/springframework/integration/osgi/config/xml/", + "ConfigParserImporterTests-default.xml"); + SubscribableChannel channel = ac.getBean("channelA", SubscribableChannel.class); + assertNotNull(channel); + // try to use it and see error + channel.send(null); + } + /** + * Will register AC with service importer, then it will register another AC with service exporter + * + * @throws Exception + */ + @Test + public void testBasicSIServiceConfigWithBackingService() throws Exception { + BundleContext bundleContext = SIBundleContextStub.getNewInstance(); + ApplicationContext ac = this.deploySIConfig(bundleContext, + "org/springframework/integration/osgi/config/xml/", + "ConfigParserImporterTests-default.xml"); + SubscribableChannel channel = ac.getBean("channelA", SubscribableChannel.class); + assertNotNull(channel); + this.deploySIConfig(bundleContext, + "org/springframework/integration/osgi/config/xml/", + "ConfigParserImporterTests-exporter.xml"); + MessageHandler handler = Mockito.mock(MessageHandler.class); + Message message = new StringMessage("hello"); + channel.subscribe(handler); + channel.send(message); + Mockito.verify(handler, Mockito.times(1)).handleMessage(message); + } + @Test + public void testControlBusAttributeWithBusPresent() throws Exception { + BundleContext bundleContext = SIBundleContextStub.getNewInstance(); + ConfigurableApplicationContext busAC = this.deploySIConfig(bundleContext, + "org/springframework/integration/osgi/config/xml/", + "BusConfigParserTests-default.xml"); + ConfigurableApplicationContext exporterAC = this.deploySIConfig(bundleContext, + "org/springframework/integration/osgi/config/xml/", + "ConfigParserImporterTests-exporter.xml"); + ConfigurableApplicationContext ac = this.deploySIConfig(bundleContext, + "org/springframework/integration/osgi/config/xml/", + "ConfigParserImporterTests-default.xml"); assertNotNull(ac.getBean("channelA")); - + ControlBus bus = (ControlBus) ac.getBean("DEFAULT_CONTROL_GROUP"); + assertNotNull(bus); + MessageHandler handler = Mockito.mock(MessageHandler.class); + bus.subscribe(handler); + exporterAC.close(); + // should be 3 notification messages sent to the bus + Mockito.verify(handler, Mockito.times(1)).handleMessage((Message) Mockito.any()); } } diff --git a/org.springframework.integration.osgi/template.mf b/org.springframework.integration.osgi/template.mf index 05a09d1e68..ae024dc09a 100644 --- a/org.springframework.integration.osgi/template.mf +++ b/org.springframework.integration.osgi/template.mf @@ -5,7 +5,8 @@ Bundle-ManifestVersion: 2 Import-Package: org.springframework.integration.handler;version="[2.0.0, 2.0.1)", org.springframework.integration.config;version="[2.0.0, 2.0.1)", org.springframework.integration.router;version="[2.0.0, 2.0.1)", - org.springframework.integration.endpoint;version="[2.0.0, 2.0.1)" + org.springframework.integration.endpoint;version="[2.0.0, 2.0.1)", + org.springframework.scheduling.concurrent;version="[3.0.0, 3.1.0]" Import-Template: org.springframework.integration.*;version="[2.0.0, 2.0.1)", org.springframework.osgi.*;version="[1.2.0, 2.0.1)", org.springframework.*;version="[3.0.0, 3.1.0]", diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/controlbus/ControlBusMessageHandler.java b/org.springframework.integration/src/main/java/org/springframework/integration/controlbus/ControlBusMessageHandler.java index e47bcc2a38..74b137d74d 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/controlbus/ControlBusMessageHandler.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/controlbus/ControlBusMessageHandler.java @@ -17,7 +17,6 @@ package org.springframework.integration.controlbus; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.integration.core.CommandMessage; import org.springframework.integration.core.Message; import org.springframework.integration.message.MessageDeliveryException; import org.springframework.integration.message.MessageHandler; @@ -36,10 +35,7 @@ public class ControlBusMessageHandler implements MessageHandler { public void handleMessage(Message message) throws MessageRejectedException, MessageHandlingException, MessageDeliveryException { - if (message instanceof CommandMessage){ - log.debug("Handling CommandMessage: " + message); - ((CommandMessage)message).execute(); - } + log.debug("Handling control message: " + message); } }