Howto: Configure Spring-WS to publish WSDL files with a '?WSDL' style URL?
I am trying to configure web service proxying using Mule ESB.
I am attempting to do this using Mule's WSProxyService, but after stepping through the corresponding code (with the debugger), it is clear that this class replaces endpoint addresses.
The problem is Spring-WS WSDL addresse开发者_StackOverflows are of the style http://xxxx/xxxx.wsdl, but WSProxyService expects http://xxxx/xxxx?wsdl or http://xxxx/xxxx&wsdl. It replaces the remote endpoint addresses with the local WSDL address; it cuts the remote WSDL address at the question mark i.e. '?WSDL' is intended to be chopped off, so to create the search term. But because of Spring-WS, this does not work.
To break it down:
WSProxyService ends up trying to use
http://xxxx/xxxx.wsdl
to replace
http://xxxx/xxxx
with
http://yyyy/yyyy
which fails... leading to actual web service call going direct and not through the proxy.
Has anyone ever noticed/solved this problem??
Cheers, Darren
How about a servlet filter in front of the Spring WS servlet that checks the url and the params?
In case of a match, you return the WSDL, otherwise you let the request through as if nothing happened.
This should be trivial to implement and will fill your need, if you absolutely must have the url of the WS + ?WSDL appended to it.
Here is the code:
public class WsdlQueryCompatibilityFilter implements Filter {
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
// do nothing
}
@Override
public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
throws IOException, ServletException {
final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
if ("GET".equals(httpServletRequest.getMethod())
&& "wsdl".equalsIgnoreCase(httpServletRequest.getQueryString())) {
httpServletRequest.getSession().getServletContext().getRequestDispatcher("/ws.wsdl")
.forward(request, response);
} else {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
// do nothing
}
}
You can also use a HttpServletRequestWrapper to handle the ?wsdl extension and let the server handle the request:
@Component
public class WsdlQuestionMarkSuffixFilter implements javax.servlet.Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
if ("wsdl".equalsIgnoreCase(httpRequest.getQueryString())) {
HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(httpRequest) {
@Override
public String getQueryString() {
return null;
}
@Override
public String getRequestURI() {
return super.getRequestURI() + ".wsdl";
}
};
chain.doFilter(requestWrapper, response);
} else {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
}
This may be applicable:
http://forum.springsource.org/showpost.php?p=101967&postcount=4
No, the ?WSDL is a way to get a WSDL of a class. In SWS, a service is not implemented as a class.
You could create a class that implements Filter
, create doFilter
method that intercept the request and get the URL if it ends with "wsdl"
, then forward the request to Spring default URL ".wsdl"
cleaning up the query string. Something like this:
@Component
public class QuestionMarkFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
if (request.getQueryString() != null && request.getQueryString().toLowerCase().endsWith("wsdl")) {
request.getRequestDispatcher("/your/service/here.wsdl?").forward(request, servletResponse);
} else {
chain.doFilter(servletRequest, servletResponse);
}
}
@Override
public void init(FilterConfig filterConfig) { }
@Override
public void destroy() { }
}
精彩评论