Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 addresses 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

like image 483
Darren Bishop Avatar asked Oct 29 '09 14:10

Darren Bishop


4 Answers

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
    }
}
like image 166
Axel Fontaine Avatar answered Nov 01 '22 18:11

Axel Fontaine


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() {

    }
}
like image 40
Peter Knuts Avatar answered Nov 01 '22 17:11

Peter Knuts


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.

like image 1
Dave Avatar answered Nov 01 '22 19:11

Dave


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() { }
}
like image 1
jlucasps Avatar answered Nov 01 '22 19:11

jlucasps