Reputation: 1
I am working with a RedHat Fuse adapter in a Java DSL using Apache Camel and CXF. I am trying to handle relatively large incoming SOAP messages, but I'm running into a timeout issue. The sender then receives a 500 Internal Server Error, even though the processing is going fine on our end. Sometimes the processing time is a bit faster, then the sending party receives a 200, and all is well.
It seems CXF or Camel has some kind of timeout that occurs ('The OUT message' takes too long), but it happens too fast for us. The problem seems to be that I can not find where and how this timeout of 30000ms is set, and how to change it.
Any help or pointers on CXF or Camel would be appreciated here, like what exactly this timeout is, or which property changes it.
Below is the error message I'm receiving, and the route I'm using:
26-09-24 07:52:12.575 [XNIO-1 task-1] WARN o.a.cxf.phase.PhaseInterceptorChain - Application {http://example.namespace.com/wsdl/Service/V1}MyService#{http://example.namespace.com/wsdl/Service/V1}processRequest has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: The OUT message was not received within: 30000 millis. Exchange[91F3A9AAC0D6092-0000000000000000]
at org.apache.camel.component.cxf.jaxws.CxfConsumer$CxfConsumerInvoker.checkFailure(CxfConsumer.java:350)
at org.apache.camel.component.cxf.jaxws.CxfConsumer$CxfConsumerInvoker.setResponseBack(CxfConsumer.java:322)
at org.apache.camel.component.cxf.jaxws.CxfConsumer$CxfConsumerInvoker.asyncInvoke(CxfConsumer.java:212)
at org.apache.camel.component.cxf.jaxws.CxfConsumer$CxfConsumerInvoker.invoke(CxfConsumer.java:161)
...
Caused by: org.apache.camel.ExchangeTimedOutException: The OUT message was not received within: 30000 millis. Exchange[91F3A9AAC0D6092-0000000000000000]
at org.apache.camel.component.cxf.jaxws.CxfConsumer$CxfConsumerInvoker.asyncInvoke(CxfConsumer.java:210)
... 105 common frames omitted
And here is the route I am using (Java DSL):
package com.example.routes;
import com.example.logging.CustomLogger;
import com.example.beans.TransformData;
import com.example.beans.UUIDGenerator;
import com.example.configuration.ExceptionConnectionErrorResolver;
import com.example.webservices.WebServiceConfig;
import org.apache.camel.Exchange;
import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.builder.ThreadPoolBuilder;
import org.apache.camel.CamelContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.concurrent.ExecutorService;
@Component
public class MyServiceRoute extends RouteBuilder {
@Autowired
CustomLogger customLogger;
@Autowired
WebServiceConfig webServiceConfig;
@Autowired
UUIDGenerator generator;
@Autowired
ExceptionConnectionErrorResolver exceptionConnectionErrorResolver;
@Override
public void configure() throws Exception {
CamelContext context = getContext();
ExecutorService executorService = new ThreadPoolBuilder(context)
.poolSize(150)
.maxPoolSize(150)
.maxQueueSize(-1)
.build("SplitThreadPool");
from("cxf:bean:processRequestSoapEndpoint?exchangePattern=InOnly").routeId("myServiceRoute")
.onException(org.apache.camel.support.processor.validation.SchemaValidationException.class,org.xml.sax.SAXParseException.class,org.apache.camel.ValidationException.class).id("onTransformationException")
.handled(true)
.bean(customLogger, "logCode(${exchangeProperty.BreadCrumb}, CODE-992, Validation of message failed. ${exception.message})").id("logCode992")
.process(exchange -> {
Exception exception = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
exchange.getContext().createProducerTemplate()
.sendBody("log:error?showAll=true&multiline=true",
"CODE-992 Validation Error: " + exception.getMessage() + "\nStack Trace:\n" + getStackTrace(exception));
})
.end()
.onException(javax.xml.transform.TransformerException.class).id("OnValidationException")
.handled(true)
.bean(customLogger, "logCode(${exchangeProperty.BreadCrumb}, CODE-032)").id("logCode032")
.end()
.onException(org.apache.cxf.interceptor.Fault.class,org.apache.camel.http.base.HttpOperationFailedException.class).id("onEndpointException")
.handled(true)
.bean(customLogger, "logCode(${exchangeProperty.BreadCrumb},CODE-043)").id("logCode043")
.bean(customLogger, "logCode(${exchangeProperty.BreadCrumb},CODE-996,Error: ${exception.message})").id("logCode996")
.end()
.onException(java.net.ConnectException.class,org.apache.http.conn.HttpHostConnectException.class).id("onConnectionEndpoint")
.handled(true)
.maximumRedeliveries(exceptionConnectionErrorResolver.getMaxRedeliveries())
.redeliveryDelay(exceptionConnectionErrorResolver.getRedeliveryDelay())
.retryAttemptedLogLevel(LoggingLevel.WARN)
.bean(customLogger, String.format("logCode(${exchangeProperty.BreadCrumb},CODE-042,%s)",webServiceConfig.processRequestSoapEndpointBackend().getAddress())).id("logCode042")
.bean(customLogger, "logCode(${exchangeProperty.BreadCrumb},CODE-996,Error: ${exception.message})").id("logCode996")
.end()
.onException(java.lang.Exception.class).id("onGeneralException")
.handled(true)
.bean(customLogger, "logCode(${exchangeProperty.BreadCrumb},CODE-000)").id("logCode000")
.bean(customLogger, "logCode(${exchangeProperty.BreadCrumb},CODE-996,Error: ${exception.message})").id("logUnexpectedException")
.end()
.bean(customLogger, "logStart").id("logStart")
.bean("PropertyGenerator").id("setProperties")
.setProperty("messageHeaderProperty", xpath("/ns:processRequestHeader", XpathNameSpaces.namespaces)).id("setMessageHeaderProperty")
.setProperty("voorloopRecordProperty", xpath("/ns:processRequestBody/ns:businessData/ns:record", XpathNameSpaces.namespaces)).id("setVoorloopRecordProperty")
.to("validator:classpath:services/ExampleService/xsd/BM/V1/ExampleMessage.xsd").id("validateExampleMessage")
.bean(customLogger, "logCode(${exchangeProperty.BreadCrumb}, CODE-092)").id("logCode092")
.split(xpath("/ns:processRequestBody/ns:businessData/ns:record/ns:person", XpathNameSpaces.namespaces)).parallelProcessing().executorService(executorService).stopOnException().id("splitPerPerson")
.bean(TransformData.class).id("setSplittedBody")
.process(generator).id("setUUIDProp")
.setProperty("timestampProperty").simple("${date:now:yyyy-MM-dd'T'HH:mm:ss.SSS'Z'}").id("setTimestamp")
.to("xslt:classpath:/transformations/ExampleTransform.xsl").id("transformExample")
.to("validator:classpath:services/ExampleService/xsd/BAS/V1/ExampleValidation.xsd").id("validateExampleValidation")
.removeHeaders("*", "BreadCrumb").id("removeHeaders")
.to("cxf:bean:processRequestSoapEndpointBackend").id("toSoapEndpoint")
.bean(customLogger, String.format("logCode(${exchangeProperty.BreadCrumb}, CODE-041,%s)",webServiceConfig.processRequestSoapEndpointBackend().getAddress())).id("logCode041")
.bean(customLogger, "logEnd").id("logCodeEnd");
}
private String getStackTrace(Exception exception) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
exception.printStackTrace(pw);
return sw.toString();
}
}
We've tried speeding up the processing time using parallel processing and tweaking small stuff to try to get under 30 seconds, but the real issue is that this timeout is too short.
The problem seems to be that I can not find where and how this timeout of 30000ms is set, and how to change it. I've tried some things like cxf.timeout=60000
, but it seems CXF does not have this property.
Things like Cxf.ConnectionTimeOut
and Cxf.ReceiveTimeout
seem to refer to HTTP timeout, but I think this is some kind of internal timeout in the application.
Upvotes: 0
Views: 70
Reputation: 1
Turns out this is the 'continuationTimeout'.
Changed the used cxf endpoint in my route like so:
from("cxf:bean:processRequestSoapEndpoint?continuationTimeout=60000")
See also the answer here:
Camel CXF: Soap client timeout
Upvotes: 0