The problem ist not spring. I think you will need a queue with elements containing the request and offering a response. But the response need to block until the element is dequed and processed. So the queue element looks like:
public class BlockingPair {
private final RequestBodyType request;
private ResponseBodyType response;
public BlockingPair(RequestBodyType request) {
this.request = request;
}
public RequestBodyType getRequest() {
return request;
}
public ResponseBodyType getResponse() {
while (response == null) {
Thread.currentThread().sleep(10);
}
return response;
}
public void setResponse(ResponseBodyType response) {
this.response = response;
}
}
The webservice enqueing creates the BlockingPair with its request body. Than pushes the BlockingPair element to the queue. Afterwards it creates the response getting the response body from the BlockingPair, but blocks.
The consumer deques one BlockingPair and sets the response body. From there the webservice continues writing the response.
You need three beans: webservice, a blocking queue and the consumer. Both webservice and consumer need the queue as bean property.
The queue and the consumer beans need to be planed in the application context (as initilialized by the ContextLoaderListener
). The queue needs a bean id to be references by the webservice (which has its own context, but the application context as a parent so the queue reference can be referenced):
Part of the web.xml
:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>service</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>service</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
The applicationContext.xml
contains two beans:
<bean id="queue" class="java.util.concurrent.LinkedBlockingQueue"/>
<bean id="consumer" class="...">
<property name="queue" ref="queue"/>
</bean>
The webservice has its own context definition, here service-servlet.xml
:
<bean id="endpoint" class="org.springframework.ws.server.endpoint....PayloadEndpoint">
<property name="queue" ref="queue"/>
</bean>
For more information on defining a spring ws endpoint, see the spring tutorial.
The consumer need to be a background task, so i would prefer quartz, for spring integration see here.