From c7bfd2b214f6890106b24bd9b110648c7fbde836 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Wed, 25 May 2011 18:25:34 +0200 Subject: [PATCH] #510 - Added Spring Integration dynamic service activator based on PluginRegistry. See the ticket or test config file for usage. --- org.synyx.hera.si/.springBeans | 13 ++ org.synyx.hera.si/pom.xml | 58 +++++ .../si/PluginRegistryAwareMessageHandler.java | 204 ++++++++++++++++++ .../config/DynamicServiceActivatorParser.java | 87 ++++++++ ...HeraSpringIntegrationNamespaceHandler.java | 36 ++++ .../main/resources/META-INF/spring.handlers | 1 + .../main/resources/META-INF/spring.schemas | 1 + .../main/resources/META-INF/spring.tooling | 4 + .../org/synyx/hera/si/config/hera-si.xsd | 64 ++++++ ...inRegistryAwareMessageHandlerUnitTest.java | 58 +++++ ...viceActivatorNamespaceIntegrationTest.java | 47 ++++ .../hera/si/sample/FirstSamplePluginImpl.java | 22 ++ .../synyx/hera/si/sample/SamplePlugin.java | 12 ++ .../si/sample/SecondSamplePluginImpl.java | 22 ++ ...dynamic-service-activator-test-context.xml | 25 +++ org.synyx.hera.si/template.mf | 13 ++ pom.xml | 1 + 17 files changed, 668 insertions(+) create mode 100644 org.synyx.hera.si/.springBeans create mode 100644 org.synyx.hera.si/pom.xml create mode 100644 org.synyx.hera.si/src/main/java/org/synyx/hera/si/PluginRegistryAwareMessageHandler.java create mode 100644 org.synyx.hera.si/src/main/java/org/synyx/hera/si/config/DynamicServiceActivatorParser.java create mode 100644 org.synyx.hera.si/src/main/java/org/synyx/hera/si/config/HeraSpringIntegrationNamespaceHandler.java create mode 100644 org.synyx.hera.si/src/main/resources/META-INF/spring.handlers create mode 100644 org.synyx.hera.si/src/main/resources/META-INF/spring.schemas create mode 100644 org.synyx.hera.si/src/main/resources/META-INF/spring.tooling create mode 100644 org.synyx.hera.si/src/main/resources/org/synyx/hera/si/config/hera-si.xsd create mode 100644 org.synyx.hera.si/src/test/java/org/synyx/hera/si/PluginRegistryAwareMessageHandlerUnitTest.java create mode 100644 org.synyx.hera.si/src/test/java/org/synyx/hera/si/config/DynamicServiceActivatorNamespaceIntegrationTest.java create mode 100644 org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/FirstSamplePluginImpl.java create mode 100644 org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/SamplePlugin.java create mode 100644 org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/SecondSamplePluginImpl.java create mode 100644 org.synyx.hera.si/src/test/resources/dynamic-service-activator-test-context.xml create mode 100644 org.synyx.hera.si/template.mf diff --git a/org.synyx.hera.si/.springBeans b/org.synyx.hera.si/.springBeans new file mode 100644 index 0000000..85a42a9 --- /dev/null +++ b/org.synyx.hera.si/.springBeans @@ -0,0 +1,13 @@ + + + 1 + + + + + + + + + + diff --git a/org.synyx.hera.si/pom.xml b/org.synyx.hera.si/pom.xml new file mode 100644 index 0000000..de4385a --- /dev/null +++ b/org.synyx.hera.si/pom.xml @@ -0,0 +1,58 @@ + + 4.0.0 + + org.synyx.hera + org.synyx.hera + 0.7.0.BUILD-SNAPSHOT + + org.synyx.hera + org.synyx.hera.si + 0.7.0.BUILD-SNAPSHOT + Hera Spring Integration integration + + + 2.0.3.RELEASE + 3.0.5.RELEASE + + + + + ${project.groupId} + org.synyx.hera.core + ${project.version} + + + + org.springframework.integration + spring-integration-core + ${spring.integration.version} + + + + org.springframework + spring-context + ${spring.version} + + + + org.springframework + spring-beans + ${spring.version} + + + + org.springframework + spring-context + ${spring.version} + + + + org.springframework + spring-test + ${spring.version} + test + + + + \ No newline at end of file diff --git a/org.synyx.hera.si/src/main/java/org/synyx/hera/si/PluginRegistryAwareMessageHandler.java b/org.synyx.hera.si/src/main/java/org/synyx/hera/si/PluginRegistryAwareMessageHandler.java new file mode 100644 index 0000000..91c8810 --- /dev/null +++ b/org.synyx.hera.si/src/main/java/org/synyx/hera/si/PluginRegistryAwareMessageHandler.java @@ -0,0 +1,204 @@ +/* + * Copyright 2011 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.synyx.hera.si; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.springframework.core.GenericTypeResolver; +import org.springframework.expression.Expression; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.integration.Message; +import org.springframework.integration.MessageHandlingException; +import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; +import org.springframework.util.Assert; +import org.springframework.util.ObjectUtils; +import org.springframework.util.ReflectionUtils; +import org.synyx.hera.core.Plugin; +import org.synyx.hera.core.PluginRegistry; + +/** + * Dynamic service activator that uses a {@link PluginRegistry} to delegate execution to one or more plugins matching a + * delimiter. + * + * @author Oliver Gierke + */ +public class PluginRegistryAwareMessageHandler extends AbstractReplyProducingMessageHandler { + + private enum InvocationMethod { + ONE, ALL; + } + + private final PluginRegistry, Object> registry; + private final Class> pluginType; + private final Class delimitzerType; + private final SpelExpressionParser parser = new SpelExpressionParser(); + + private Expression delimiterExpression; + private Expression invocationArgumentsExpression; + private String serviceMethodName; + private InvocationMethod invocationMethod = InvocationMethod.ONE; + + /** + * Creates a new {@link PluginRegistryAwareMessageHandler} for the given {@link PluginRegistry}, pluginType and a + * method name to call. + * + * @param registry + * @param pluginType + * @param serviceMethodName + */ + @SuppressWarnings("unchecked") + public PluginRegistryAwareMessageHandler(PluginRegistry, ?> registry, + Class> pluginType, String serviceMethodName) { + + Assert.notNull(registry); + Assert.notNull(pluginType); + Assert.hasText(serviceMethodName); + + this.registry = (PluginRegistry, Object>) registry; + this.serviceMethodName = serviceMethodName; + this.pluginType = pluginType; + this.delimitzerType = GenericTypeResolver.resolveTypeArgument(pluginType, Plugin.class); + } + + /** + * Sets the SpEL expression to extract the delimiter from the {@link Message}. + * + * @param delimiterExpression the delimiterExpression to set + */ + public void setDelimiterExpression(String expression) { + Assert.hasText(expression); + this.delimiterExpression = parser.parseExpression(expression); + } + + /** + * Sets the SpEL expression to extract the method arguments for the actual plugin method invocation from the + * {@link Message}. + * + * @param invocationArgumentsExpression the invocationArgumentsExpression to set + */ + public void setInvocationArgumentsExpression(String expression) { + Assert.hasText(expression); + this.invocationArgumentsExpression = parser.parseExpression(expression); + } + + /* + * (non-Javadoc) + * @see org.springframework.integration.handler.AbstractReplyProducingMessageHandler#handleRequestMessage(org.springframework.integration.Message) + */ + @SuppressWarnings("unchecked") + @Override + protected Object handleRequestMessage(Message requestMessage) { + + Object delimiter = getDelimiter(requestMessage); + + switch (invocationMethod) { + case ALL: + return invokePlugins(registry.getPluginsFor(delimiter), requestMessage); + case ONE: + default: + List results = invokePlugins(Arrays.asList(registry.getPluginFor(delimiter)), requestMessage); + return results.isEmpty() ? null : results.get(0); + } + } + + private List invokePlugins(Iterable> plugins, Message message) { + List results = new ArrayList(); + + for (Plugin plugin : plugins) { + + Object[] invocationArguments = getInvocationArguments(message); + Class[] types = getTypes(invocationArguments); + + Method businessMethod = ReflectionUtils.findMethod(pluginType, serviceMethodName, types); + + if (businessMethod == null) { + throw new MessageHandlingException(message, String.format( + "Did not find a method %s on %s taking the following parameters %s", serviceMethodName, + pluginType.getName(), Arrays.toString(types))); + } + + Object result = ReflectionUtils.invokeMethod(businessMethod, plugin, invocationArguments); + + if (!businessMethod.getReturnType().equals(void.class)) { + results.add(result); + } + } + + return results; + } + + /** + * Returns the delimiter object to be used for the given {@link Message}. Will use the configured delimiter expression + * if configured. + * + * @param message + * @return + */ + private Object getDelimiter(Message message) { + + Object delimiter = message; + + if (delimiterExpression != null) { + StandardEvaluationContext context = new StandardEvaluationContext(message); + delimiter = delimiterExpression.getValue(context); + } + + Assert.isInstanceOf(delimitzerType, delimiter, String.format("Delimiter expression did " + + "not return a suitable delimiter! Make sure the expression evaluates to a suitable " + + "type! Got %s but need %s", delimiter.getClass(), delimitzerType)); + + return delimiter; + } + + /** + * Returns the actual arguments to be used for the plugin method invocation. Will apply the configured invocation + * argument expression to the given {@link Message}. + * + * @param message + * @return + */ + private Object[] getInvocationArguments(Message message) { + + if (invocationArgumentsExpression == null) { + return new Object[] { message }; + } + + StandardEvaluationContext context = new StandardEvaluationContext(message); + Object result = delimiterExpression.getValue(context); + + return ObjectUtils.isArray(result) ? ObjectUtils.toObjectArray(result) : new Object[] { result }; + } + + /** + * Returns an array of types for the given objects. Inspects each element of the array for its type. will return + * {@literal null} for {@literal null} source values. + * + * @param source + * @return + */ + private Class[] getTypes(Object[] source) { + Class[] result = new Class[source.length]; + for (int i = 0; i < source.length; i++) { + Object sourceElement = source[i]; + result[i] = sourceElement == null ? null : sourceElement.getClass(); + } + return result; + } +} diff --git a/org.synyx.hera.si/src/main/java/org/synyx/hera/si/config/DynamicServiceActivatorParser.java b/org.synyx.hera.si/src/main/java/org/synyx/hera/si/config/DynamicServiceActivatorParser.java new file mode 100644 index 0000000..1e2290d --- /dev/null +++ b/org.synyx.hera.si/src/main/java/org/synyx/hera/si/config/DynamicServiceActivatorParser.java @@ -0,0 +1,87 @@ +/* + * Copyright 2011 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.synyx.hera.si.config; + +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.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.config.xml.AbstractConsumerEndpointParser; +import org.springframework.util.StringUtils; +import org.synyx.hera.core.support.PluginRegistryFactoryBean; +import org.synyx.hera.si.PluginRegistryAwareMessageHandler; +import org.w3c.dom.Element; + +/** + * {@link BeanDefinitionParser} to create {@link PluginRegistryAwareMessageHandler} beans. + * + * @author Oliver Gierke + */ +public class DynamicServiceActivatorParser extends AbstractConsumerEndpointParser { + + /* + * (non-Javadoc) + * @see org.springframework.integration.config.xml.AbstractConsumerEndpointParser#parseHandler(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext) + */ + @Override + protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) { + + Object source = parserContext.extractSource(element); + + String pluginType = element.getAttribute("plugin-type"); + String method = element.getAttribute("method"); + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(PluginRegistryAwareMessageHandler.class); + builder.addConstructorArgValue(getRegistryBeanDefinition(pluginType, source)); + builder.addConstructorArgValue(pluginType); + builder.addConstructorArgValue(method); + + String delimiter = element.getAttribute("delimiter"); + + if (StringUtils.hasText(delimiter)) { + builder.addPropertyValue("delimiterExpression", delimiter); + } + + String invocationArguments = element.getAttribute("invocation-arguments"); + + if (StringUtils.hasText(invocationArguments)) { + builder.addPropertyValue("invocationArgumentsExpression", invocationArguments); + } + + AbstractBeanDefinition definition = builder.getBeanDefinition(); + definition.setSource(source); + + return builder; + } + + /** + * Creates a {@link BeanDefinition} for a {@link PluginRegistryFactoryBean}. + * + * @param pluginType + * @param source + * @return + */ + private AbstractBeanDefinition getRegistryBeanDefinition(String pluginType, Object source) { + + BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(PluginRegistryFactoryBean.class); + builder.addPropertyValue("type", pluginType); + + AbstractBeanDefinition definition = builder.getBeanDefinition(); + definition.setSource(source); + return definition; + } +} diff --git a/org.synyx.hera.si/src/main/java/org/synyx/hera/si/config/HeraSpringIntegrationNamespaceHandler.java b/org.synyx.hera.si/src/main/java/org/synyx/hera/si/config/HeraSpringIntegrationNamespaceHandler.java new file mode 100644 index 0000000..d417da3 --- /dev/null +++ b/org.synyx.hera.si/src/main/java/org/synyx/hera/si/config/HeraSpringIntegrationNamespaceHandler.java @@ -0,0 +1,36 @@ +/* + * Copyright 2011 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.synyx.hera.si.config; + +import org.springframework.beans.factory.xml.BeanDefinitionParser; +import org.springframework.beans.factory.xml.NamespaceHandler; +import org.springframework.beans.factory.xml.NamespaceHandlerSupport; + +/** + * {@link NamespaceHandler} to register {@link BeanDefinitionParser}s. + * + * @author Oliver Gierke + */ +public class HeraSpringIntegrationNamespaceHandler extends NamespaceHandlerSupport { + + /* + * (non-Javadoc) + * @see org.springframework.beans.factory.xml.NamespaceHandler#init() + */ + public void init() { + registerBeanDefinitionParser("dynamic-service-activator", new DynamicServiceActivatorParser()); + } +} diff --git a/org.synyx.hera.si/src/main/resources/META-INF/spring.handlers b/org.synyx.hera.si/src/main/resources/META-INF/spring.handlers new file mode 100644 index 0000000..3c33371 --- /dev/null +++ b/org.synyx.hera.si/src/main/resources/META-INF/spring.handlers @@ -0,0 +1 @@ +http\://schemas.synyx.org/hera/si=org.synyx.hera.si.config.HeraSpringIntegrationNamespaceHandler \ No newline at end of file diff --git a/org.synyx.hera.si/src/main/resources/META-INF/spring.schemas b/org.synyx.hera.si/src/main/resources/META-INF/spring.schemas new file mode 100644 index 0000000..240da0b --- /dev/null +++ b/org.synyx.hera.si/src/main/resources/META-INF/spring.schemas @@ -0,0 +1 @@ +http\://schemas.synyx.org/hera/si/hera-si.xsd=org/synyx/hera/si/config/hera-si.xsd \ No newline at end of file diff --git a/org.synyx.hera.si/src/main/resources/META-INF/spring.tooling b/org.synyx.hera.si/src/main/resources/META-INF/spring.tooling new file mode 100644 index 0000000..8fa3d6e --- /dev/null +++ b/org.synyx.hera.si/src/main/resources/META-INF/spring.tooling @@ -0,0 +1,4 @@ +# Tooling related information for the Hera namespace +http\://schemas.synyx.org/hera/si@name=Hera Spring Integration Namespace +http\://schemas.synyx.org/hera/si@prefix=int-hera +http\://schemas.synyx.org/hera/si@icon=org/springframework/beans/factory/xml/spring-beans.gif \ No newline at end of file diff --git a/org.synyx.hera.si/src/main/resources/org/synyx/hera/si/config/hera-si.xsd b/org.synyx.hera.si/src/main/resources/org/synyx/hera/si/config/hera-si.xsd new file mode 100644 index 0000000..fc70ee8 --- /dev/null +++ b/org.synyx.hera.si/src/main/resources/org/synyx/hera/si/config/hera-si.xsd @@ -0,0 +1,64 @@ + + + + + + + + + + This service activator will be backed by a Hera Plugin registry that + allows dynamic invocation of Spring beans implementing the plugin + interface defined in "plugin-type". We will dynamically pick up all + Spring beans implementing that interface and create a PluginRegistry + of those. See org.synyx.hera.si.PluginRegistryAwareMessageHandler for + details. + + + + + + + The input channel to listen to. + + + + + The type of Spring beans to dynamically pick up. + + + + + The method to be invoked on the plugin(s) selected. + + + + + The output channel to publish invocation results to. + + + + + + A SpEL expression to extract the delimiter to be used from the + incoming Message. If not set the entire Message will be used as + delimiter. + + + + + + + A SpEL expression to extract the arguments for the actual method + invocation. + + + + + + + \ No newline at end of file diff --git a/org.synyx.hera.si/src/test/java/org/synyx/hera/si/PluginRegistryAwareMessageHandlerUnitTest.java b/org.synyx.hera.si/src/test/java/org/synyx/hera/si/PluginRegistryAwareMessageHandlerUnitTest.java new file mode 100644 index 0000000..adfcc00 --- /dev/null +++ b/org.synyx.hera.si/src/test/java/org/synyx/hera/si/PluginRegistryAwareMessageHandlerUnitTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2011 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.synyx.hera.si; + +import java.util.Arrays; + +import org.junit.Test; +import org.springframework.integration.Message; +import org.springframework.integration.MessageHandlingException; +import org.springframework.integration.support.MessageBuilder; +import org.synyx.hera.core.OrderAwarePluginRegistry; +import org.synyx.hera.core.PluginRegistry; +import org.synyx.hera.si.sample.FirstSamplePluginImpl; +import org.synyx.hera.si.sample.SamplePlugin; +import org.synyx.hera.si.sample.SecondSamplePluginImpl; + +/** + * Unit tests for {@link PluginRegistryAwareMessageHandler}. + * + * @author Oliver Gierke + */ +public class PluginRegistryAwareMessageHandlerUnitTest { + + PluginRegistry registry = OrderAwarePluginRegistry.create(Arrays.asList( + new FirstSamplePluginImpl(), new SecondSamplePluginImpl())); + PluginRegistryAwareMessageHandler handler = new PluginRegistryAwareMessageHandler(registry, SamplePlugin.class, + "myBusinessMethod"); + + @Test + public void routesInvocationToFirstpluginIfConfiguredToDoSo() { + + handler.setDelimiterExpression("payload"); + handler.setInvocationArgumentsExpression("payload"); + + Message message = MessageBuilder.withPayload("FOO").build(); + handler.handleMessage(message); + } + + @Test(expected=MessageHandlingException.class) + public void failsHandlingMessageIfDelimiterTypeDoesNotMatch() { + + Message message = MessageBuilder.withPayload("FOO").build(); + handler.handleMessage(message); + } +} diff --git a/org.synyx.hera.si/src/test/java/org/synyx/hera/si/config/DynamicServiceActivatorNamespaceIntegrationTest.java b/org.synyx.hera.si/src/test/java/org/synyx/hera/si/config/DynamicServiceActivatorNamespaceIntegrationTest.java new file mode 100644 index 0000000..c7b24c2 --- /dev/null +++ b/org.synyx.hera.si/src/test/java/org/synyx/hera/si/config/DynamicServiceActivatorNamespaceIntegrationTest.java @@ -0,0 +1,47 @@ +/* + * Copyright 2011 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.synyx.hera.si.config; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.integration.Message; +import org.springframework.integration.MessageChannel; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * Integration test for the namespace. + * + * @author Oliver Gierke + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("classpath:dynamic-service-activator-test-context.xml") +public class DynamicServiceActivatorNamespaceIntegrationTest { + + @Autowired + @Qualifier("sampleChannel") + MessageChannel channel; + + @Test + public void invokesPluginBasedOnPayload() { + + Message message = MessageBuilder.withPayload("FOO").build(); + channel.send(message); + } +} diff --git a/org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/FirstSamplePluginImpl.java b/org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/FirstSamplePluginImpl.java new file mode 100644 index 0000000..1e562c5 --- /dev/null +++ b/org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/FirstSamplePluginImpl.java @@ -0,0 +1,22 @@ +package org.synyx.hera.si.sample; + +/** + * + * @author Oliver Gierke + */ +public class FirstSamplePluginImpl implements SamplePlugin { + + /* (non-Javadoc) + * @see org.synyx.hera.core.Plugin#supports(java.lang.Object) + */ + public boolean supports(String delimiter) { + return "FOO".equals(delimiter); + } + + /* (non-Javadoc) + * @see org.synyx.hera.si.sample.SamplePlugin#myBusinessMethod() + */ + public void myBusinessMethod(String message) { + System.out.println("First plugin invoked! " + message); + } +} diff --git a/org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/SamplePlugin.java b/org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/SamplePlugin.java new file mode 100644 index 0000000..05a19d9 --- /dev/null +++ b/org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/SamplePlugin.java @@ -0,0 +1,12 @@ +package org.synyx.hera.si.sample; + +import org.synyx.hera.core.Plugin; + +/** + * + * @author Oliver Gierke + */ +public interface SamplePlugin extends Plugin { + + void myBusinessMethod(String message); +} diff --git a/org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/SecondSamplePluginImpl.java b/org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/SecondSamplePluginImpl.java new file mode 100644 index 0000000..36c2d14 --- /dev/null +++ b/org.synyx.hera.si/src/test/java/org/synyx/hera/si/sample/SecondSamplePluginImpl.java @@ -0,0 +1,22 @@ +package org.synyx.hera.si.sample; + +/** + * + * @author Oliver Gierke + */ +public class SecondSamplePluginImpl implements SamplePlugin { + + /* (non-Javadoc) + * @see org.synyx.hera.core.Plugin#supports(java.lang.Object) + */ + public boolean supports(String delimiter) { + return "BAR".equals(delimiter); + } + + /* (non-Javadoc) + * @see org.synyx.hera.si.sample.SamplePlugin#myBusinessMethod() + */ + public void myBusinessMethod(String message) { + System.out.println("Second plugin invoked! " + message); + } +} diff --git a/org.synyx.hera.si/src/test/resources/dynamic-service-activator-test-context.xml b/org.synyx.hera.si/src/test/resources/dynamic-service-activator-test-context.xml new file mode 100644 index 0000000..92525b4 --- /dev/null +++ b/org.synyx.hera.si/src/test/resources/dynamic-service-activator-test-context.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + diff --git a/org.synyx.hera.si/template.mf b/org.synyx.hera.si/template.mf new file mode 100644 index 0000000..c46502d --- /dev/null +++ b/org.synyx.hera.si/template.mf @@ -0,0 +1,13 @@ +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: ${project.artifactId} +Bundle-Name: ${project.name} +Bundle-Vendor: Synyx GmbH & Co. KG +Bundle-Version: ${project.version} +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Export-Template: + ${project.artifactId}.*;version="${project.version}" +Import-Template: + org.synyx.hera.core.*;version="${project.version:[=.=.=.=,+1.0.0)}", + org.springframework.*;version="${spring.version:[=.=.=.=,+2.0.0)}", + org.springframework.integration.*;version="${spring.integration.version:[=.=.=.=,+1.0.0)}", + org.w3c.dom.*;version="0" diff --git a/pom.xml b/pom.xml index 51d6edc..ab93f43 100644 --- a/pom.xml +++ b/pom.xml @@ -17,6 +17,7 @@ core metadata + org.synyx.hera.si