The interceptor-based solution provides a very flexible way of configuring timeouts for Apache CXF based SOAP clients.For custom timeout configuration per operation(Methods defined inside wsdl), we will use an interceptor that sets a MessageProperty. It must be configured in the right Phase, otherwise, the MessageProperty might not have an effect.
Java Interceptor :
package com.interceptor;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName;
import org.apache.cxf.interceptor.MessageSenderInterceptor;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
/**
* <p>
* An SOAPCustomTimeoutInterceptor {@link AbstractPhaseInterceptor} that
* timeout based on the QName of the operation.
* </p>
*
*/
public class SOAPCustomTimeoutInterceptor extends AbstractPhaseInterceptor<Message> {
/** Keep all timeouts per OperationName in milliseconds */
private Map<QName, Long> receiveTimeoutByOperationName = new HashMap<QName, Long>();
public SOAPCustomTimeoutInterceptor(String phase) {
super(phase);
addBefore(MessageSenderInterceptor.class.getName());
}
public SOAPCustomTimeoutInterceptor() {
this(Phase.PREPARE_SEND);
}
/**
* Setting timeout based on QName in message
*
* @param message
*/
@Override
public void handleMessage(Message message) {
final QName operationName = message.getExchange().getBindingOperationInfo().getName();
final Long receiveTimeout = receiveTimeoutByOperationName.get(operationName);
if (receiveTimeout != null) {
message.put(Message.RECEIVE_TIMEOUT, receiveTimeout);
}
}
public void setReceiveTimeoutByOperationName(Map<QName, Long>receiveTimeoutByOperationName) {
this.receiveTimeoutByOperationName = receiveTimeoutByOperationName;
}
}
This handleMessage takes a Map of operation QNames and timeout-values. If it finds a match, it configures the timeout, otherwise, it does nothing.
Spring Configuration :
<?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:cxf="http://camel.apache.org/schema/cxf"
xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/cxf
http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd
http://cxf.apache.org/transports/http/configuration
http://cxf.apache.org/schemas/configuration/http-conf.xsd">
<cxf:cxfEndpoint id="bookService"
address="http://locathost:8080/someServiceName"
serviceClass="someServiceClass" />
<cxf:outInterceptors>
<ref bean="timeoutPerOperation" />
</cxf:outInterceptors>
</cxf:cxfEndpoint>
<bean id="timeoutPerOperation" class="sample.camel.CustomTimeoutInterceptor"
<property name="receiveTimeoutByOperationName">
<map key-type="javax.xml.namespace.QName" value-type="java.lang.Long">
<entry value="600">
<key>
<bean class="javax.xml.namespace.QName" factory-method="valueOf">
<constructor-arg value="{http://tempuri.org/}someMethod" />
</bean>
</key>
</entry>
</map>
</property>
</bean>
</beans>
Above configuration defines timeout per operation wise.You can add N entries inside the map with different with operations.{http://tempuri.org/} - is target namespace defined in WSDL file.tns defines the target name space.
example : xmlns:tns="http://tempuri.org/"
someMethod - is operation name defined in WSDL file.Inside portType name tag, you can find all opertion name(method name).
No comments:
Post a Comment