6 Replies Latest reply on Mar 24, 2005 5:59 AM by thomas.diesler

    URL rewriting of wsdl includes

    thomas.diesler

      Hi folks,

      this thread is about the URLs that we rewrite in the wsdl for wsdl imports and schema includes. Lets look at JIRA issue JBWS-153 for this discussion

      The wsdl uses

       <wsdl:types>
       <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.dis-corp.com/xml/2005/ebiz">
       <xsd:include schemaLocation="schemas/get/Get.xsd"/>
       </xsd:schema>
       </wsdl:types>
      


      The wsdl is obtained through URL

      http://satellite:8080/ws4ee-jbws153/Order?wsdl

      and the include is rewritten as

       <wsdl:types>
       <xsd:schema targetNamespace="http://www.dis-corp.com/xml/2005/ebiz" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
       <xsd:include schemaLocation="/ws4ee-jbws153/Order?wsdl&amp;resource=schemas/get/Get.xsd"/>
       </xsd:schema>
       </wsdl:types>
      


      which VB.net does not understand.

      The issue is that the schemaLocation cannot be simply treated as relative URL because it results in

      http://satellite:8080/ws4ee-jbws153/schemas/get/Get.xsd

      which is obviously invalid.

      A solution recently suggested on the forums uses a predefined URL path to obtain the wsdl and its included artifacts, like this:

      http://satellite:8080/ws4ee-jbws153/Order/wsdl

      for the wsdl, and hence

      http://satellite:8080/ws4ee-jbws153/Order/schemas/get/Get.xsd

      for the included schema.

      The problem with this is that the web.xml defines the servlet mapping as

       <servlet-mapping>
       <servlet-name>Order</servlet-name>
       <url-pattern>/Order</url-pattern>
       </servlet-mapping>
      


      and not as

       <servlet-mapping>
       <servlet-name>Order</servlet-name>
       <url-pattern>/Order/*</url-pattern>
       </servlet-mapping>
      


      which BTW is disallowed by the WS4EE spec.

      The URL

      http://satellite:8080/ws4ee-jbws153/Order/schemas/get/Get.xsd

      is invalid and will not be redirected to the ServiceEndpointServlet for schema delivery to the client.

      Ok, we rewrite the web.xml anyway and might want to append the missing /*. Changeing .../Order?wsdl to .../Order/wsdl would break all clients which should not be done lilght heartedly.

      I seek your feedback on this "rewrite issue". Is there any possible way of avoiding complex parameter lists, which are not supported by .NET? How do other stacks do it?

        • 1. Re: URL rewriting of wsdl includes
          anil.saldhana

          Thomas,
          thanks for posting this issue. I spent few hours on Monday thinking over this(when I hacked something in ServiceEndpointServlet).

          I support the idea of not tinkering the schemaLocation in the published wsdl. It should be the way the author intended it to be.

          http://satellite:8080/ws4ee-jbws153/schemas/get/Get.xsd
          


          will be routed to the ServiceEndpointServlet and the following code can capture that it is a xsd request (code is not perfect)

          protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
           {
           String pathInfo = req.getPathInfo();
           if (pathInfo != null && (pathInfo.endsWith("xsd") || pathInfo.endsWith("XSD")))
           {
           ServiceEndpointInfo sepInfo = wsEndpoint.getServiceEndpointInfo();
           DeploymentInfo di = sepInfo.getDeploymentInfo();
           URL warURL = di.localUrl != null ? di.localUrl : di.url;
           String warUrl = warURL.toString();
           String pathToResource = "wsdl" + pathInfo;
           //TODO: Assumption is that the xsd files are relative to WEB-INF/wsdl
           URL xsdURL = new URL(warUrl + "WEB-INF/" + pathToResource);
           res.setContentType("text/xml");
           ServletOutputStream outputStream = res.getOutputStream();
           IOUtils.copyStream(outputStream, xsdURL.openStream());
           outputStream.close();
           }
          


          Just the way, we intercept "?wsdl" requests in the servlet and copy the wsdl content, we should provide a way to intercept xsd and "included" wsdl in the servlet.

          The only warning is that this approach has to be tested with multiple testcases.




          • 2. Re: URL rewriting of wsdl includes
            jason.greene

            Hi, I researched this a bit, and this is must definately a bug in the .NET wsdl.exe tool, as opposed to a decision not to support url params. It actually fetches the content correctly (ie sends the appropriate GET requests). What ends up happening is that it eventually errors complaining about the reuse of a targetNamespace (which is how xsd:include is supposed to work of course). I would bet the problem is that they internally enforce uniqueness of a given path to a specific namespace, and that their URL fetching code strips all url parameters causing the uniqueness check to fail.

            There are already known (slightly similar) issues with their include/import handling code, and there are 2 hotfixes available. I can't test them though because they are not publicly available (you have to obtain them from Microsoft support).

            I think we have to be careful about coping with other platform's bugs. Axis is a great example of taking that too far. IMO this problem is also very easy to work around. You can either publish the wsdl files through a differnt mechanism (using something like wsdl-publish-location), or you can download them, replace the urls, and pass the files over to wsdl.exe.

            On the other side, in this case it would not be too hard to define another servlet as Anil suggests (which should get us past the ws4ee spec requirement).

            -Jason

            • 3. Re: URL rewriting of wsdl includes
              anil.saldhana

              Jason's comments are within the boxes

              Hi, I researched this a bit, and this is must definately a bug in the .NET wsdl.exe tool, as opposed to a decision not to support url params. It actually fetches the content correctly (ie sends the appropriate GET requests). What ends up happening is that it eventually errors complaining about the reuse of a targetNamespace (which is how xsd:include is supposed to work of course). I would bet the problem is that they internally enforce uniqueness of a given path to a specific namespace, and that their URL fetching code strips all url parameters causing the uniqueness check to fail.
              

              Yes, the namespace specified for an xsd:include is either null or the same NS of the parent schema.

              I think we have to be careful about coping with other platform's bugs. Axis is a great example of taking that too far. IMO this problem is also very easy to work around. You can either publish the wsdl files through a differnt mechanism (using something like wsdl-publish-location), or you can download them, replace the urls, and pass the files over to wsdl.exe.
              


              I think the issue is not whether only .Net clients can see the xsd or wsdl includes. Its for all ws clients. I support your idea about not working around other platform's bugs. We should stick to what the specs say and tell the opposite end to reciprocate.



              On the other side, in this case it would not be too hard to define another servlet as Anil suggests (which should get us past the ws4ee spec requirement).
              


              Not another servlet. It is "ServiceEndPointServlet" which currently intercepts HTTP/GET requests with "?wsdl" param. I was suggesting that this servlet can intercept all GET requests and cater to .xsd or .wsdl requests.

              • 4. Re: URL rewriting of wsdl includes
                jason.greene

                 

                "anil.saldhana@jboss.com" wrote:

                I think the issue is not whether only .Net clients can see the xsd or wsdl includes. Its for all ws clients. I support your idea about not working around other platform's bugs. We should stick to what the specs say and tell the opposite end to reciprocate.


                As far the spec is concerned, schemaLocation is anyURI, which places no real restriction on the uri.

                I tested a few webservice clients to see how they handle it
                JWSDP - pass (already known)
                XMLSpy - pass
                Mono - pass (for those not familiar mono is a multiplatform .NET port, I find this amusing that Mono works and .NET doesn't)
                Gsoap(c/c++ soap api) - failed due to relative url
                Weblogic - failed due to relative url

                As you can see none of these failed due to uri parameters, however, 2 failed because they appear to want absolute urls. So now we have another problem to solve.

                -Jason





                • 5. Re: URL rewriting of wsdl includes
                  thomas.diesler


                  The reason why I rolled back the change in ServiceEndpointServlet as invalid was because the URL below will actually *not* be routed to the endpoint servlet


                  http://satellite:8080/ws4ee-jbws153/schemas/get/Get.xsd


                  Only requests to the exact URL


                  http://satellite:8080/ws4ee-jbws153/Order


                  will be seen by the ServiceEndpointServlet. You can't stip off '/Order' and you can't append anythig either without changing the <url-mapping> in web.xml.

                  In absense of an alternative solution that actually works lets stick to what we have, right?

                  I don't see the benefit in installing an alternative servlet for wsdl + include delivery when this can already be done through the ServiceEndpointServlet given the right URL parameters


                  • 6. Re: URL rewriting of wsdl includes
                    thomas.diesler

                    Thanks for your feedback & the good research