I'm looking for a way to forward http header information along with the SOAP message to the Spring Endpoint in order to get access to details like IP address, etc.
Relevant web.xml:
<servlet>
<servlet-name>SoapHost</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SoapHost</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>
SoapHost-servlet.xml:
<?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:context="http://www.springframework.org/schema/context"
xmlns:sws="http://www.springframework.org/schema/web-services"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/web-services
http://www.springframework.org/schema/web-services/web-services-2.0.xsd">
<!-- To detect @Endpoint -->
<sws:annotation-driven />
<!-- To detect @Service, @Component etc -->
<context:component-scan base-package="za.co.mycee.soaphost" />
<!-- To generate dynamic wsdl for SoapHost Services -->
<sws:dynamic-wsdl
id="SoapHost"
portTypeName="SoapHost"
locationUri="/ws/SoapHost"
targetNamespace="http://www.mycee.co.za/SoapHost">
<sws:xsd location="/WEB-INF/SoapHost.xsd" />
</sws:dynamic-wsdl>
<!-- Validate Request and Response -->
<sws:interceptors>
<bean id="MyCeeSoapHost" class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schema" value="/WEB-INF/SoapHost.xsd" />
<property name="validateRequest" value="true" />
<property name="validateResponse" value="true" />
</bean>
</sws:interceptors>
</beans>
Endpoint:
@Endpoint
public class ...Endpoint {
@Autowired
...Service ...Service;
@Autowired
...Service ...Service;
@Autowired
...Service ...Service;
@ResponsePayload
@PayloadRoot(localPart = "...Request", namespace = "http://www.mycee.co.za/SoapHost")
public ...Response do...(@RequestPayload ...Request request) {
...
// get IP address here
// get some other info from headers here
...
}
}
I've tried adding it as one of the parameters:
@ResponsePayload
@PayloadRoot(localPart = "...Request", namespace = "http://www.mycee.co.za/SoapHost")
public ...Response do...(
@RequestPayload ...Request request,
HttpServletRequest httpServletRequest) {
but that returns an error in the XML response: "No adapter for endpoint" and "Is your endpoint annotated with @Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint"
Sorry for not replying directly to your question, but why don't you put filter right before servlet? In this filter you can store IP or any other information in some context object, like ThreadLocal or similar.
I believe, that SOAP should know nothing about IP address. These are different abstraction layers. SOAP, by design, operates on SOAP Headers if some meta information is required.
Reply to comment from topic-starter:
No, it won't break Spring-WS flow because it just absolutely normal to put servlets behind filters. Filter is a plain javax.servlet.Filter
Example as requested:
Endpoint that is slightly modified version of Spring's example
@Endpoint
public class FilteredEndpoint {
@ResponsePayload
@PayloadRoot(localPart = "HolidayRequest", namespace = "http://mycompany.com/hr/schemas")
public void doRespose(@RequestPayload Element request) {
System.out.println(Context.ip.get());
}
}
Info is stored in Context object. Context uses ThreadLocal to hold data. It works because each request is handled by separate thread
public class Context {
public static ThreadLocal<String> ip = new ThreadLocal<String>();
}
Finally filter
public class MyHttpFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
Context.ip.set(request.getRemoteAddr());
chain.doFilter(request, response);
}
@Override
public void destroy() {}
}
And web.xml
<filter>
<filter-name>httpfilter</filter-name>
<filter-class>so.example.MyHttpFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>httpfilter</filter-name>
<url-pattern>/ws/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>SoapHost</servlet-name>
<servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class>
<init-param>
<param-name>transformWsdlLocations</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SoapHost</servlet-name>
<url-pattern>/ws/*</url-pattern>
</servlet-mapping>