INT-881, Decoupled SI Services configuration from service interaction with the Control Bus
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Constants used by OSGi Service Extender
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface IntegrationOSGiConstants {
|
||||
public final String OSGI_BEAN_NAME = "org.springframework.osgi.bean.name";
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.springframework.integration.channel.SubscribableChannel;
|
||||
import org.springframework.integration.controlbus.ControlBus;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
|
||||
/**
|
||||
* Implementation of the {@link ControlBus} interface.
|
||||
* Control Bus itself wrapper over {@link SubscribableChannel},
|
||||
* which represents the entry point to Control Bus infrastructure.
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class OSGiIntegrationControlBus implements ControlBus {
|
||||
private SubscribableChannel channel;
|
||||
private String busName;
|
||||
|
||||
public OSGiIntegrationControlBus(SubscribableChannel channel, String busName){
|
||||
this.channel = channel;
|
||||
this.busName = busName;
|
||||
}
|
||||
|
||||
public boolean subscribe(MessageHandler handler) {
|
||||
return channel.subscribe(handler);
|
||||
}
|
||||
|
||||
|
||||
public boolean unsubscribe(MessageHandler handler) {
|
||||
return channel.unsubscribe(handler);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return channel.getName();
|
||||
}
|
||||
|
||||
|
||||
public boolean send(Message<?> message) {
|
||||
return channel.send(message);
|
||||
}
|
||||
|
||||
|
||||
public boolean send(Message<?> message, long timeout) {
|
||||
return channel.send(message, timeout);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.integration.controlbus.ControlBus#isBusAvailable()
|
||||
*/
|
||||
public boolean isBusAvailable() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -15,21 +15,21 @@
|
||||
*/
|
||||
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.controlbus.ControlBus;
|
||||
import org.springframework.intergration.osgi.IntegrationOSGiConstants;
|
||||
import org.springframework.integration.osgi.extender.IntegrationServiceRegistrationListener;
|
||||
import org.springframework.osgi.service.exporter.support.AutoExport;
|
||||
import org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean;
|
||||
import org.springframework.osgi.service.importer.support.Cardinality;
|
||||
import org.springframework.osgi.service.importer.support.OsgiServiceProxyFactoryBean;
|
||||
import org.springframework.osgi.util.OsgiBundleUtils;
|
||||
import org.springframework.osgi.util.OsgiServiceUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Will register {@link OsgiServiceFactoryBean} to export {@link ControlBus} as an OSGi service
|
||||
* Utility class which wraps Spring-DM factory bean creation for exporting and importing SI components as
|
||||
* OSGi services.
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
@@ -37,14 +37,20 @@ import org.springframework.util.StringUtils;
|
||||
public class AbstractOSGiServiceManagingParserUtil {
|
||||
|
||||
/**
|
||||
* Will export a bean identified by the 'beanName' as an OSGi Service. It will publish the service under all
|
||||
* interfaces visible this class represents.
|
||||
* Will define OSGi Service exporter BeanDefinitionBuilder for a bean identified by the 'beanName'
|
||||
* parameter as an OSGi Service. If 'publishInterfaces' parameter is not provided this exporter will
|
||||
* use all interfaces implemented by this service class hierarchy. Otherwise you can provide an array of
|
||||
* specific interfaces to be published under this service.
|
||||
*
|
||||
* @param beanName
|
||||
* @param registry
|
||||
* @param publishedIntefaces
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static BeanDefinitionBuilder defineServiceExporterFor(String beanName, BeanDefinitionRegistry registry, Class... publishedIntefaces){
|
||||
public static BeanDefinitionBuilder defineServiceExporterFor(String beanName,
|
||||
BeanDefinitionRegistry registry,
|
||||
Class... publishedIntefaces){
|
||||
BeanDefinitionBuilder serviceBuilder = BeanDefinitionBuilder.genericBeanDefinition(OsgiServiceFactoryBean.class);
|
||||
serviceBuilder.addPropertyValue("targetBeanName", beanName);
|
||||
if (publishedIntefaces != null && publishedIntefaces.length > 0){
|
||||
@@ -55,10 +61,18 @@ public class AbstractOSGiServiceManagingParserUtil {
|
||||
serviceBuilder.addPropertyValue("registerService", true);
|
||||
return serviceBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param beanName
|
||||
* @param filter
|
||||
* @param registry
|
||||
* @param publishedIntefaces
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static BeanDefinitionBuilder defineServiceImporterFor(String beanName, String filter,
|
||||
BeanDefinitionRegistry registry, Class... publishedIntefaces){
|
||||
Assert.notEmpty(publishedIntefaces, "At least one interface must be provided");
|
||||
BeanDefinitionBuilder serviceBuilder = BeanDefinitionBuilder.genericBeanDefinition(OsgiServiceProxyFactoryBean.class);
|
||||
serviceBuilder.addPropertyValue("cardinality", Cardinality.C_0__1);
|
||||
if (StringUtils.hasText(filter)){
|
||||
@@ -66,14 +80,34 @@ public class AbstractOSGiServiceManagingParserUtil {
|
||||
}
|
||||
if (publishedIntefaces != null && publishedIntefaces.length > 0){
|
||||
serviceBuilder.addPropertyValue("interfaces", publishedIntefaces);
|
||||
} else {
|
||||
serviceBuilder.addPropertyValue("autoExport", AutoExport.INTERFACES);
|
||||
}
|
||||
}
|
||||
serviceBuilder.addPropertyValue("serviceBeanName", beanName);
|
||||
|
||||
//TODO: pf.setTimeout(timeoutInMillis)
|
||||
|
||||
return serviceBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will define a registration listener bean definition for the exported service adding reference to the
|
||||
* to the ControlBusListeninigDecorator to it.
|
||||
*
|
||||
* @param registry
|
||||
* @param exporterBuilder
|
||||
* @param busBeanName
|
||||
* @return
|
||||
*/
|
||||
public static AbstractBeanDefinition defineRegistrationListenerForBus(BeanDefinitionRegistry registry,
|
||||
BeanDefinitionBuilder exporterBuilder,
|
||||
String busBeanName){
|
||||
BeanDefinitionBuilder listenerBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(IntegrationServiceRegistrationListener.class);
|
||||
String busGroupName = busBeanName;
|
||||
if (!registry.containsBeanDefinition(busGroupName)){
|
||||
ControlBusOSGiUtils.registerImporterForControlBus(registry, busGroupName);
|
||||
}
|
||||
listenerBuilder.addConstructorArgReference(busGroupName);
|
||||
AbstractBeanDefinition listenerDefinition = listenerBuilder.getBeanDefinition();
|
||||
exporterBuilder.addPropertyValue("listeners", listenerDefinition);
|
||||
return listenerDefinition;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
|
||||
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.controlbus.ControlBus;
|
||||
import org.springframework.intergration.osgi.OSGiIntegrationControlBus;
|
||||
import org.springframework.integration.osgi.OSGiIntegrationControlBus;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
@@ -44,7 +44,7 @@ public class BusConfigParser extends AbstractBeanDefinitionParser {
|
||||
*/
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
return beanName;
|
||||
return beanName;
|
||||
}
|
||||
/**
|
||||
*
|
||||
@@ -59,7 +59,7 @@ public class BusConfigParser extends AbstractBeanDefinitionParser {
|
||||
}
|
||||
|
||||
BeanDefinitionBuilder rootBuilder = BeanDefinitionBuilder.rootBeanDefinition(OSGiIntegrationControlBus.class);
|
||||
rootBuilder.addConstructorArgReference("controlMessagesDistributionChannel");
|
||||
rootBuilder.addConstructorArgReference(ControlBusOSGiUtils.DEFAULT_CONTROL_DIST_CHANNEL);
|
||||
rootBuilder.addConstructorArgValue(beanName);
|
||||
|
||||
BeanDefinitionBuilder osgiServiceDefinition =
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* 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.config.xml;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.BeanDefinitionStoreException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
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.xml.AbstractBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.controlbus.ControlBus;
|
||||
import org.springframework.integration.osgi.extender.IntegrationServiceRegistrationListener;
|
||||
import org.springframework.intergration.osgi.ControlBusAwarePostProcessor;
|
||||
import org.springframework.intergration.osgi.IntegrationOSGiConstants;
|
||||
import org.springframework.osgi.config.internal.adapter.OsgiServiceRegistrationListenerAdapter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser to process 'bus' element
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class BusParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
private static final Log log = LogFactory.getLog(BusConfigParser.class);
|
||||
private String busGroupName;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
|
||||
throws BeanDefinitionStoreException {
|
||||
return "controlBusPostProcessor-" + busGroupName;
|
||||
}
|
||||
/**
|
||||
* Will parse 'bus' element and its sub elements
|
||||
*/
|
||||
protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
|
||||
this.setBusGroupName(element);
|
||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
BeanDefinitionBuilder rootDefinition = BeanDefinitionBuilder.rootBeanDefinition(ControlBusAwarePostProcessor.class);
|
||||
|
||||
List<Element> producerList = DomUtils.getChildElementsByTagName(element, "manage-producer");
|
||||
//List<Element> consumerList = DomUtils.getChildElementsByTagName(element, "manage-consumer");
|
||||
|
||||
for (Element producerElement : producerList) {
|
||||
String producerName = producerElement.getAttribute("ref");
|
||||
Assert.isTrue(StringUtils.hasText(producerName), "'manage-producer' must define 'ref' attribute");
|
||||
// define service exporter
|
||||
BeanDefinitionBuilder serviceExportBuilder =
|
||||
AbstractOSGiServiceManagingParserUtil.defineServiceExporterFor(producerName, registry);
|
||||
|
||||
String registrationListenerName = this.defineRegistrationListener(registry);
|
||||
|
||||
// add listener(s) to the service exporter
|
||||
serviceExportBuilder.addPropertyReference("listeners", registrationListenerName);
|
||||
// register service exporter
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(serviceExportBuilder.getBeanDefinition(), registry);
|
||||
}
|
||||
log.trace("Managed configuration for " + busGroupName + " was parsed successfully");
|
||||
return rootDefinition.getBeanDefinition();
|
||||
}
|
||||
/**
|
||||
* Defines and registers OSGi Service Registration listener for the exported service (e.g., channel), which
|
||||
* will communicate life-cycle events of this service to the Control Bus
|
||||
*/
|
||||
private String defineRegistrationListener(BeanDefinitionRegistry registry){
|
||||
// define POJO listener
|
||||
BeanDefinitionBuilder listenerBuilder = BeanDefinitionBuilder.genericBeanDefinition(IntegrationServiceRegistrationListener.class);
|
||||
// inject Control Bus service instance into the listener
|
||||
BeanDefinition controlBusDefinition = this.registerImportedControlBusServiceDefinition(registry);
|
||||
listenerBuilder.addPropertyValue("controlBus", controlBusDefinition);
|
||||
String listenerName =
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(listenerBuilder.getBeanDefinition(), registry);
|
||||
// define listener adapter for the above listener
|
||||
BeanDefinitionBuilder listenerAdapterBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(OsgiServiceRegistrationListenerAdapter.class);
|
||||
listenerAdapterBuilder.addPropertyValue("targetBeanName", listenerName);
|
||||
listenerAdapterBuilder.addPropertyValue("registrationMethod", "register");
|
||||
listenerAdapterBuilder.addPropertyValue("unregistrationMethod", "unRegister");
|
||||
String registrationListenerName =
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(listenerAdapterBuilder.getBeanDefinition(), registry);
|
||||
return registrationListenerName;
|
||||
}
|
||||
/**
|
||||
* Will define a service importer (equivalent to <osgi:reference>) for the ControlBus service.
|
||||
*/
|
||||
private BeanDefinition registerImportedControlBusServiceDefinition(BeanDefinitionRegistry registry){
|
||||
String filter = "(&(" + IntegrationOSGiConstants.OSGI_BEAN_NAME + "=" + busGroupName + "))";
|
||||
BeanDefinitionBuilder controlBusImporterBuilder =
|
||||
AbstractOSGiServiceManagingParserUtil.defineServiceImporterFor(busGroupName, filter, registry, ControlBus.class);
|
||||
BeanDefinition controlBusImporterDefinition = controlBusImporterBuilder.getBeanDefinition();
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(controlBusImporterBuilder.getBeanDefinition(), registry);
|
||||
return controlBusImporterDefinition;
|
||||
}
|
||||
/**
|
||||
* Determines and sets the 'group-name' for the ControlBus group which will be managing this deployment
|
||||
*/
|
||||
private void setBusGroupName(Element element){
|
||||
busGroupName = element.getAttribute("group-name");
|
||||
Assert.isTrue(StringUtils.hasText(busGroupName), "bus-config 'group-name' attribute must be provided");
|
||||
log.debug("Control Bus group name: " + busGroupName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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.config.xml;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
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.xml.BeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.osgi.extender.IntegrationServiceRegistrationListener;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
/**
|
||||
* Parser to process 'config' element of SI Service Extender
|
||||
* and its sub-elements
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ConfigParser implements BeanDefinitionParser {
|
||||
private static final Log log = LogFactory.getLog(ConfigParser.class);
|
||||
private static final String TYPE = "si-type";
|
||||
private static final String REF = "ref";
|
||||
private static final String NAME = "name";
|
||||
private static final String CONTROL_BUS = "control-bus";
|
||||
private static final String EXPORTER_SUFFIX = "-Service";
|
||||
private static final int EXPORT = 1;
|
||||
private static final int IMPORT = 2;
|
||||
/**
|
||||
* Will parse 'config' element of "integration-service-extender' namespace and its sub-elements
|
||||
*/
|
||||
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||
List<Element> elements = DomUtils.getChildElementsByTagName(element, "export");
|
||||
for (Element exportElements : elements) {
|
||||
this.processExportElement(exportElements, parserContext, EXPORT);
|
||||
}
|
||||
elements = DomUtils.getChildElementsByTagName(element, "import");
|
||||
for (Element exportElements : elements) {
|
||||
this.processImportElement(exportElements, parserContext, IMPORT);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
*/
|
||||
private void processExportElement(Element element, ParserContext parserContext, int configType){
|
||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
String includeType = this.getIncludeType(element);
|
||||
Assert.notNull(includeType, "You must prvide one of the following: 'type' or 'ref' attribute wihin the 'include' element");
|
||||
if (includeType.equals(TYPE)){
|
||||
this.processTypeAttribute(element, registry, configType);
|
||||
} else if (includeType.equals(REF)){
|
||||
this.processRefAttribute(element, registry, configType);
|
||||
}
|
||||
}
|
||||
/**
|
||||
*/
|
||||
private void processImportElement(Element element, ParserContext parserContext, int configType){
|
||||
BeanDefinitionRegistry registry = parserContext.getRegistry();
|
||||
String serviceName = element.getAttribute(NAME);
|
||||
Assert.hasText(serviceName, "you must enter a valid value in the " + NAME + " attribute");
|
||||
Class[] interfaces = this.discoverInterfaces(serviceName, element);
|
||||
BeanDefinitionBuilder importerBuilder =
|
||||
AbstractOSGiServiceManagingParserUtil.defineServiceImporterFor(serviceName, null, registry, interfaces);
|
||||
registry.registerBeanDefinition(serviceName, importerBuilder.getBeanDefinition());
|
||||
}
|
||||
/**
|
||||
*/
|
||||
private void processRefAttribute(Element element, BeanDefinitionRegistry registry, int configType) {
|
||||
if (configType == EXPORT){
|
||||
String beanName = element.getAttribute(REF);
|
||||
this.generateServiceExorterDefinition(beanName, element, registry);
|
||||
} else if (configType == IMPORT){
|
||||
|
||||
}
|
||||
}
|
||||
/**
|
||||
*/
|
||||
private void processTypeAttribute(Element element, BeanDefinitionRegistry registry, int configType) {
|
||||
String exportedTypes = element.getAttribute(TYPE);
|
||||
if (configType == EXPORT){
|
||||
Element rootDocumentElement = element.getOwnerDocument().getDocumentElement();
|
||||
List<Element> elementsToExport = DomUtils.getChildElementsByTagName(rootDocumentElement, exportedTypes);
|
||||
for (Element elementToExport : elementsToExport) {
|
||||
String beanName = elementToExport.getAttribute("id");
|
||||
this.generateServiceExorterDefinition(beanName, element, registry);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
*
|
||||
*/
|
||||
private void generateServiceExorterDefinition(String beanName, Element element, BeanDefinitionRegistry registry){
|
||||
BeanDefinitionBuilder exportedElementBuilder =
|
||||
AbstractOSGiServiceManagingParserUtil.defineServiceExporterFor(beanName, registry);
|
||||
this.connectWithControlBusIfRequired(element, exportedElementBuilder, registry, beanName);
|
||||
registry.registerBeanDefinition(beanName+EXPORTER_SUFFIX, exportedElementBuilder.getBeanDefinition());
|
||||
}
|
||||
/**
|
||||
* If element specifies 'control-bus' attribute, this method will register {@link IntegrationServiceRegistrationListener}
|
||||
* which will send registration messages to the ControlBus
|
||||
*/
|
||||
private void connectWithControlBusIfRequired(Element originalElement,
|
||||
BeanDefinitionBuilder exportedElementBuilder,
|
||||
BeanDefinitionRegistry registry,
|
||||
String componentName) {
|
||||
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 =
|
||||
AbstractOSGiServiceManagingParserUtil.defineRegistrationListenerForBus(registry, exportedElementBuilder, controlBusAttributeValue);
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(listenerDefinition, registry);
|
||||
}
|
||||
}
|
||||
/**
|
||||
*/
|
||||
private String getIncludeType(Element element){
|
||||
if (element.hasAttribute(REF)){
|
||||
return REF;
|
||||
} else if (element.hasAttribute(TYPE)){
|
||||
return TYPE;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
*/
|
||||
private Class[] discoverInterfaces(String name, Element element){
|
||||
if (element.hasAttribute(TYPE)){
|
||||
return SiTypeToJavaTypeMaper.mapSiType(element.getAttribute(TYPE));
|
||||
}
|
||||
// Element documentElement = element.getOwnerDocument().getDocumentElement();
|
||||
// NodeList children = documentElement.getChildNodes();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.config.xml;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
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.integration.controlbus.ControlBus;
|
||||
import org.springframework.integration.osgi.IntegrationOSGiConstants;
|
||||
import org.springframework.integration.osgi.extender.ControlBusListeningDecorator;
|
||||
|
||||
/**
|
||||
* TODO - insert COMMENT
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ControlBusOSGiUtils {
|
||||
public final static String DEFAULT_BUS_GROUP_NAME = "DEFAULT_CONTROL_GROUP";
|
||||
public final static String DEFAULT_CONTROL_DIST_CHANNEL = "DEFAULT_CONTROL_DIST_CHANNEL";
|
||||
/**
|
||||
* Will define a service importer (equivalent to <osgi:reference>) for the ControlBus service.
|
||||
* It will also register binding listener for this 'controlbus' reference which could be used
|
||||
* to react to the life-cycle events of this 'controlbus' reference.
|
||||
* For example: Individual service reference listeners coiuld use it to determine when the bus went away and
|
||||
* no control events need to be dispatched to the bus.
|
||||
*/
|
||||
public static BeanDefinition registerImporterForControlBus(BeanDefinitionRegistry registry, String busGroupName){
|
||||
String filter = "(&(" + IntegrationOSGiConstants.OSGI_BEAN_NAME + "=" + busGroupName + "))";
|
||||
BeanDefinitionBuilder controlBusImporterBuilder =
|
||||
AbstractOSGiServiceManagingParserUtil.defineServiceImporterFor(busGroupName, filter, registry, ControlBus.class);
|
||||
|
||||
BeanDefinitionBuilder busListenerBuilder =
|
||||
BeanDefinitionBuilder.genericBeanDefinition(ControlBusListeningDecorator.class);
|
||||
AbstractBeanDefinition busListenerDefinition = busListenerBuilder.getBeanDefinition();
|
||||
//String listenerName = IntegrationOSGiConstants.BUS_LISTENER_PREFIX + busGroupName;
|
||||
String listenerName = busGroupName;
|
||||
registry.registerBeanDefinition(listenerName, busListenerDefinition);
|
||||
controlBusImporterBuilder.addPropertyReference("listeners", listenerName);
|
||||
BeanDefinition controlBusImporterDefinition = controlBusImporterBuilder.getBeanDefinition();
|
||||
BeanDefinitionReaderUtils.registerWithGeneratedName(controlBusImporterBuilder.getBeanDefinition(), registry);
|
||||
return controlBusImporterDefinition;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,6 @@ public class IntegrationOSGiControlBusNamespaceHandler extends AbstractIntegrati
|
||||
*/
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("bus-config", new BusConfigParser());
|
||||
registerBeanDefinitionParser("bus", new BusParser());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.config.xml;
|
||||
|
||||
import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHandler;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class IntegrationOSGiServiceExtenderNamespaceHandler extends AbstractIntegrationNamespaceHandler {
|
||||
|
||||
/**
|
||||
* Will register the required parsers
|
||||
*/
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("config", new ConfigParser());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.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.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
class SiTypeToJavaTypeMaper {
|
||||
public static final String PUB_SUB_CHANNEL = "publish-subscribe-channel";
|
||||
private static Map<String, Class[]> siTypeMappings = new HashMap<String, Class[]>();
|
||||
|
||||
static {
|
||||
siTypeMappings.put(PUB_SUB_CHANNEL, ClassUtils.getClassHierarchy(PublishSubscribeChannel.class, ClassUtils.INCLUDE_INTERFACES));
|
||||
}
|
||||
|
||||
public static Class[] mapSiType(String siType){
|
||||
Assert.isTrue(siTypeMappings.containsKey(siType), "Can not map SI-Type '" + siType + "' to Java Type. Not supported.");
|
||||
return siTypeMappings.get(siType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.core.Message;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
import org.springframework.osgi.service.importer.OsgiServiceLifecycleListener;
|
||||
|
||||
/**
|
||||
* Wraps OSGi Service Reference representing a {@link ControlBus} to provide several simplification
|
||||
* around life-cycle of the underlying reference.
|
||||
*
|
||||
* First, this wrapper implements {@link OsgiServiceLifecycleListener} which will listen for
|
||||
* bind/unbind events of the service reference representing a particular instance of the {@link ControlBus} service.
|
||||
* Calls to bind/unbind methods will set <code>busAvailable</code> attribute to 'true'/'false' respectively.
|
||||
* sparing you from dealing with the internals of the service reference proxy, which might be at the state where
|
||||
* it is not backed up by a concrete instance of the {@link ControlBus} service (e.g., when such service is unregistered).
|
||||
* This class also implements {@link ControlBus} interface delegating all method calls to the actual instance of the ControlBus
|
||||
* with one exception. Call to {@link ControlBus#isBusAvailable()} will return the value of the <code>busAvailable</code>
|
||||
* attribute which is set by the calls to bind/unbind methods.
|
||||
* This way you can interact with the ControlBus as if it was a real instance of the ControlBus service when it is
|
||||
* available, but it also give you a quick and convenient way to know when bus goes away.
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ControlBusListeningDecorator implements OsgiServiceLifecycleListener, ControlBus {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ControlBusListeningDecorator.class);
|
||||
private boolean busAvailable;
|
||||
private ControlBus controlBus;
|
||||
private String name;
|
||||
/*
|
||||
* (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 {
|
||||
controlBus = (ControlBus) service;
|
||||
name = controlBus.getName();
|
||||
log.debug("Binding to the Control Bus: " + name);
|
||||
busAvailable = true;
|
||||
}
|
||||
/*
|
||||
* (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 {
|
||||
log.debug("un-Binding from the Control Bus: " + name);
|
||||
busAvailable = false;
|
||||
controlBus = null;
|
||||
}
|
||||
/*
|
||||
*/
|
||||
public void setControlBus(ControlBus controlBus) {
|
||||
this.controlBus = controlBus;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.integration.controlbus.ControlBus#isBusAvailable()
|
||||
*/
|
||||
public boolean isBusAvailable() {
|
||||
return busAvailable;
|
||||
}
|
||||
/*
|
||||
*/
|
||||
public void setBusAvailable(boolean busAvailable) {
|
||||
this.busAvailable = busAvailable;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.integration.channel.SubscribableChannel#subscribe(org.springframework.integration.message.MessageHandler)
|
||||
*/
|
||||
public boolean subscribe(MessageHandler handler) {
|
||||
if (isBusAvailable()){
|
||||
return controlBus.subscribe(handler);
|
||||
} else {
|
||||
log.debug("Can not subscribe to the Control Bus: " + name + ". Control Bus is not availabel");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.integration.channel.SubscribableChannel#unsubscribe(org.springframework.integration.message.MessageHandler)
|
||||
*/
|
||||
public boolean unsubscribe(MessageHandler handler) {
|
||||
if (isBusAvailable()){
|
||||
return controlBus.unsubscribe(handler);
|
||||
} else {
|
||||
log.debug("Can not unsubscribe from the Control Bus: " + name + ". Control Bus is not availabel");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.integration.core.MessageChannel#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.integration.core.MessageChannel#send(org.springframework.integration.core.Message)
|
||||
*/
|
||||
public boolean send(Message<?> message) {
|
||||
if (isBusAvailable()){
|
||||
return controlBus.send(message);
|
||||
} else {
|
||||
log.debug("Can not send message to the Control Bus: " + name + ". Control Bus is not availabel");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.integration.core.MessageChannel#send(org.springframework.integration.core.Message, long)
|
||||
*/
|
||||
public boolean send(Message<?> message, long timeout) {
|
||||
if (isBusAvailable()){
|
||||
return controlBus.send(message, timeout);
|
||||
} else {
|
||||
log.debug("Can not send message to the Control Bus: " + name + ". Control Bus is not availabel");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ 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.osgi.service.exporter.OsgiServiceRegistrationListener;
|
||||
|
||||
/**
|
||||
* Service Registration listener which publishes registration life-cycle Messages
|
||||
@@ -29,32 +30,37 @@ import org.springframework.integration.message.StringMessage;
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class IntegrationServiceRegistrationListener {
|
||||
public class IntegrationServiceRegistrationListener implements OsgiServiceRegistrationListener {
|
||||
private static final Log log = LogFactory.getLog(IntegrationServiceRegistrationListener.class);
|
||||
private ControlBus controlBus;
|
||||
private ControlBusListeningDecorator controlBusDecorator;
|
||||
|
||||
public IntegrationServiceRegistrationListener(ControlBusListeningDecorator controlBusDecorator){
|
||||
this.controlBusDecorator = controlBusDecorator;
|
||||
}
|
||||
/**
|
||||
* Will send a notification message to the named {@link ControlBus} notifying that service
|
||||
* for an SI component was registered and is ready to be used.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void register(Object service, Map properties){
|
||||
if (controlBus != null){
|
||||
log.info("Dispatching REGISTRATION Message for: " + service + "- " + properties + " to: " + controlBus.getName());
|
||||
public void registered(Object service, Map properties){
|
||||
if (controlBusDecorator.isBusAvailable()){
|
||||
log.info("Dispatching REGISTRATION Message for: " + service + "- " + properties + " to: " +
|
||||
controlBusDecorator.getName());
|
||||
//TODO: change to structural message
|
||||
controlBus.send(new StringMessage("Dispatching REGISTRATION Message for: " + service + "- " + properties));
|
||||
controlBusDecorator.send(new StringMessage("Dispatching REGISTRATION Message for: " + service + "- " + properties));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Will send a notification message to the named {@link ControlBus} notifying that service
|
||||
* for an SI component was un-registered and can no longet be used.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void unRegister(Object service, Map properties){
|
||||
if (controlBus != null){
|
||||
log.info("Dispatching UN-REGISTRATION Message for: " + service + "- " + properties + " to: " + controlBus.getName());
|
||||
public void unregistered(Object service, Map properties){
|
||||
if (controlBusDecorator.isBusAvailable()){
|
||||
log.info("Dispatching UN-REGISTRATION Message for: " + service + "- " + properties + " to: " +
|
||||
controlBusDecorator.getName());
|
||||
//TODO: change to structural message
|
||||
controlBus.send(new StringMessage("Dispatching UN-REGISTRATION Message for: " + service + "- " + properties));
|
||||
controlBusDecorator.send(new StringMessage("Dispatching UN-REGISTRATION Message for: " + service + "- " + properties));
|
||||
}
|
||||
}
|
||||
//
|
||||
public ControlBus getControlBus() {
|
||||
return controlBus;
|
||||
}
|
||||
//
|
||||
public void setControlBus(ControlBus controlBus) {
|
||||
this.controlBus = controlBus;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
http\://www.springframework.org/schema/integration/integration-control-bus=org.springframework.integration.osgi.config.xml.IntegrationOSGiControlBusNamespaceHandler
|
||||
http\://www.springframework.org/schema/integration/integration-control-bus=org.springframework.integration.osgi.config.xml.IntegrationOSGiControlBusNamespaceHandler
|
||||
http\://www.springframework.org/schema/integration/integration-service-extender=org.springframework.integration.osgi.config.xml.IntegrationOSGiServiceExtenderNamespaceHandler
|
||||
@@ -1 +1,3 @@
|
||||
http\://www.springframework.org/schema/integration/integration-control-bus/spring-integration-bus-1.0.xsd=org/springframework/integration/osgi/config/xml/spring-integration-bus-1.0.xsd
|
||||
http\://www.springframework.org/schema/integration/integration-service-extender/spring-integration-service-extender-1.0.xsd=org/springframework/integration/osgi/config/xml/spring-integration-service-extender-1.0.xsd
|
||||
|
||||
|
||||
@@ -30,32 +30,4 @@
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="bus">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Configures all required interactions with the named Control Bus configuration
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:choice>
|
||||
<xsd:element name="manage-subscriber" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="ref" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="manage-producer" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="ref" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
<xsd:attribute name="group-name" type="xsd:string" default="DEFAULT_CONTROL_GROUP">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Identifies group-name of a Control Bus this configuration defines
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
@@ -0,0 +1,104 @@
|
||||
<xsd:schema
|
||||
xmlns="http://www.springframework.org/schema/integration/integration-service-extender"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:tool="http://www.springframework.org/schema/tool"
|
||||
targetNamespace="http://www.springframework.org/schema/integration/integration-service-extender"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
<xsd:import namespace="http://www.springframework.org/schema/beans" />
|
||||
<xsd:import namespace="http://www.springframework.org/schema/tool" />
|
||||
|
||||
<xsd:element name="config">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Configures SI Service Extender, which configures
|
||||
existing beans as SI Services.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:choice>
|
||||
<xsd:element name="export" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="siTypes">
|
||||
<xsd:attribute name="ref" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Identifies the name of the 'bean' to be
|
||||
exported as an SI Service. Framework will find bean matching
|
||||
this name and export it as an SI Service.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="import" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="siTypes">
|
||||
<xsd:attribute name="name" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Identifies the name of the 'bean' to be
|
||||
imported as an SI Service.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<!-- -->
|
||||
<xsd:complexType name="siTypes">
|
||||
<xsd:attribute name="si-type">
|
||||
<xsd:simpleType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>Identifies the supported type of Spring
|
||||
Integration components to be
|
||||
exported as SI Services. Framework
|
||||
will find all components of matching type and export them as
|
||||
SI
|
||||
Services.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:restriction base="xsd:string">
|
||||
<xsd:enumeration value="publish-subscribe-channel">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Will export all components of type
|
||||
<publish-subscribe-channel> as SI Services
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
<xsd:enumeration value="channel">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Will export all components of type
|
||||
<channel> as SI Services
|
||||
s</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:enumeration>
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="control-bus" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>Identifies the name of the 'control-bus'
|
||||
which
|
||||
will manage this component. This
|
||||
means that framework will
|
||||
dispatch
|
||||
control events to the identified
|
||||
'control-bus'.
|
||||
(OPTIONAL if no
|
||||
control is necessary)
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:schema>
|
||||
@@ -24,8 +24,8 @@ import org.osgi.framework.ServiceReference;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.integration.controlbus.ControlBus;
|
||||
import org.springframework.integration.osgi.AbstractSIConfigBundleTestDeployer;
|
||||
import org.springframework.integration.osgi.IntegrationOSGiConstants;
|
||||
import org.springframework.integration.osgi.stubs.SIBundleContextStub;
|
||||
import org.springframework.intergration.osgi.IntegrationOSGiConstants;
|
||||
|
||||
|
||||
/**
|
||||
@@ -40,12 +40,11 @@ public class BusConfigParserTests extends AbstractSIConfigBundleTestDeployer {
|
||||
ApplicationContext ac = this.deploySIConfig(bundleContext,
|
||||
"org/springframework/integration/osgi/config/xml/",
|
||||
"BusConfigParserTests-default.xml");
|
||||
ControlBus controlBus = (ControlBus) ac.getBean(IntegrationOSGiConstants.DEFAULT_BUS_GROUP_NAME);
|
||||
ControlBus controlBus = (ControlBus) ac.getBean(ControlBusOSGiUtils.DEFAULT_BUS_GROUP_NAME);
|
||||
assertNotNull(controlBus);
|
||||
assertTrue(controlBus.getBusName().equals(IntegrationOSGiConstants.DEFAULT_BUS_GROUP_NAME));
|
||||
ServiceReference[] sr = bundleContext.getServiceReferences(ControlBus.class.getName(),
|
||||
"(&(" + IntegrationOSGiConstants.OSGI_BEAN_NAME + "=" +
|
||||
IntegrationOSGiConstants.DEFAULT_BUS_GROUP_NAME + "))");
|
||||
ControlBusOSGiUtils.DEFAULT_BUS_GROUP_NAME + "))");
|
||||
assertNotNull(sr);
|
||||
assertTrue(sr.length == 1);
|
||||
controlBus = (ControlBus) bundleContext.getService(sr[0]);
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.springframework.integration.osgi.AbstractSIConfigBundleTestDeployer;
|
||||
import org.springframework.integration.osgi.stubs.SIBundleContextStub;
|
||||
|
||||
/**
|
||||
* THis test bootstraps two instances of the Control Bus, then shuts down one demonstrating and testing
|
||||
* This test bootstraps two instances of the Control Bus, then shuts down one demonstrating and testing
|
||||
* transparent fail-over to another instance of the Control Bus
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
@@ -38,8 +38,9 @@ import org.springframework.integration.osgi.stubs.SIBundleContextStub;
|
||||
public class BusUsageFailoverTests extends AbstractSIConfigBundleTestDeployer {
|
||||
static MessageHandler handler = Mockito.mock(MessageHandler.class);
|
||||
|
||||
|
||||
@Test
|
||||
public void testDefaultControlBusConfig() throws Exception {
|
||||
public void testControlBusFailover() throws Exception {
|
||||
BundleContext bundleContext = SIBundleContextStub.getInstance();
|
||||
|
||||
ConfigurableApplicationContext primaryAc = this.deploySIConfig(bundleContext,
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:si-service="http://www.springframework.org/schema/integration/integration-service-extender"
|
||||
xmlns:si-control="http://www.springframework.org/schema/integration/integration-control-bus"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:osgi="http://www.springframework.org/schema/osgi"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration/integration-control-bus http://www.springframework.org/schema/integration/integration-control-bus/spring-integration-bus-1.0.xsd
|
||||
http://www.springframework.org/schema/integration/integration-service-extender http://www.springframework.org/schema/integration/integration-service-extender/spring-integration-service-extender-1.0.xsd
|
||||
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-1.2.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd">
|
||||
|
||||
<si:publish-subscribe-channel id="channelA"/>
|
||||
<si:publish-subscribe-channel id="channelB"/>
|
||||
|
||||
<si:channel id="channelC"/>
|
||||
|
||||
<si-service:config>
|
||||
<si-service:export si-type="publish-subscribe-channel"/>
|
||||
<si-service:export ref="channelC"/>
|
||||
</si-service:config>
|
||||
|
||||
<osgi:reference id="channelA-reference" interface="org.springframework.integration.channel.SubscribableChannel"/>
|
||||
</beans>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:si-service="http://www.springframework.org/schema/integration/integration-service-extender"
|
||||
xmlns:si-control="http://www.springframework.org/schema/integration/integration-control-bus"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:osgi="http://www.springframework.org/schema/osgi"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration/integration-control-bus http://www.springframework.org/schema/integration/integration-control-bus/spring-integration-bus-1.0.xsd
|
||||
http://www.springframework.org/schema/integration/integration-service-extender http://www.springframework.org/schema/integration/integration-service-extender/spring-integration-service-extender-1.0.xsd
|
||||
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-1.2.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd">
|
||||
|
||||
<si:publish-subscribe-channel id="channelA"/>
|
||||
<si:publish-subscribe-channel id="channelB"/>
|
||||
|
||||
<si:channel id="channelC"/>
|
||||
|
||||
<si-service:config>
|
||||
<si-service:export si-type="publish-subscribe-channel" control-bus="DEFAULT_CONTROL_GROUP"/>
|
||||
<si-service:export ref="channelC" control-bus="DEFAULT_CONTROL_GROUP"/>
|
||||
</si-service:config>
|
||||
</beans>
|
||||
|
||||
|
||||
<!-- <si-service:import name="foo"/>-->
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.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;
|
||||
|
||||
/**
|
||||
* Tests 'config' element.
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ConfigParserExporterTests extends AbstractSIConfigBundleTestDeployer {
|
||||
|
||||
@Test
|
||||
public void testBasicSIServiceConfig() throws Exception {
|
||||
BundleContext bundleContext = SIBundleContextStub.getNewInstance();
|
||||
ApplicationContext ac = this.deploySIConfig(bundleContext,
|
||||
"org/springframework/integration/osgi/config/xml/",
|
||||
"ConfigParserExporterTests-default.xml");
|
||||
assertNotNull(ac.getBean("channelA-Service"));
|
||||
assertNotNull(ac.getBean("channelB-Service"));
|
||||
assertNotNull(ac.getBean("channelC-Service"));
|
||||
|
||||
SubscribableChannel channel = (SubscribableChannel) ac.getBean("channelA");
|
||||
SubscribableChannel channel_reference = ac.getBean("channelA-reference", SubscribableChannel.class);
|
||||
// verify that standar OSGi configuration can still bind to this service
|
||||
MessageHandler handler = Mockito.mock(MessageHandler.class);
|
||||
channel_reference.subscribe(handler);
|
||||
Message<String> message = new StringMessage("hello");
|
||||
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 ac = this.deploySIConfig(bundleContext,
|
||||
"org/springframework/integration/osgi/config/xml/",
|
||||
"ConfigParserExporterTests-withbus-attribute.xml");
|
||||
assertNotNull(ac.getBean("channelA-Service"));
|
||||
assertNotNull(ac.getBean("channelB-Service"));
|
||||
assertNotNull(ac.getBean("channelC-Service"));
|
||||
ControlBus bus = (ControlBus) ac.getBean("DEFAULT_CONTROL_GROUP");
|
||||
assertNotNull(bus);
|
||||
MessageHandler handler = Mockito.mock(MessageHandler.class);
|
||||
bus.subscribe(handler);
|
||||
ac.close();
|
||||
// should be 3 notification messages sent to the bus
|
||||
Mockito.verify(handler, Mockito.times(3)).handleMessage((Message<?>) Mockito.any());
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:si-control="http://www.springframework.org/schema/integration/integration-control-bus"
|
||||
xmlns:si-service="http://www.springframework.org/schema/integration/integration-service-extender"
|
||||
xmlns:si="http://www.springframework.org/schema/integration"
|
||||
xmlns:osgi="http://www.springframework.org/schema/osgi"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration/integration-control-bus http://www.springframework.org/schema/integration/integration-control-bus/spring-integration-bus-1.0.xsd
|
||||
http://www.springframework.org/schema/integration/integration-service-extender http://www.springframework.org/schema/integration/integration-service-extender/spring-integration-service-extender-1.0.xsd
|
||||
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-1.2.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd">
|
||||
|
||||
<si-control:bus group-name="DEFAULT_CONTROL_GROUP" >
|
||||
<si-control:manage-producer ref="exportedChannel"/>
|
||||
</si-control:bus>
|
||||
|
||||
<si:publish-subscribe-channel id="exportedChannel"/>
|
||||
<si-service:config>
|
||||
<si-service:import name="channelA" si-type="publish-subscribe-channel"/>
|
||||
</si-service:config>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.config.xml;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.integration.osgi.AbstractSIConfigBundleTestDeployer;
|
||||
import org.springframework.integration.osgi.stubs.SIBundleContextStub;
|
||||
|
||||
/**
|
||||
* Tests 'config' element.
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ConfigParserImporterTests extends AbstractSIConfigBundleTestDeployer {
|
||||
|
||||
@Test
|
||||
public void testBasicSIServiceConfig() throws Exception {
|
||||
BundleContext bundleContext = SIBundleContextStub.getNewInstance();
|
||||
ApplicationContext ac = this.deploySIConfig(bundleContext,
|
||||
"org/springframework/integration/osgi/config/xml/",
|
||||
"ConfigParserImporterTests-default.xml");
|
||||
assertNotNull(ac.getBean("channelA"));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
<!-- END SERVICE BINDING CONFIG-->
|
||||
|
||||
<!-- CONTROL BUS channel, exposed as an OSGi service -->
|
||||
<si:publish-subscribe-channel id="controlMessagesDistributionChannel"/>
|
||||
<si:publish-subscribe-channel id="DEFAULT_CONTROL_DIST_CHANNEL"/>
|
||||
<!-- END CONTROL BUS channel, exposed as an OSGi service -->
|
||||
|
||||
<si:header-value-router input-channel="controlMessagesDistributionChannel" header-name="INTEGRATION_EVENT_TYPE">
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* 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 static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
import org.omg.CORBA.MARSHAL;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.integration.channel.PublishSubscribeChannel;
|
||||
import org.springframework.integration.controlbus.ControlBus;
|
||||
import org.springframework.integration.osgi.AbstractSIConfigBundleTestDeployer;
|
||||
import org.springframework.integration.osgi.stubs.SIBundleContextStub;
|
||||
import org.springframework.osgi.config.internal.adapter.OsgiServiceRegistrationListenerAdapter;
|
||||
import org.springframework.osgi.mock.MockServiceReference;
|
||||
import org.springframework.osgi.service.exporter.OsgiServiceRegistrationListener;
|
||||
import org.springframework.osgi.service.exporter.support.OsgiServiceFactoryBean;
|
||||
import org.springframework.osgi.util.OsgiServiceUtils;
|
||||
|
||||
/**
|
||||
* TODO - insert COMMENT
|
||||
* @author Oleg Zhurakousky
|
||||
* @since 2.0
|
||||
*/
|
||||
public class BusParserProducersTests extends AbstractSIConfigBundleTestDeployer {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testBusWithSubscribersBusPresent() throws Exception {
|
||||
SIBundleContextStub bundleContext = SIBundleContextStub.getInstance();
|
||||
this.deploySIConfig(bundleContext,
|
||||
"org/springframework/integration/osgi/config/xml/",
|
||||
"BusConfigParserTests-default.xml");
|
||||
ApplicationContext ac = this.deploySIConfig(bundleContext,
|
||||
"org/springframework/integration/osgi/extender/",
|
||||
"BusParserProducersTests.xml");
|
||||
Map beans = ac.getBeansOfType(OsgiServiceFactoryBean.class);
|
||||
assertTrue(beans.size() == 1);
|
||||
OsgiServiceFactoryBean serviceExporter = (OsgiServiceFactoryBean) beans.values().toArray()[0];
|
||||
assertTrue(serviceExporter.getTargetBeanName().equals("exportedChannel"));
|
||||
DirectFieldAccessor serviceExporterAccessor = new DirectFieldAccessor(serviceExporter);
|
||||
OsgiServiceRegistrationListener[] listeners =
|
||||
(OsgiServiceRegistrationListener[]) serviceExporterAccessor.getPropertyValue("listeners");
|
||||
assertTrue(listeners.length == 1);
|
||||
|
||||
ServiceReference sr =
|
||||
bundleContext.getServiceReferences(null, "(&(org.springframework.osgi.bean.name=exportedChannel))")[0];
|
||||
assertNotNull(sr);
|
||||
}
|
||||
@Test
|
||||
public void testBusWithSubscribersBusNotPresent() throws Exception {
|
||||
SIBundleContextStub bundleContext = SIBundleContextStub.getInstance();
|
||||
this.deploySIConfig(bundleContext,
|
||||
"org/springframework/integration/osgi/extender/",
|
||||
"BusParserProducersTests.xml");
|
||||
assertTrue(true); // if exception was not thrown we are ok
|
||||
}
|
||||
}
|
||||
@@ -181,4 +181,9 @@ public class SIBundleContextStub extends MockBundleContext {
|
||||
public Map<ServiceReference, Object> getServices() {
|
||||
return services;
|
||||
}
|
||||
|
||||
public void remove(ServiceReference sr){
|
||||
services.remove(sr);
|
||||
serviceReferences.remove(sr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,15 +38,15 @@ public class SIServiceRegistrationStub extends MockServiceRegistration {
|
||||
public void setBundleContext(SIBundleContextStub context){
|
||||
this.context = context;
|
||||
}
|
||||
// public void unregister() {
|
||||
// ServiceReference ref = this.getReference();
|
||||
// DirectFieldAccessor refAccessor = new DirectFieldAccessor(ref);
|
||||
// Dictionary properties = (Dictionary) refAccessor.getPropertyValue("properties");
|
||||
//
|
||||
// context.removeService(this.getReference());
|
||||
// Set<ServiceListener> listeners = context.getFilteredListeners(properties);
|
||||
// for (ServiceListener serviceListener : listeners) {
|
||||
// serviceListener.serviceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING, ref));
|
||||
// }
|
||||
// }
|
||||
public void unregister() {
|
||||
ServiceReference ref = this.getReference();
|
||||
DirectFieldAccessor refAccessor = new DirectFieldAccessor(ref);
|
||||
Dictionary properties = (Dictionary) refAccessor.getPropertyValue("properties");
|
||||
|
||||
context.remove(this.getReference());
|
||||
Set<ServiceListener> listeners = context.getFilteredListeners(properties);
|
||||
for (ServiceListener serviceListener : listeners) {
|
||||
serviceListener.serviceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING, ref));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.integration.osgi">
|
||||
<level value="debug" />
|
||||
<level value="trace" />
|
||||
</logger>
|
||||
|
||||
<!-- Root Logger -->
|
||||
|
||||
Reference in New Issue
Block a user