问题
I am building a Proof of Concept showcasing the end-to-end flow of an XML-based RESTful application built with Spring Integration, the overall idea being the following:
1) A HTTP Inbound Gateway that accepts incoming requests from the calling client
2) A set of @Router, @ServiceActivator, @Splitter & @Aggregator artifacts to process the incoming request and send a set of possible responses (the response XSD has optional elements inside a parent element that get populated based on the use-case) back to the calling client
I tested the flow on a local Tomcat 7.0.68 instance using Chrome's Advanced REST client extension and it always works fine the 1st time and that's the end of it.
Every test thereafter fails in the exact same way - after the final invocation of the @CorrelationStrategy method in the Aggregator, the flow ends with just this message, "No reply received within timeout".
The docs (http://docs.spring.io/spring-integration/docs/4.3.8.RELEASE/reference/htmlsingle/#http-timeout) say that for an HTTP Inbound Gateway, both the timeout properties default to 1000ms. I actually did try to manually set reply-timeout to 50000 but it didn't work.
Also, http://docs.spring.io/spring-integration/docs/4.3.8.RELEASE/reference/htmlsingle/#aggregator-config says, "The timeout interval to wait when sending a reply Message to the output-channel or discard-channel. Defaults to -1 - blocking indefinitely"
Since the failure seems to do with Spring Integration relying on some default timeout, can someone please let me know if there is anything else to try from my side?
Here are the most relevant pieces of code from my project:
Context file: product-integration.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:int="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:int-stream="http://www.springframework.org/schema/integration/stream"
xmlns:int-http="http://www.springframework.org/schema/integration/http"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/integration/stream
http://www.springframework.org/schema/integration/stream/spring-integration-stream.xsd
http://www.springframework.org/schema/integration/http
http://www.springframework.org/schema/integration/http/spring-integration-http.xsd ">
<int:annotation-config/>
<context:component-scan base-package="com.amb.splitteraggregator"/>
<!-- POST -->
<int-http:inbound-gateway request-channel="gatewayProductRequests"
reply-channel="gatewayProductResponses"
supported-methods="POST"
path="/product"
request-payload-type="java.lang.Stringe>
<int-http:request-mapping consumes="application/xml" produces="application/xml"/>
</int-http:inbound-gateway>
<int:channel id="gatewayProductResponses" />
<int:channel id="validatedProductRequests" />
<int:channel id="upstreamProductResponses" />
<int:channel id="downStreamProductRequests" />
<int:channel id="downStreamRawProductsAndRequest" />
<int:channel id="downStreamProductRequestBatches" />
<int:channel id="compositeMessagesWithResponse" />
<int:channel id="compositeMessagesForAggregation" />
<int:channel id="compositeMessagesWithRawProductsAndRequestOrResponse" />
Aggregator: ProductAggregator.java
@MessageEndpoint
public class ProductAggregator {
final static Logger logger = Logger.getLogger(ProductAggregator.class);
@Autowired
ProductServiceHelper productServiceHelper;
@Aggregator(inputChannel="compositeMessagesForAggregation", outputChannel="upstreamProductResponses", sendTimeout="10000")
public Message<Composite> generateAggregatedResponse(List<Message<Composite>> listOfCompositeMessagesForAggregation) {
logger.info("generateAggregatedResponse :: START");
PRODUCTRESPONSE productResponse = new PRODUCTRESPONSE();
PRODUCTRESPONSEDATA productResponseData = new PRODUCTRESPONSEDATA();
ERROR error = new ERROR();
PRODUCTRESPONSE productResponseInComposite = null;
List<PRODUCT> listOfProductsInComposite = null;
List<PRODUCT> listOfProductsToReturn = new ArrayList<PRODUCT>();
StringBuilder errorsToReturn = new StringBuilder();
String uuid = null;
for(Message<Composite> compositeMessage : listOfCompositeMessagesForAggregation) {
productResponseInComposite = compositeMessage.getPayload().getProductResponse();
if (null != productResponseInComposite.getPRODUCTRESPONSEDATA()) {
uuid = productResponseInComposite.getPRODUCTRESPONSEDATA().getUuid();
listOfProductsInComposite = productResponseInComposite.getPRODUCTRESPONSEDATA().getPRODUCT();
listOfProductsToReturn.addAll(listOfProductsInComposite);
} else if (null != productResponseInComposite.getERROR()) {
errorsToReturn.append(productResponseInComposite.getERROR().getErrorMsgCode());
errorsToReturn.append(",");
}
}
if (null != listOfProductsToReturn && !listOfProductsToReturn.isEmpty()) {
productResponseData.getPRODUCT().addAll(listOfProductsToReturn);
productResponseData.setUuid(uuid);
productResponse.setPRODUCTRESPONSEDATA(productResponseData);
}
if (errorsToReturn.length() != 0) {
error.setErrorMsgCode(errorsToReturn.toString());
error.setUuid(uuid);
productResponse.setERROR(error);
}
Composite compositeWithAggregatedResponse = productServiceHelper.buildComposite(false, productResponse);
Message<Composite> compositeMessageWithAggregatedResponse = MessageBuilder.withPayload(compositeWithAggregatedResponse).build();
logger.info("generateAggregatedResponse :: END");
return compositeMessageWithAggregatedResponse;
}
@CorrelationStrategy
public UUID correlateByUUID(Message<Composite> compositeMessageForAggregation) {
logger.info("correlateByUUID :: START");
logger.info("Correlation by UUID done");
logger.info("correlateByUUID :: END");
UUID correlationUUID = null;
if (null != compositeMessageForAggregation.getPayload().getProductResponse().getPRODUCTRESPONSEDATA()) {
correlationUUID = UUID.fromString(compositeMessageForAggregation.getPayload().getProductResponse().getPRODUCTRESPONSEDATA().getUuid());
} else if (null != compositeMessageForAggregation.getPayload().getProductResponse().getERROR()) {
correlationUUID = UUID.fromString(compositeMessageForAggregation.getPayload().getProductResponse().getERROR().getUuid());
}
return correlationUUID;
}
}
Custom composite object moving through the channels: Composite.java
public class Composite {
private PRODUCTREQUEST productRequest;
private PRODUCTRESPONSE productResponse;
private List<RawProduct> listOfRawProducts;
private boolean isError;
public Composite(boolean isError, PRODUCTREQUEST productRequest) {
this.isError = isError;
this.productRequest = productRequest;
}
public Composite(boolean isError, PRODUCTRESPONSE productResponse) {
this.isError = isError;
this.productResponse = productResponse;
}
public Composite(boolean isError, List<RawProduct> listOfRawProducts) {
this.isError = isError;
this.listOfRawProducts = new ArrayList<RawProduct>(listOfRawProducts);
}
public Composite(boolean isError, PRODUCTREQUEST productRequest, List<RawProduct> listOfRawProducts) {
this.isError = isError;
this.productRequest = productRequest;
this.listOfRawProducts = new ArrayList<RawProduct>(listOfRawProducts);
}
public PRODUCTREQUEST getProductRequest() {
return productRequest;
}
public PRODUCTRESPONSE getProductResponse() {
return productResponse;
}
public boolean isError() {
return isError;
}
public List<RawProduct> getListOfRawProducts() {
return this.listOfRawProducts;
}
}
pom.xml
<modelVersion>4.0.0</modelVersion>
<groupId>com.amb</groupId>
<artifactId>splitteraggregator</artifactId>
<name>SpringWebSplitterAggregator</name>
<packaging>war</packaging>
<version>1.0.0-BUILD-SNAPSHOT</version>
<properties>
<java-version>1.7</java-version>
<org.springframework-version>4.3.7.RELEASE</org.springframework-version>
<spring.integration.version>4.3.8.RELEASE</spring.integration.version>
<org.aspectj-version>1.6.10</org.aspectj-version>
<org.slf4j-version>1.6.6</org.slf4j-version>
<log4j.version>1.2.17</log4j.version>
<junit.version>4.11</junit.version>
</properties>
<dependencies>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${org.springframework-version}</version>
<exclusions>
<!-- Exclude Commons Logging in favor of SLF4j -->
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<!-- Spring Integration -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>${spring.integration.version}</version>
</dependency>
<!-- Spring Integration Stream -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-stream</artifactId>
<version>${spring.integration.version}</version>
<!-- <scope>compile</scope> -->
</dependency>
<!-- Spring Integration HTTP -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-http</artifactId>
<version>${spring.integration.version}</version>
</dependency>
<!-- AspectJ -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${org.aspectj-version}</version>
</dependency>
<!-- Logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j-version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${org.slf4j-version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
<exclusions>
<exclusion>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
</exclusion>
<exclusion>
<groupId>javax.jms</groupId>
<artifactId>jms</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
<scope>compile</scope>
</dependency>
<!-- @Inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!-- Test -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<additionalProjectnatures>
<projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
</additionalProjectnatures>
<additionalBuildcommands>
<buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
</additionalBuildcommands>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<compilerArgument>-Xlint:all</compilerArgument>
<showWarnings>true</showWarnings>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>org.test.int1.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
Please let me know if more code snippets from my project are required - this is my first question on Stack Overflow so pardon me if there is any etiquette that I missed.
- Bharath
来源:https://stackoverflow.com/questions/43987748/spring-integration-aggregator-failing-no-reply-received-within-timeout-messa