From c392e198874e78e7afff2195aa0072f7597dd9f4 Mon Sep 17 00:00:00 2001 From: David Turanski Date: Fri, 8 Jul 2011 12:44:40 -0400 Subject: [PATCH] -aSimplified flow configuration and enhanced documentation mechanism --- .classpath | 1 + .project | 6 ++ .springBeans | 4 +- README | 22 +++-- pom.xml | 33 ++++++- .../flow/ChannelNamePortConfiguration.java | 34 +++---- .../integration/flow/Flow.java | 78 +++++---------- .../integration/flow/FlowConfiguration.java | 50 ++++------ .../flow/FlowProviderPortConfiguration.java | 28 ------ .../flow/NamedResourceConfiguration.java | 65 ------------ .../flow/NamedResourceMetadata.java | 60 ------------ .../integration/flow/PortConfiguration.java | 2 +- .../integration/flow/PortMetadata.java | 23 +++-- .../config/FlowMessageHandlerFactoryBean.java | 4 +- .../integration/flow/config/FlowUtils.java | 98 +++++++++++++------ .../config/xml/FlowConfigurationParser.java | 46 +-------- .../flow/config/xml/FlowNamespaceHandler.java | 2 +- .../flow/config/xml/FlowParser.java | 1 + ....java => FlowPortConfigurationParser.java} | 2 +- .../flow/handler/FlowMessageHandler.java | 2 +- .../config/spring-integration-flow-2.0.xsd | 54 +++------- .../NamedResourcesConfigurationTest.groovy | 43 -------- .../config/xml/FlowConfigNamespaceTest.java | 9 +- .../flow/config/xml/FlowWithErrorTest.java | 3 +- .../config/xml/FlowWithReferencesTest.java | 15 +-- .../FlowConfigNamespaceTest-context.xml | 52 +++++----- .../FlowWithMissingReferencesTest-context.xml | 19 ---- .../flows/{ => subflow1}/subflow1-context.xml | 15 +-- .../flows/{ => subflow2}/subflow2-context.xml | 1 - .../integration/flows/subflow3-context.xml | 37 ------- .../flows/{ => subflow4}/subflow4-context.xml | 8 +- .../flows/{ => subflow5}/subflow5-context.xml | 13 +-- src/test/resources/log4j.xml | 2 +- 33 files changed, 255 insertions(+), 577 deletions(-) delete mode 100644 src/main/java/org/springframework/integration/flow/FlowProviderPortConfiguration.java delete mode 100644 src/main/java/org/springframework/integration/flow/NamedResourceConfiguration.java delete mode 100644 src/main/java/org/springframework/integration/flow/NamedResourceMetadata.java rename src/main/java/org/springframework/integration/flow/config/xml/{FlowProviderPortConfigurationParser.java => FlowPortConfigurationParser.java} (92%) delete mode 100644 src/test/java/org/springframework/integration/flow/NamedResourcesConfigurationTest.groovy delete mode 100644 src/test/resources/FlowWithMissingReferencesTest-context.xml rename src/test/resources/META-INF/spring/integration/flows/{ => subflow1}/subflow1-context.xml (74%) rename src/test/resources/META-INF/spring/integration/flows/{ => subflow2}/subflow2-context.xml (96%) delete mode 100644 src/test/resources/META-INF/spring/integration/flows/subflow3-context.xml rename src/test/resources/META-INF/spring/integration/flows/{ => subflow4}/subflow4-context.xml (79%) rename src/test/resources/META-INF/spring/integration/flows/{ => subflow5}/subflow5-context.xml (73%) diff --git a/.classpath b/.classpath index 98cf23a..0a104f7 100644 --- a/.classpath +++ b/.classpath @@ -4,6 +4,7 @@ + diff --git a/.project b/.project index a4c1e0d..ba707a1 100644 --- a/.project +++ b/.project @@ -26,8 +26,14 @@ + + org.springframework.ide.eclipse.core.springbuilder + + + + org.springframework.ide.eclipse.core.springnature org.eclipse.jem.workbench.JavaEMFNature org.eclipse.wst.common.modulecore.ModuleCoreNature org.eclipse.jdt.groovy.core.groovyNature diff --git a/.springBeans b/.springBeans index 38aad46..5ab5ff5 100644 --- a/.springBeans +++ b/.springBeans @@ -1,16 +1,16 @@ 1 - + - src/test/resources/META-INF/spring/integration/flows/subflow1-context.xml src/test/resources/FlowConfigNamespaceTest-context.xml src/test/resources/FlowClientNamespaceTest-context.xml src/test/resources/ref-bean-config.xml + src/test/resources/META-INF/spring/integration/flows/subflow1/subflow1-context.xml diff --git a/README b/README index 945f332..b8def02 100644 --- a/README +++ b/README @@ -5,7 +5,7 @@ A flow is a Spring Integration message flow intended for reuse. A flow is access to internal channels. A flow may expose multiple inputs and multiple outputs. A port mapping is defined for each input and has multiple -outputs associated with it. See src/test/resources/META-INF/spring/integration/flows/subflow1-context.xml, for example. +outputs associated with it. See src/test/resources/META-INF/spring/integration/flows/subflow1/subflow1-context.xml, for example. Generally, a message flow may behave like a router. For example, a flow may define a primary output and a discard output. Additionally, it may act like a delayer, providing no immediate response. Or it @@ -14,9 +14,8 @@ could act as an outbound channel adapter, providing no output. The goal is to support these, and possibly other semantics. Additional goals are: - Encapsulation: the flow channels, and component should not be included the consumer application context. The consumer need not know how the flow is configured (i.e, it is contained in a jar). -- Configuration: The flow may define optional or required properties to be provided by the consumer. The flow may define optional -or required bean definitions provided by the consumer (e.g, a generic XML processor may require an OXM marshaller) - - The flow should be self describing, in terms of ports, properties, and beans it exposes +- Configuration: The flow may reference properties or beans to be provided by the consumer, e.g, a generic XML processor may require an OXM marshaller. + - The flow should provide a description, in terms of ports, properties, and beans it exposes - It should be easy to implement or wrap an existing configuration as a flow and provide a better option than simple importing a spring configuration file and sending a message to one of its input channels @@ -27,6 +26,15 @@ The flow consumer instantiates a flow and defines one or more flow outbound-gate +The flow also supports a properties attribute and a referenced-bean-locations attribute used to inject properties and a list of configuration files respectively. +Additionally any bean definition may be or property in the parent context may be inherited by the flow. + +An optional flow-id may be used to resolve the flow configuration. By default the id attribute is used as the flow-id. The flow-id is useful if there are multiple +instances of the same flow, each configured differently. Each instance would have a unique id and the same flow-id. + +An optional help attribute will output the flow's documentation to the STDOUT if set to 'true'. + + @@ -35,17 +43,17 @@ ports. The output port name is contained in the response header 'flow.output.por The input-port attribute is optional -- if the flow defines a single input port it will be mapped by default. -The flow also supports a properties attribute and a referenced-bean-locations attribute used to inject properties and a list of configuration files respectively. -Additionally any bean definition may be or property in the parent context may be inherited by the flow. Flow Implementation ------------------- The flow element creates a Flow instance (eventually, configured with properties, referenced beans, etc.) The flow id is used to derive the flow's -spring bean definition file by convention (META-INF/spring/flows/[flow-id]-context.xml). This bean definition file and any referenced bean locations +spring bean definition file by convention (classpath:META-INF/spring/flows/[flow-id]/*.xml). This bean definition file and any referenced bean locations will be used to create a child application context. The flow context must provide a FlowConfiguration containing the metadata describing the input ports, output ports, and referenced beans and properties. +The flow implementer should also create a text file classpath:META-INF/spring/flows/[flow-id]/flow.doc which will contain the 'help' contents. + Currently, all defined outputs are bridged to a PublishSubscribeChannel which acts as a single 'flowOutputChannel'. Each flow outbound-gateway instance is backed by a FlowMessageHandler that bridges the 'flow output channel' to its own QueueChannel. This emulates a JMS topic. Each flow message handler sends the request message to the flow input channel corresponding to the input port and checks diff --git a/pom.xml b/pom.xml index 8c174fd..435b26d 100644 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,7 @@ 4.0.0 org.springframework.integration spring-integration-flow - 2.0.5.BUILD-SNAPSHOT + 2.1.0.BUILD-SNAPSHOT Spring Integration Flow Support @@ -108,10 +108,36 @@ 4.8.2 test + + + org.springframework.integration + spring-integration-xml + ${spring.integration.version} + test + + + + org.springframework + spring-oxm + ${spring.framework.version} + test + + + + xmlunit + xmlunit + 1.3 + test + + + - + + + + org.apache.maven.plugins maven-compiler-plugin @@ -121,7 +147,8 @@ 1.5 - + + maven-antrun-plugin diff --git a/src/main/java/org/springframework/integration/flow/ChannelNamePortConfiguration.java b/src/main/java/org/springframework/integration/flow/ChannelNamePortConfiguration.java index 9ab2df9..33a1032 100644 --- a/src/main/java/org/springframework/integration/flow/ChannelNamePortConfiguration.java +++ b/src/main/java/org/springframework/integration/flow/ChannelNamePortConfiguration.java @@ -19,32 +19,27 @@ package org.springframework.integration.flow; import java.util.ArrayList; -import java.util.Collections; import java.util.List; -public class ChannelNamePortConfiguration extends NamedResourceConfiguration implements FlowProviderPortConfiguration { +public class ChannelNamePortConfiguration implements PortConfiguration { private PortMetadata inputPortMetadata; + private List outputPortMetadataList; public ChannelNamePortConfiguration(PortMetadata inputPortMetadata, List outputPortMetadataList) { - super(outputPortMetadataList); + this.outputPortMetadataList = outputPortMetadataList; this.inputPortMetadata = inputPortMetadata; } @Override public String getInputPortName() { - return this.inputPortMetadata.getName(); + return this.inputPortMetadata.getPortName(); } @Override public String getInputChannel() { return this.inputPortMetadata.getChannelName(); } - - @Override - public String getInputPortDescription() { - return this.inputPortMetadata.getDescription(); - } @Override @@ -59,9 +54,8 @@ public class ChannelNamePortConfiguration extends NamedResourceConfiguration imp @Override public List getOutputPortNames() { List results = new ArrayList(); - for (NamedResourceMetadata resourceMetadata : getConfiguredResources()) { - PortMetadata portMetadata = (PortMetadata) resourceMetadata; - results.add(portMetadata.getName()); + for (PortMetadata portMetadata : outputPortMetadataList ) { + results.add(portMetadata.getPortName()); } /** * consistent with ClientPortConfiguration impl. @@ -73,12 +67,14 @@ public class ChannelNamePortConfiguration extends NamedResourceConfiguration imp return results; } - - /* (non-Javadoc) - * @see org.springframework.integration.flow.FlowProviderPortConfiguration#getOutputPortMetadata() - */ - @Override - public List getOutputPortMetadata() { - return Collections.unmodifiableList(super.getConfiguredResources()); + + public PortMetadata find(String portName){ + for (PortMetadata portMetadata : outputPortMetadataList ) { + if (portName.equals(portMetadata.getPortName())){ + return portMetadata; + } + } + return null; } + } diff --git a/src/main/java/org/springframework/integration/flow/Flow.java b/src/main/java/org/springframework/integration/flow/Flow.java index ad98889..1a82dd6 100644 --- a/src/main/java/org/springframework/integration/flow/Flow.java +++ b/src/main/java/org/springframework/integration/flow/Flow.java @@ -49,7 +49,9 @@ public class Flow implements InitializingBean, BeanNameAware, ChannelResolver, A private volatile Properties flowProperties; - private volatile String name; + private volatile String beanName; + + private volatile String flowId; private volatile ChannelResolver flowChannelResolver; @@ -67,10 +69,18 @@ public class Flow implements InitializingBean, BeanNameAware, ChannelResolver, A @Override public void afterPropertiesSet() { + + if (this.flowId == null){ + this.flowId = this.beanName; + } + + if (this.help) { + System.out.println(FlowUtils.getDocumentation(this.flowId)); + } if (configLocations == null) { configLocations = new String[] { String.format( - "classpath*:META-INF/spring/integration/flows/%s-context.xml", this.name) }; + "classpath:META-INF/spring/integration/flows/%s/*.xml", this.flowId) }; } if (referencedBeanLocations != null) { @@ -87,9 +97,7 @@ public class Flow implements InitializingBean, BeanNameAware, ChannelResolver, A this.flowConfiguration = flowContext.getBean(FlowConfiguration.class); Assert.notNull(flowConfiguration, "flow context does not contain a flow configuration"); - if (this.help) { - System.out.println(displayFlowConfiguration()); - } + validatePortMapping(); @@ -109,15 +117,19 @@ public class Flow implements InitializingBean, BeanNameAware, ChannelResolver, A @Override public void setBeanName(String name) { - this.name = name; + this.beanName = name; } public String getBeanName() { - return this.name; + return this.beanName; } - public void setReferencedBeanLocations(String[] referencedBeanLocations) { + public void setFlowId(String flowId) { + this.flowId = flowId; + } + + public void setReferencedBeanLocations(String[] referencedBeanLocations) { this.referencedBeanLocations = referencedBeanLocations; } @@ -142,58 +154,12 @@ public class Flow implements InitializingBean, BeanNameAware, ChannelResolver, A return flowChannelResolver.resolveChannelName(channelName); } - - - /** - * - */ - private String displayFlowConfiguration() { - StringBuilder sb = new StringBuilder(); - sb.append("\nFlow configuration for [").append(this.getBeanName()).append("]:\n"); - sb.append("Port configuration:\n"); - for (FlowProviderPortConfiguration portConfiguration : this.getFlowConfiguration().getPortConfigurations()) { - sb.append("\tinput port:").append(portConfiguration.getInputPortName()).append("\n\n\t") - .append(portConfiguration.getInputPortDescription()).append("\n\n").append("\toutput ports:\n"); - - for (NamedResourceMetadata metadata : portConfiguration.getOutputPortMetadata()) { - sb.append("\t\t").append(metadata.getName()).append("\t") - .append(metadata.getDescription()).append("\n"); - } - - NamedResourceConfiguration referencedBeansConfig = this.getFlowConfiguration() - .getReferencedBeansConfiguration(); - if (referencedBeansConfig != null && !referencedBeansConfig.getConfiguredResources().isEmpty()) { - sb.append("\nReferenced beans:\n"); - for (NamedResourceMetadata metadata : referencedBeansConfig.getConfiguredResources()) { - sb.append("\t").append(metadata).append("\n"); - } - } - - NamedResourceConfiguration propertiesConfig = this.getFlowConfiguration().getPropertiesConfiguration(); - if (propertiesConfig != null && !propertiesConfig.getConfiguredResources().isEmpty()) { - sb.append("\nFlow properties:\n"); - for (NamedResourceMetadata metadata : propertiesConfig.getConfiguredResources()) { - sb.append("\t").append(metadata).append("\n"); - } - } - - } - - return sb.toString(); - } private void addReferencedProperties() { if (flowProperties != null) { PropertySource propertySource = new PropertiesPropertySource("flowProperties", flowProperties); - NamedResourceConfiguration propertiesConfiguration = this.getFlowConfiguration() - .getPropertiesConfiguration(); - if (propertiesConfiguration != null) { - for (NamedResourceMetadata resource : propertiesConfiguration.getRequiredResources()) { - Assert.isTrue(propertySource.containsProperty(resource.getName()), "Flow [" + this.name - + "] is missing required property [" + resource.getName() + "]"); - } - } + MutablePropertySources propertySources = flowContext.getEnvironment().getPropertySources(); propertySources.addLast(propertySource); @@ -212,7 +178,7 @@ public class Flow implements InitializingBean, BeanNameAware, ChannelResolver, A /* * create a bridge for each target output port to the flow outputChannel */ - for (FlowProviderPortConfiguration targetPortConfiguration : this.getFlowConfiguration() + for (PortConfiguration targetPortConfiguration : this.getFlowConfiguration() .getPortConfigurations()) { for (String outputPort : targetPortConfiguration.getOutputPortNames()) { String targetOutputChannelName = (String) targetPortConfiguration.getOutputChannel(outputPort); diff --git a/src/main/java/org/springframework/integration/flow/FlowConfiguration.java b/src/main/java/org/springframework/integration/flow/FlowConfiguration.java index 29ac726..c2772e7 100644 --- a/src/main/java/org/springframework/integration/flow/FlowConfiguration.java +++ b/src/main/java/org/springframework/integration/flow/FlowConfiguration.java @@ -24,47 +24,35 @@ import java.util.List; */ public class FlowConfiguration { - private final List portConfigurations; - - private volatile NamedResourceConfiguration propertiesConfiguration; - - private volatile NamedResourceConfiguration referencedBeansConfiguration; - - public FlowConfiguration(List portConfigurations) { + private final List portConfigurations; + + /** + * + * @param portConfigurations + */ + public FlowConfiguration(List portConfigurations) { this.portConfigurations = portConfigurations; } - public FlowProviderPortConfiguration getConfigurationForInputPort(String inputPortName) { - for (FlowProviderPortConfiguration pc : portConfigurations) { + /** + * + * @param inputPortName + * @return + */ + public PortConfiguration getConfigurationForInputPort(String inputPortName) { + for (PortConfiguration pc : portConfigurations) { if (pc.getInputPortName().equals(inputPortName)) { return pc; } } return null; } - - public void setPropertiesConfiguration(NamedResourceConfiguration propertiesConfiguration) { - this.propertiesConfiguration = propertiesConfiguration; - } - - public void setReferenceedBeansConfiguration(NamedResourceConfiguration referencedBeansConfiguration) { - this.setReferencedBeansConfiguration(referencedBeansConfiguration); - } - - public List getPortConfigurations() { + /** + * + * @return + */ + public List getPortConfigurations() { return portConfigurations; } - public NamedResourceConfiguration getPropertiesConfiguration() { - return propertiesConfiguration; - } - - public void setReferencedBeansConfiguration(NamedResourceConfiguration referencedBeansConfiguration) { - this.referencedBeansConfiguration = referencedBeansConfiguration; - } - - public NamedResourceConfiguration getReferencedBeansConfiguration() { - return referencedBeansConfiguration; - } - } diff --git a/src/main/java/org/springframework/integration/flow/FlowProviderPortConfiguration.java b/src/main/java/org/springframework/integration/flow/FlowProviderPortConfiguration.java deleted file mode 100644 index b5b53af..0000000 --- a/src/main/java/org/springframework/integration/flow/FlowProviderPortConfiguration.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2002-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.springframework.integration.flow; - -import java.util.List; - -/** - * - * @author David Turanski - * - */ -public interface FlowProviderPortConfiguration extends PortConfiguration { - public abstract String getInputPortDescription(); - public abstract List getOutputPortMetadata(); -} \ No newline at end of file diff --git a/src/main/java/org/springframework/integration/flow/NamedResourceConfiguration.java b/src/main/java/org/springframework/integration/flow/NamedResourceConfiguration.java deleted file mode 100644 index 72809f1..0000000 --- a/src/main/java/org/springframework/integration/flow/NamedResourceConfiguration.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2002-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.springframework.integration.flow; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * - * @author David Turanski - * - */ -public class NamedResourceConfiguration { - private final List resourceMetadata; - - public NamedResourceConfiguration(List resourceMetadata) { - this.resourceMetadata = resourceMetadata; - } - - public boolean isRequired(String namedResource) { - for (NamedResourceMetadata metadata : resourceMetadata) { - if (metadata.getName().equals(namedResource)) { - return metadata.isRequired(); - } - } - return false; - } - - public List getConfiguredResources() { - return Collections.unmodifiableList(resourceMetadata); - } - - public List getRequiredResources() { - List requiredResources = new ArrayList(); - for (NamedResourceMetadata metadata : resourceMetadata) { - if (metadata.isRequired()) { - requiredResources.add(metadata); - } - } - return requiredResources; - } - - public NamedResourceMetadata find(String name) { - for (NamedResourceMetadata metadata : resourceMetadata) { - if (metadata.getName().equals(name)) { - return metadata; - } - } - return null; - } -} diff --git a/src/main/java/org/springframework/integration/flow/NamedResourceMetadata.java b/src/main/java/org/springframework/integration/flow/NamedResourceMetadata.java deleted file mode 100644 index 1819e20..0000000 --- a/src/main/java/org/springframework/integration/flow/NamedResourceMetadata.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2002-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.springframework.integration.flow; - -import org.springframework.util.Assert; - -/** - * - * @author David Turanski - * - */ -public class NamedResourceMetadata { - private final String name; - - private final String description; - - private final boolean required; - - public NamedResourceMetadata(String name, String description, boolean required) { - Assert.hasText(name, "name is required"); - this.name = name; - this.description = description; - this.required = required; - } - - public String getName() { - return name; - } - - public String getDescription() { - return description; - } - - public boolean isRequired() { - return required; - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(getName()).append("\t") - .append(required? "required" : "optional") - .append("\t") - .append(getDescription()); - return sb.toString(); - } - -} diff --git a/src/main/java/org/springframework/integration/flow/PortConfiguration.java b/src/main/java/org/springframework/integration/flow/PortConfiguration.java index 813a6ea..fcc666e 100644 --- a/src/main/java/org/springframework/integration/flow/PortConfiguration.java +++ b/src/main/java/org/springframework/integration/flow/PortConfiguration.java @@ -30,5 +30,5 @@ public interface PortConfiguration { public Collection getOutputPortNames(); public Object getOutputChannel(String portName); - // TODO: Do we need error channel? + } diff --git a/src/main/java/org/springframework/integration/flow/PortMetadata.java b/src/main/java/org/springframework/integration/flow/PortMetadata.java index 3eebfca..6030f82 100644 --- a/src/main/java/org/springframework/integration/flow/PortMetadata.java +++ b/src/main/java/org/springframework/integration/flow/PortMetadata.java @@ -20,20 +20,25 @@ package org.springframework.integration.flow; * @author David Turanski * */ -public class PortMetadata extends NamedResourceMetadata { +public class PortMetadata { private final String channelName; + private final String portName; public PortMetadata(String portName, String channelName) { - this(portName, "", channelName); + this.portName = portName; + this.channelName = channelName; } - public PortMetadata(String portName, String description, String channelName) { - super(portName, description, true); - this.channelName = channelName; - } + public String getChannelName() { + return channelName; + } - public String getChannelName() { - return channelName; - } + public String getPortName() { + return portName; + } + + + + } diff --git a/src/main/java/org/springframework/integration/flow/config/FlowMessageHandlerFactoryBean.java b/src/main/java/org/springframework/integration/flow/config/FlowMessageHandlerFactoryBean.java index edbe1e4..09097b4 100644 --- a/src/main/java/org/springframework/integration/flow/config/FlowMessageHandlerFactoryBean.java +++ b/src/main/java/org/springframework/integration/flow/config/FlowMessageHandlerFactoryBean.java @@ -23,7 +23,7 @@ import org.springframework.integration.config.AbstractSimpleMessageHandlerFactor import org.springframework.integration.core.MessageHandler; import org.springframework.integration.core.PollableChannel; import org.springframework.integration.flow.Flow; -import org.springframework.integration.flow.FlowProviderPortConfiguration; +import org.springframework.integration.flow.PortConfiguration; import org.springframework.integration.flow.handler.FlowMessageHandler; import org.springframework.util.Assert; @@ -45,7 +45,7 @@ public class FlowMessageHandlerFactoryBean extends AbstractSimpleMessageHandlerF private volatile PollableChannel flowReceiveChannel; - private volatile FlowProviderPortConfiguration flowConfiguration; + private volatile PortConfiguration flowConfiguration; @Override protected MessageHandler createHandler() { diff --git a/src/main/java/org/springframework/integration/flow/config/FlowUtils.java b/src/main/java/org/springframework/integration/flow/config/FlowUtils.java index eda7f5a..3c51a9b 100644 --- a/src/main/java/org/springframework/integration/flow/config/FlowUtils.java +++ b/src/main/java/org/springframework/integration/flow/config/FlowUtils.java @@ -12,6 +12,12 @@ */ package org.springframework.integration.flow.config; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; + import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; @@ -19,41 +25,71 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.integration.MessageChannel; import org.springframework.integration.core.SubscribableChannel; import org.springframework.integration.handler.BridgeHandler; +import org.springframework.util.ResourceUtils; /** * @author David Turanski - * + * */ public class FlowUtils { - /** - * Create a bridge - * @param inputChannel - * @param outputChannel - */ - - public static void bridgeChannels(SubscribableChannel inputChannel, MessageChannel outputChannel) { - BridgeHandler bridgeHandler = new BridgeHandler(); - bridgeHandler.setOutputChannel(outputChannel); - inputChannel.subscribe(bridgeHandler); + /** + * Create a bridge + * + * @param inputChannel + * @param outputChannel + */ + + public static void bridgeChannels(SubscribableChannel inputChannel, MessageChannel outputChannel) { + BridgeHandler bridgeHandler = new BridgeHandler(); + bridgeHandler.setOutputChannel(outputChannel); + inputChannel.subscribe(bridgeHandler); } - - - /** - * Register a bean with "flow" prefix - * @param beanDefinition - * @param registry - * @return - */ - public static String registerBeanDefinition(BeanDefinition beanDefinition, BeanDefinitionRegistry registry){ - String beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, registry); - beanName = "flow."+ beanName; - String strIndex = StringUtils.substringAfter(beanName,"#"); - int index = Integer.valueOf(strIndex); - while (registry.isBeanNameInUse(beanName)){ - index++; - beanName = beanName.replaceAll("#\\d$","#"+ (index)); - } - registry.registerBeanDefinition(beanName, beanDefinition); - return beanName; - } + + /** + * Register a bean with "flow" prefix + * + * @param beanDefinition + * @param registry + * @return + */ + public static String registerBeanDefinition(BeanDefinition beanDefinition, BeanDefinitionRegistry registry) { + String beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, registry); + beanName = "flow." + beanName; + String strIndex = StringUtils.substringAfter(beanName, "#"); + int index = Integer.valueOf(strIndex); + while (registry.isBeanNameInUse(beanName)) { + index++; + beanName = beanName.replaceAll("#\\d$", "#" + (index)); + } + registry.registerBeanDefinition(beanName, beanDefinition); + return beanName; + } + + public static String getDocumentation(String flowName) { + + String path = String.format("classpath:META-INF/spring/integration/flows/%s/flow.doc", flowName); + + try { + File file = ResourceUtils.getFile(path); + + BufferedReader br = new BufferedReader(new FileReader(file)); + + String line; + StringBuilder result = new StringBuilder(); + while ((line = br.readLine()) != null) { + result.append(line).append("\n"); + } + + br.close(); + + return result.toString(); + + } catch (FileNotFoundException e) { + return "no help available"; + } catch (IOException e) { + e.printStackTrace(); + return "no help available"; + } + } + } diff --git a/src/main/java/org/springframework/integration/flow/config/xml/FlowConfigurationParser.java b/src/main/java/org/springframework/integration/flow/config/xml/FlowConfigurationParser.java index b13e1bd..12b463b 100644 --- a/src/main/java/org/springframework/integration/flow/config/xml/FlowConfigurationParser.java +++ b/src/main/java/org/springframework/integration/flow/config/xml/FlowConfigurationParser.java @@ -16,6 +16,7 @@ package org.springframework.integration.flow.config.xml; import java.util.List; + import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; @@ -24,8 +25,6 @@ import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.flow.ChannelNamePortConfiguration; import org.springframework.integration.flow.FlowConfiguration; -import org.springframework.integration.flow.NamedResourceConfiguration; -import org.springframework.integration.flow.NamedResourceMetadata; import org.springframework.integration.flow.PortMetadata; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; @@ -57,19 +56,8 @@ public class FlowConfigurationParser implements BeanDefinitionParser { flowConfigurationBuilder.addConstructorArgValue(portConfigList); - BeanDefinition referencedProperties = this.buildNamedResourceConfiguration(element, "referenced-property"); - - flowConfigurationBuilder.addPropertyValue("propertiesConfiguration", referencedProperties); - - BeanDefinition referencedBeans = this.buildNamedResourceConfiguration(element, "referenced-bean"); - - flowConfigurationBuilder.addPropertyValue("referencedBeansConfiguration", referencedBeans); - BeanDefinitionReaderUtils.registerWithGeneratedName(flowConfigurationBuilder.getBeanDefinition(), - parserContext.getRegistry()); - - - + parserContext.getRegistry()); return null; } @@ -101,38 +89,10 @@ public class FlowConfigurationParser implements BeanDefinitionParser { return portConfigurationBuilder.getBeanDefinition(); } - private BeanDefinition buildNamedResourceConfiguration(Element parent, String elementName) { - ManagedList namedResourceList = new ManagedList(); - List namedResources = DomUtils.getChildElementsByTagName(parent, elementName); - for (Element el : namedResources ) { - BeanDefinitionBuilder namedResourceBuilder = BeanDefinitionBuilder.genericBeanDefinition(NamedResourceMetadata.class); - boolean required = ("true".equals(el.getAttribute("required"))); - String name = el.getAttribute("id"); - String description = getChildElementText(el, "description", ""); - namedResourceBuilder.addConstructorArgValue(name); - namedResourceBuilder.addConstructorArgValue(description); - namedResourceBuilder.addConstructorArgValue(required); - namedResourceList.add(namedResourceBuilder.getBeanDefinition()); - } - BeanDefinitionBuilder namedResourceConfigurationBuilder = BeanDefinitionBuilder.genericBeanDefinition(NamedResourceConfiguration.class); - namedResourceConfigurationBuilder.addConstructorArgValue(namedResourceList); - return namedResourceConfigurationBuilder.getBeanDefinition(); - } - - private String getChildElementText(Element parent, String elementName, String defaultValue ){ - String value = defaultValue; - Element child = DomUtils.getChildElementByTagName(parent, elementName); - if (child != null ) { - value = child.getTextContent(); - } - return value; - } - + private BeanDefinition buildPortMetadata(Element element, Element portElement) { BeanDefinitionBuilder portMetadataBuilder = BeanDefinitionBuilder.genericBeanDefinition(PortMetadata.class); portMetadataBuilder.addConstructorArgValue(portElement.getAttribute("name")); - String description = getChildElementText(portElement, "description", ""); - portMetadataBuilder.addConstructorArgValue(description); portMetadataBuilder.addConstructorArgValue(portElement.getAttribute("channel")); return portMetadataBuilder.getBeanDefinition(); } diff --git a/src/main/java/org/springframework/integration/flow/config/xml/FlowNamespaceHandler.java b/src/main/java/org/springframework/integration/flow/config/xml/FlowNamespaceHandler.java index 8804094..073885d 100644 --- a/src/main/java/org/springframework/integration/flow/config/xml/FlowNamespaceHandler.java +++ b/src/main/java/org/springframework/integration/flow/config/xml/FlowNamespaceHandler.java @@ -29,7 +29,7 @@ public class FlowNamespaceHandler extends AbstractIntegrationNamespaceHandler { registerBeanDefinitionParser("flow", new FlowParser()); registerBeanDefinitionParser("outbound-gateway", new FlowOutboundGatewayParser()); registerBeanDefinitionParser("flow-configuration", new FlowConfigurationParser()); - registerBeanDefinitionParser("port-mapping", new FlowProviderPortConfigurationParser()); + registerBeanDefinitionParser("port-mapping", new FlowPortConfigurationParser()); } } diff --git a/src/main/java/org/springframework/integration/flow/config/xml/FlowParser.java b/src/main/java/org/springframework/integration/flow/config/xml/FlowParser.java index caf2cc7..9960c3f 100644 --- a/src/main/java/org/springframework/integration/flow/config/xml/FlowParser.java +++ b/src/main/java/org/springframework/integration/flow/config/xml/FlowParser.java @@ -45,6 +45,7 @@ public class FlowParser implements BeanDefinitionParser { IntegrationNamespaceUtils.setValueIfAttributeDefined(flowBuilder, element, "referenced-bean-locations"); IntegrationNamespaceUtils.setReferenceIfAttributeDefined(flowBuilder, element, "properties"); IntegrationNamespaceUtils.setValueIfAttributeDefined(flowBuilder, element, "help"); + IntegrationNamespaceUtils.setValueIfAttributeDefined(flowBuilder, element, "flow-id"); BeanDefinition beanDefinition = flowBuilder.getBeanDefinition(); parserContext.getRegistry().registerBeanDefinition(id, beanDefinition); diff --git a/src/main/java/org/springframework/integration/flow/config/xml/FlowProviderPortConfigurationParser.java b/src/main/java/org/springframework/integration/flow/config/xml/FlowPortConfigurationParser.java similarity index 92% rename from src/main/java/org/springframework/integration/flow/config/xml/FlowProviderPortConfigurationParser.java rename to src/main/java/org/springframework/integration/flow/config/xml/FlowPortConfigurationParser.java index 568e583..898ccf2 100644 --- a/src/main/java/org/springframework/integration/flow/config/xml/FlowProviderPortConfigurationParser.java +++ b/src/main/java/org/springframework/integration/flow/config/xml/FlowPortConfigurationParser.java @@ -25,7 +25,7 @@ import org.w3c.dom.Element; * @author David Turanski * */ -public class FlowProviderPortConfigurationParser implements BeanDefinitionParser { +public class FlowPortConfigurationParser implements BeanDefinitionParser { @Override public BeanDefinition parse(Element arg0, ParserContext arg1) { diff --git a/src/main/java/org/springframework/integration/flow/handler/FlowMessageHandler.java b/src/main/java/org/springframework/integration/flow/handler/FlowMessageHandler.java index 8f27511..a611363 100644 --- a/src/main/java/org/springframework/integration/flow/handler/FlowMessageHandler.java +++ b/src/main/java/org/springframework/integration/flow/handler/FlowMessageHandler.java @@ -84,7 +84,7 @@ public class FlowMessageHandler extends AbstractReplyProducingMessageHandler { } } } catch (MessagingException me) { - log.debug("caught exception - failed message: " + me.getFailedMessage()); + log.error(me.getMessage(), me); if (conversationId.equals(me.getFailedMessage().getHeaders().get("flow.conversation.id"))) { return new ErrorMessage(me); } diff --git a/src/main/resources/org/springframework/integration/flow/config/spring-integration-flow-2.0.xsd b/src/main/resources/org/springframework/integration/flow/config/spring-integration-flow-2.0.xsd index 65150e4..a010f50 100644 --- a/src/main/resources/org/springframework/integration/flow/config/spring-integration-flow-2.0.xsd +++ b/src/main/resources/org/springframework/integration/flow/config/spring-integration-flow-2.0.xsd @@ -44,6 +44,14 @@ ]]> + + + + + @@ -105,8 +113,7 @@ - - + @@ -129,52 +136,17 @@ - - - - - - - - - - - - - - - - - - - - - - + + nillable="false" type="BasePortType"> - + - - - - - - - - - - + \ No newline at end of file diff --git a/src/test/java/org/springframework/integration/flow/NamedResourcesConfigurationTest.groovy b/src/test/java/org/springframework/integration/flow/NamedResourcesConfigurationTest.groovy deleted file mode 100644 index be65799..0000000 --- a/src/test/java/org/springframework/integration/flow/NamedResourcesConfigurationTest.groovy +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2002-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.springframework.integration.flow -import org.junit.Test -/** - * - * @author David Turanski - * - */ -class NamedResourcesConfigurationTest { - def resourceMetadataList = [ - new NamedResourceMetadata('resource1','describes resource1',true), - new NamedResourceMetadata('resource2','describes resource2',false), - new NamedResourceMetadata('resource3','describes resource3',true) - ] - - @Test - public void testGetRequired(){ - def namedResourceConfiguration = new NamedResourceConfiguration(resourceMetadataList); - def required = namedResourceConfiguration.getRequiredResources() - assert required.size() == 2 - required.each { assert it.required; assert namedResourceConfiguration.isRequired(it.name) } - } - - @Test - public void testGetAll(){ - def namedResourceConfiguration = new NamedResourceConfiguration(resourceMetadataList); - assert namedResourceConfiguration.getConfiguredResources().size() == 3 - } -} diff --git a/src/test/java/org/springframework/integration/flow/config/xml/FlowConfigNamespaceTest.java b/src/test/java/org/springframework/integration/flow/config/xml/FlowConfigNamespaceTest.java index 23be2da..aacfdcd 100644 --- a/src/test/java/org/springframework/integration/flow/config/xml/FlowConfigNamespaceTest.java +++ b/src/test/java/org/springframework/integration/flow/config/xml/FlowConfigNamespaceTest.java @@ -15,13 +15,14 @@ */ package org.springframework.integration.flow.config.xml; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.integration.flow.FlowConfiguration; -import org.springframework.integration.flow.FlowProviderPortConfiguration; +import org.springframework.integration.flow.PortConfiguration; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -40,10 +41,10 @@ public class FlowConfigNamespaceTest { public void test() { assertNotNull(flowConfiguration.getPortConfigurations()); assertEquals(2, flowConfiguration.getPortConfigurations().size()); - FlowProviderPortConfiguration pc0 = flowConfiguration.getPortConfigurations().get(0); + PortConfiguration pc0 = flowConfiguration.getPortConfigurations().get(0); assertEquals("input", pc0.getInputPortName()); assertEquals("subflow-input", pc0.getInputChannel()); - assertEquals("", pc0.getInputPortDescription()); + assertEquals("subflow-output", pc0.getOutputChannel("output")); assertEquals(1, pc0.getOutputPortNames().size()); } diff --git a/src/test/java/org/springframework/integration/flow/config/xml/FlowWithErrorTest.java b/src/test/java/org/springframework/integration/flow/config/xml/FlowWithErrorTest.java index c9b120a..3c2ae58 100644 --- a/src/test/java/org/springframework/integration/flow/config/xml/FlowWithErrorTest.java +++ b/src/test/java/org/springframework/integration/flow/config/xml/FlowWithErrorTest.java @@ -18,7 +18,6 @@ package org.springframework.integration.flow.config.xml; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import org.junit.Ignore; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -54,7 +53,7 @@ public class FlowWithErrorTest { @Test public void testDirectCallWithErrorChannel(){ - ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/spring/integration/flows/subflow5-context.xml"); + ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/spring/integration/flows/subflow5/subflow5-context.xml"); MessageChannel input = applicationContext.getBean("subflow-input",MessageChannel.class); SubscribableChannel error = applicationContext.getBean("errorChannel",SubscribableChannel.class); diff --git a/src/test/java/org/springframework/integration/flow/config/xml/FlowWithReferencesTest.java b/src/test/java/org/springframework/integration/flow/config/xml/FlowWithReferencesTest.java index 671a0d1..29172be 100644 --- a/src/test/java/org/springframework/integration/flow/config/xml/FlowWithReferencesTest.java +++ b/src/test/java/org/springframework/integration/flow/config/xml/FlowWithReferencesTest.java @@ -17,10 +17,8 @@ package org.springframework.integration.flow.config.xml; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; import org.junit.Test; -import org.springframework.beans.factory.BeanCreationException; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.Message; @@ -50,16 +48,5 @@ public class FlowWithReferencesTest { assertEquals("undefined",reply.getHeaders().get("property.value.2")); } - @Test - public void testMissingPropertyReference() { - try { - new ClassPathXmlApplicationContext("classpath:/FlowWithMissingReferencesTest-context.xml"); - fail("should throw exception"); - } catch (BeanCreationException e) { - if(!("Flow [subflow3] is missing required property [key1]".equals(e.getCause().getMessage() ) ) ) { - e.printStackTrace(); - fail(e.getMessage()); - } - } - } + } diff --git a/src/test/resources/FlowConfigNamespaceTest-context.xml b/src/test/resources/FlowConfigNamespaceTest-context.xml index 8f20764..2f17eb5 100644 --- a/src/test/resources/FlowConfigNamespaceTest-context.xml +++ b/src/test/resources/FlowConfigNamespaceTest-context.xml @@ -1,37 +1,35 @@ - + - - - - - - - - - - + + - - - - - - - - + - + - + - - - - + + + + + + + + + + + diff --git a/src/test/resources/FlowWithMissingReferencesTest-context.xml b/src/test/resources/FlowWithMissingReferencesTest-context.xml deleted file mode 100644 index 7756002..0000000 --- a/src/test/resources/FlowWithMissingReferencesTest-context.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - val1 - - - - - - diff --git a/src/test/resources/META-INF/spring/integration/flows/subflow1-context.xml b/src/test/resources/META-INF/spring/integration/flows/subflow1/subflow1-context.xml similarity index 74% rename from src/test/resources/META-INF/spring/integration/flows/subflow1-context.xml rename to src/test/resources/META-INF/spring/integration/flows/subflow1/subflow1-context.xml index a274a15..bef9b04 100644 --- a/src/test/resources/META-INF/spring/integration/flows/subflow1-context.xml +++ b/src/test/resources/META-INF/spring/integration/flows/subflow1/subflow1-context.xml @@ -11,18 +11,9 @@ - - - - - - - - - + + + diff --git a/src/test/resources/META-INF/spring/integration/flows/subflow2-context.xml b/src/test/resources/META-INF/spring/integration/flows/subflow2/subflow2-context.xml similarity index 96% rename from src/test/resources/META-INF/spring/integration/flows/subflow2-context.xml rename to src/test/resources/META-INF/spring/integration/flows/subflow2/subflow2-context.xml index 794df5a..493921b 100644 --- a/src/test/resources/META-INF/spring/integration/flows/subflow2-context.xml +++ b/src/test/resources/META-INF/spring/integration/flows/subflow2/subflow2-context.xml @@ -19,7 +19,6 @@ - diff --git a/src/test/resources/META-INF/spring/integration/flows/subflow3-context.xml b/src/test/resources/META-INF/spring/integration/flows/subflow3-context.xml deleted file mode 100644 index b74f256..0000000 --- a/src/test/resources/META-INF/spring/integration/flows/subflow3-context.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - This optionally describes the flow - - - This describes the purpose/ necessary conditions for this output - - - - - This is an example of a required property - - - This is an example of an optional property - - - - - - diff --git a/src/test/resources/META-INF/spring/integration/flows/subflow4-context.xml b/src/test/resources/META-INF/spring/integration/flows/subflow4/subflow4-context.xml similarity index 79% rename from src/test/resources/META-INF/spring/integration/flows/subflow4-context.xml rename to src/test/resources/META-INF/spring/integration/flows/subflow4/subflow4-context.xml index 1451b8b..633c010 100644 --- a/src/test/resources/META-INF/spring/integration/flows/subflow4-context.xml +++ b/src/test/resources/META-INF/spring/integration/flows/subflow4/subflow4-context.xml @@ -13,12 +13,8 @@ - - This optionally describes the flow - - - This describes the purpose/ necessary conditions for this output - + + diff --git a/src/test/resources/META-INF/spring/integration/flows/subflow5-context.xml b/src/test/resources/META-INF/spring/integration/flows/subflow5/subflow5-context.xml similarity index 73% rename from src/test/resources/META-INF/spring/integration/flows/subflow5-context.xml rename to src/test/resources/META-INF/spring/integration/flows/subflow5/subflow5-context.xml index c2b8a1f..3c5d7a1 100644 --- a/src/test/resources/META-INF/spring/integration/flows/subflow5-context.xml +++ b/src/test/resources/META-INF/spring/integration/flows/subflow5/subflow5-context.xml @@ -13,16 +13,9 @@ - - This optionally describes the flow - - - This describes the purpose/ necessary conditions for this output - - - - This describes the purpose/ necessary conditions for this output - + + + diff --git a/src/test/resources/log4j.xml b/src/test/resources/log4j.xml index 75e0f19..3294ced 100644 --- a/src/test/resources/log4j.xml +++ b/src/test/resources/log4j.xml @@ -16,7 +16,7 @@ - +