-aSimplified flow configuration and enhanced documentation mechanism
This commit is contained in:
@@ -4,6 +4,7 @@
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="src" path="target/generated-sources/xjc"/>
|
||||
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
|
||||
|
||||
6
.project
6
.project
@@ -26,8 +26,14 @@
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.springframework.ide.eclipse.core.springbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.springframework.ide.eclipse.core.springnature</nature>
|
||||
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
|
||||
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
|
||||
<nature>org.eclipse.jdt.groovy.core.groovyNature</nature>
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beansProjectDescription>
|
||||
<version>1</version>
|
||||
<pluginVersion><![CDATA[2.7.0.201106102322-M2]]></pluginVersion>
|
||||
<pluginVersion><![CDATA[2.7.0.201107040453-RELEASE]]></pluginVersion>
|
||||
<configSuffixes>
|
||||
<configSuffix><![CDATA[xml]]></configSuffix>
|
||||
</configSuffixes>
|
||||
<enableImports><![CDATA[false]]></enableImports>
|
||||
<configs>
|
||||
<config>src/test/resources/META-INF/spring/integration/flows/subflow1-context.xml</config>
|
||||
<config>src/test/resources/FlowConfigNamespaceTest-context.xml</config>
|
||||
<config>src/test/resources/FlowClientNamespaceTest-context.xml</config>
|
||||
<config>src/test/resources/ref-bean-config.xml</config>
|
||||
<config>src/test/resources/META-INF/spring/integration/flows/subflow1/subflow1-context.xml</config>
|
||||
</configs>
|
||||
<configSets>
|
||||
</configSets>
|
||||
|
||||
22
README
22
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
|
||||
|
||||
<int-flow:flow id="subflow1"/>
|
||||
|
||||
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'.
|
||||
|
||||
|
||||
<int-flow:outbound-gateway flow="subflow1" input-channel="another-input"
|
||||
output-channel="another-output" input-port="gateway-input"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
33
pom.xml
33
pom.xml
@@ -9,7 +9,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-flow</artifactId>
|
||||
<version>2.0.5.BUILD-SNAPSHOT</version>
|
||||
<version>2.1.0.BUILD-SNAPSHOT</version>
|
||||
<name>Spring Integration Flow Support</name>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -108,10 +108,36 @@
|
||||
<version>4.8.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.integration</groupId>
|
||||
<artifactId>spring-integration-xml</artifactId>
|
||||
<version>${spring.integration.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-oxm</artifactId>
|
||||
<version>${spring.framework.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>xmlunit</groupId>
|
||||
<artifactId>xmlunit</artifactId>
|
||||
<version>1.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
<plugins>
|
||||
<!-- Generate JAXB classes from schema into target -->
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
@@ -121,7 +147,8 @@
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
|
||||
@@ -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<PortMetadata> outputPortMetadataList;
|
||||
|
||||
public ChannelNamePortConfiguration(PortMetadata inputPortMetadata, List<PortMetadata> 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<String> getOutputPortNames() {
|
||||
List<String> results = new ArrayList<String>();
|
||||
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<NamedResourceMetadata> getOutputPortMetadata() {
|
||||
return Collections.unmodifiableList(super.getConfiguredResources());
|
||||
|
||||
public PortMetadata find(String portName){
|
||||
for (PortMetadata portMetadata : outputPortMetadataList ) {
|
||||
if (portName.equals(portMetadata.getPortName())){
|
||||
return portMetadata;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -24,47 +24,35 @@ import java.util.List;
|
||||
*/
|
||||
public class FlowConfiguration {
|
||||
|
||||
private final List<FlowProviderPortConfiguration> portConfigurations;
|
||||
|
||||
private volatile NamedResourceConfiguration propertiesConfiguration;
|
||||
|
||||
private volatile NamedResourceConfiguration referencedBeansConfiguration;
|
||||
|
||||
public FlowConfiguration(List<FlowProviderPortConfiguration> portConfigurations) {
|
||||
private final List<PortConfiguration> portConfigurations;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param portConfigurations
|
||||
*/
|
||||
public FlowConfiguration(List<PortConfiguration> 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<FlowProviderPortConfiguration> getPortConfigurations() {
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<PortConfiguration> getPortConfigurations() {
|
||||
return portConfigurations;
|
||||
}
|
||||
|
||||
public NamedResourceConfiguration getPropertiesConfiguration() {
|
||||
return propertiesConfiguration;
|
||||
}
|
||||
|
||||
public void setReferencedBeansConfiguration(NamedResourceConfiguration referencedBeansConfiguration) {
|
||||
this.referencedBeansConfiguration = referencedBeansConfiguration;
|
||||
}
|
||||
|
||||
public NamedResourceConfiguration getReferencedBeansConfiguration() {
|
||||
return referencedBeansConfiguration;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<NamedResourceMetadata> getOutputPortMetadata();
|
||||
}
|
||||
@@ -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<? extends NamedResourceMetadata> resourceMetadata;
|
||||
|
||||
public NamedResourceConfiguration(List<? extends NamedResourceMetadata> 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<NamedResourceMetadata> getConfiguredResources() {
|
||||
return Collections.unmodifiableList(resourceMetadata);
|
||||
}
|
||||
|
||||
public List<NamedResourceMetadata> getRequiredResources() {
|
||||
List<NamedResourceMetadata> requiredResources = new ArrayList<NamedResourceMetadata>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,5 +30,5 @@ public interface PortConfiguration {
|
||||
public Collection<String> getOutputPortNames();
|
||||
|
||||
public Object getOutputChannel(String portName);
|
||||
// TODO: Do we need error channel?
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Object> namedResourceList = new ManagedList<Object>();
|
||||
List<Element> 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();
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,14 @@
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="flow-id" type="xsd:string"
|
||||
use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Flow id
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
@@ -105,8 +113,7 @@
|
||||
|
||||
<xsd:element name="port-mapping" type="PortMappingType" />
|
||||
</xsd:choice>
|
||||
<xsd:element name="referenced-bean" minOccurs="0" maxOccurs="unbounded" type="NamedResourceType"/>
|
||||
<xsd:element name="referenced-property" minOccurs="0" maxOccurs="unbounded" type="NamedResourceType"/>
|
||||
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
@@ -129,52 +136,17 @@
|
||||
<xsd:attribute name="channel" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="FlowPortType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines an integration flow port binding
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="BasePortType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="description" minOccurs="0"
|
||||
maxOccurs="1" type="xsd:string" />
|
||||
</xsd:sequence>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="FlowOutputPortType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines an integration flow output port binding
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="FlowPortType">
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
|
||||
<xsd:complexType name="PortMappingType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="input-port" minOccurs="1" maxOccurs="1"
|
||||
nillable="false" type="FlowPortType">
|
||||
nillable="false" type="BasePortType">
|
||||
</xsd:element>
|
||||
<xsd:element name="output-port" minOccurs="0" maxOccurs="unbounded" type="FlowOutputPortType"/>
|
||||
<xsd:element name="output-port" minOccurs="0" maxOccurs="unbounded" type="BasePortType"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="NamedResourceType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="description" type="xsd:string" minOccurs="0"/>
|
||||
</xsd:sequence>
|
||||
|
||||
<xsd:attribute name="required" type="xsd:boolean" default="false">
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="id" use="required" type="xsd:ID">
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
|
||||
</xsd:schema>
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,37 +1,35 @@
|
||||
<?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:int-flow="http://www.springframework.org/schema/integration/flow"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/flow http://www.springframework.org/schema/integration/flow/spring-integration-flow-2.0.xsd
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int-flow="http://www.springframework.org/schema/integration/flow"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration/flow http://www.springframework.org/schema/integration/flow/spring-integration-flow-2.0.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
<int-flow:flow-configuration>
|
||||
<int-flow:flow-configuration>
|
||||
|
||||
|
||||
<int-flow:port-mapping>
|
||||
<int-flow:input-port name="input" channel="subflow-input">
|
||||
<int-flow:description></int-flow:description>
|
||||
</int-flow:input-port>
|
||||
<int-flow:output-port name="output" channel="subflow-output">
|
||||
<int-flow:description></int-flow:description>
|
||||
</int-flow:output-port>
|
||||
</int-flow:port-mapping>
|
||||
|
||||
<int-flow:port-mapping-ref bean="portConfig1" />
|
||||
<int-flow:port-mapping>
|
||||
<int-flow:input-port name="input"
|
||||
channel="subflow-input" />
|
||||
|
||||
<int-flow:port-mapping>
|
||||
<int-flow:input-port name="input2" channel="subflow-input2">
|
||||
<int-flow:description></int-flow:description>
|
||||
</int-flow:input-port>
|
||||
<int-flow:output-port name="output2" channel="subflow-output2">
|
||||
<int-flow:description></int-flow:description>
|
||||
</int-flow:output-port>
|
||||
</int-flow:port-mapping>
|
||||
<int-flow:output-port name="output"
|
||||
channel="subflow-output" />
|
||||
|
||||
<int-flow:port-mapping-ref bean="portConfig2" />
|
||||
</int-flow:port-mapping>
|
||||
|
||||
</int-flow:flow-configuration>
|
||||
<int-flow:port-mapping-ref bean="portConfig1" />
|
||||
|
||||
<int-flow:port-mapping>
|
||||
<int-flow:input-port name="input2" channel="subflow-input2" />
|
||||
<int-flow:output-port name="output2" channel="subflow-output2"/>
|
||||
</int-flow:port-mapping>
|
||||
<int-flow:port-mapping>
|
||||
<int-flow:input-port name="input2"
|
||||
channel="subflow-input2" />
|
||||
<int-flow:output-port name="output2"
|
||||
channel="subflow-output2" />
|
||||
</int-flow:port-mapping>
|
||||
<int-flow:port-mapping-ref bean="portConfig2" />
|
||||
</int-flow:flow-configuration>
|
||||
|
||||
<int-flow:port-mapping>
|
||||
<int-flow:input-port name="input2" channel="subflow-input2" />
|
||||
<int-flow:output-port name="output2"
|
||||
channel="subflow-output2" />
|
||||
</int-flow:port-mapping>
|
||||
</beans>
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
<?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:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-flow="http://www.springframework.org/schema/integration/flow"
|
||||
xmlns:util="http://www.springframework.org/schema/util"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/flow http://www.springframework.org/schema/integration/flow/spring-integration-flow-2.0.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
|
||||
|
||||
<util:properties id="flowProperties">
|
||||
<prop key="key2">val1</prop>
|
||||
</util:properties>
|
||||
|
||||
<!-- Instantiate the flow -->
|
||||
<int-flow:flow id="subflow3" help="true" referenced-bean-locations="classpath:ref-bean-config.xml" properties="flowProperties"/>
|
||||
|
||||
</beans>
|
||||
@@ -11,18 +11,9 @@
|
||||
|
||||
<int-flow:flow-configuration>
|
||||
<int-flow:port-mapping>
|
||||
<int-flow:input-port name="gateway-input"
|
||||
channel="subflow-input">
|
||||
<int-flow:description></int-flow:description>
|
||||
</int-flow:input-port>
|
||||
<int-flow:output-port name="gateway-output"
|
||||
channel="hello-output">
|
||||
<int-flow:description></int-flow:description>
|
||||
</int-flow:output-port>
|
||||
<int-flow:output-port name="gateway-discard"
|
||||
channel="world-output">
|
||||
<int-flow:description></int-flow:description>
|
||||
</int-flow:output-port>
|
||||
<int-flow:input-port name="gateway-input" channel="subflow-input"/>
|
||||
<int-flow:output-port name="gateway-output" channel="hello-output"/>
|
||||
<int-flow:output-port name="gateway-discard" channel="world-output"/>
|
||||
</int-flow:port-mapping>
|
||||
</int-flow:flow-configuration>
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
<int-flow:input-port name="input" channel="subflow-input" />
|
||||
<int-flow:output-port name="output" channel="subflow-output" />
|
||||
</int-flow:port-mapping>
|
||||
<int-flow:referenced-bean id="refbean" required="true" />
|
||||
</int-flow:flow-configuration>
|
||||
|
||||
<int:channel id="subflow-output" />
|
||||
@@ -1,37 +0,0 @@
|
||||
<?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:util="http://www.springframework.org/schema/util"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:int-flow="http://www.springframework.org/schema/integration/flow"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd
|
||||
http://www.springframework.org/schema/integration/flow http://www.springframework.org/schema/integration/flow/spring-integration-flow-2.0.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
|
||||
|
||||
<!-- Need to set ignore-unresolvable true or provide defaults for required properties -->
|
||||
<context:property-placeholder ignore-unresolvable="true"/>
|
||||
|
||||
<int-flow:flow-configuration>
|
||||
<int-flow:port-mapping>
|
||||
<int-flow:input-port name="input" channel="subflow-input">
|
||||
<int-flow:description>This optionally describes the flow</int-flow:description>
|
||||
</int-flow:input-port>
|
||||
<int-flow:output-port name="output" channel="subflow-output">
|
||||
<int-flow:description>This describes the purpose/ necessary conditions for this output</int-flow:description>
|
||||
</int-flow:output-port>
|
||||
</int-flow:port-mapping>
|
||||
|
||||
<int-flow:referenced-property id="key1" required="true">
|
||||
<int-flow:description>This is an example of a required property</int-flow:description>
|
||||
</int-flow:referenced-property>
|
||||
<int-flow:referenced-property id="key2" required="false">
|
||||
<int-flow:description>This is an example of an optional property</int-flow:description>
|
||||
</int-flow:referenced-property>
|
||||
</int-flow:flow-configuration>
|
||||
|
||||
<int:channel id="subflow-output" />
|
||||
|
||||
</beans>
|
||||
@@ -13,12 +13,8 @@
|
||||
|
||||
<int-flow:flow-configuration>
|
||||
<int-flow:port-mapping>
|
||||
<int-flow:input-port name="input" channel="subflow-input">
|
||||
<int-flow:description>This optionally describes the flow</int-flow:description>
|
||||
</int-flow:input-port>
|
||||
<int-flow:output-port name="output" channel="subflow-output">
|
||||
<int-flow:description>This describes the purpose/ necessary conditions for this output</int-flow:description>
|
||||
</int-flow:output-port>
|
||||
<int-flow:input-port name="input" channel="subflow-input"/>
|
||||
<int-flow:output-port name="output" channel="subflow-output"/>
|
||||
</int-flow:port-mapping>
|
||||
</int-flow:flow-configuration>
|
||||
|
||||
@@ -13,16 +13,9 @@
|
||||
|
||||
<int-flow:flow-configuration>
|
||||
<int-flow:port-mapping>
|
||||
<int-flow:input-port name="input" channel="subflow-input">
|
||||
<int-flow:description>This optionally describes the flow</int-flow:description>
|
||||
</int-flow:input-port>
|
||||
<int-flow:output-port name="output" channel="subflow-output">
|
||||
<int-flow:description>This describes the purpose/ necessary conditions for this output</int-flow:description>
|
||||
</int-flow:output-port>
|
||||
|
||||
<int-flow:output-port name="error" channel="errorChannel">
|
||||
<int-flow:description>This describes the purpose/ necessary conditions for this output</int-flow:description>
|
||||
</int-flow:output-port>
|
||||
<int-flow:input-port name="input" channel="subflow-input"/>
|
||||
<int-flow:output-port name="output" channel="subflow-output"/>
|
||||
<int-flow:output-port name="error" channel="errorChannel"/>
|
||||
</int-flow:port-mapping>
|
||||
</int-flow:flow-configuration>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.integration">
|
||||
<level value="debug" />
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<!-- Root Logger -->
|
||||
|
||||
Reference in New Issue
Block a user