Search code examples
javaweb-servicessoapjbossservlet-mapping

Remap JAX-WS address


My problem is that I have a web service that gets published by jboss at http://localhost:8080/A, where A is the service implementation class; I want a custom url http://localhost:8080/B/C/D.ws.

In the wsdl, soap:address is correctly set http://localhost:8080/B/C/D.ws.

During war deployment, service gets published at the "wrong" address:

INFO  [org.jboss.ws.cxf.metadata] Adding service endpoint metadata: id=org.example.ServiceImpl
 address=http://localhost:8080/ServiceImpl
 ...

The best I got was jboss publishing the ws at the wrong url, and then the address changed through a servlet; but a SOAP call to the "right" url returned a 404. This is /WEB-INF/cxf-servlet.xml:

<?xml ... >
<beans ...
    xmlns:jaxws="http://cxf.apache.org/jaxws" ... >
    <jaxws:endpoint
        id="someId"
        implementor="org.example.ServiceImpl"
        address="/B/C/D.ws" />
</beans>

With the following url-pattern in web.xml:

<servlet>
    <servlet-name>cxf</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>cxf</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

This was the log:

17:41:53,648 INFO  [org.jboss.ws.cxf.metadata] Adding service endpoint metadata: id=org.example.ServiceImpl
 address=http://localhost:8080/ServiceImpl
 ...
17:41:59,307 INFO  [org.apache.cxf.service.factory.ReflectionServiceFactoryBean] Creating Service {... targetNamespace ...}ServiceImplService from class org.example.ServicePort
17:41:59,572 INFO  [org.apache.cxf.endpoint.ServerImpl] Setting the server's publish address to be /B/C/D.ws

Thanks


Solution

  • I had a similar problem and resolved with this approach.

    In the web.xml overwrites the url pattern for the service implementation, like this:

    <servlet>
        <servlet-name>ServiceImpl</servlet-name>
        <servlet-class>org.example.ServiceImpl</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ServiceImpl</servlet-name>
        <url-pattern>/B/C/D.ws</url-pattern>
    </servlet-mapping>
    

    Like you I use the property address to set the service publish address

    This works for my in JBoss AS 6.1 (cxf 2.3.1)


    EDIT:

    To validate that this works correctly in JBoss EAP 6.2, create a simple web project based on jboss-eap-quickstarts/helloworld-ws/ as follows:

    Service Class:

    @WebService(serviceName = "HelloWorldService", portName = "HelloWorld", name = "HelloWorld", endpointInterface = "org.jboss.as.quickstarts.wshelloworld.HelloWorldService", targetNamespace = "http://www.jboss.org/jbossas/quickstarts/wshelloworld/HelloWorld")
    public class HelloWorldServiceImpl implements HelloWorldService {
    
        @Override
        public String sayHello() {
            return "Hello World!";
        }
    
        @Override
        public String sayHelloToName(final String name) {
    
            /* Create a list with just the one value */
            final List<String> names = new ArrayList<String>();
            names.add(name);
    
            return sayHelloToNames(names);
        }
    
        @Override
        public String sayHelloToNames(final List<String> names) {
            return "Hello " + createNameListString(names);
        }
    
        /**
         * Creates a list of names separated by commas or an and symbol if its the last separation. This is then used to say hello to
         * the list of names.
         * 
         * i.e. if the input was {John, Mary, Luke} the output would be John, Mary & Luke
         * 
         * @param names A list of names
         * @return The list of names separated as described above.
         */
        private String createNameListString(final List<String> names) {
    
            /*
             * If the list is null or empty then assume the call was anonymous.
             */
            if (names == null || names.isEmpty()) {
                return "Anonymous!";
            }
    
            final StringBuilder nameBuilder = new StringBuilder();
            for (int i = 0; i < names.size(); i++) {
    
                /*
                 * Add the separator if its not the first string or the last separator since that should be an and (&) symbol.
                 */
                if (i != 0 && i != names.size() - 1)
                    nameBuilder.append(", ");
                else if (i != 0 && i == names.size() - 1)
                    nameBuilder.append(" & ");
    
                nameBuilder.append(names.get(i));
            }
    
            nameBuilder.append("!");
    
            return nameBuilder.toString();
        }
    }
    

    web.xml:

    <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
        <servlet>
            <servlet-name>HelloWorldService</servlet-name>
            <servlet-class>org.jboss.as.quickstarts.wshelloworld.HelloWorldServiceImpl</servlet-class>
        </servlet>
    
        <servlet-mapping>
            <servlet-name>HelloWorldService</servlet-name>
            <url-pattern>/C/D.ws</url-pattern>
        </servlet-mapping>
    
    </web-app>
    

    To overwrite the root context of the application using the jboss-web.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <jboss-web xmlns="http://www.jboss.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="  
          http://www.jboss.com/xml/ns/javaee  
          http://www.jboss.org/j2ee/schema/jboss-web_5_1.xsd">
        <context-root>B</context-root>
    </jboss-web> 
    

    Getting the following result for the deploy:

    11:24:10,371 INFO  [org.jboss.ws.cxf.metadata] (MSC service thread 1-7) JBWS024061: Adding service endpoint metadata: id=HelloWorldService
     address=http://localhost:8080/B/C/D.ws
     implementor=org.jboss.as.quickstarts.wshelloworld.HelloWorldServiceImpl
     serviceName={http://www.jboss.org/jbossas/quickstarts/wshelloworld/HelloWorld}HelloWorldService
     portName={http://www.jboss.org/jbossas/quickstarts/wshelloworld/HelloWorld}HelloWorld
     annotationWsdlLocation=null
     wsdlLocationOverride=null
     mtomEnabled=false
    11:24:10,583 INFO  [org.apache.cxf.service.factory.ReflectionServiceFactoryBean] (MSC service thread 1-7) Creating Service {http://www.jboss.org/jbossas/quickstarts/wshelloworld/HelloWorld}HelloWorldService from class org.jboss.as.quickstarts.wshelloworld.HelloWorldService
    11:24:10,944 INFO  [org.apache.cxf.endpoint.ServerImpl] (MSC service thread 1-7) Setting the server's publish address to be http://localhost:8080/B/C/D.ws
    11:24:11,009 INFO  [org.jboss.ws.cxf.deployment] (MSC service thread 1-7) JBWS024074: WSDL published to: file:/C:/desarrollo/java/jboss/jboss-eap-6.2/standalone/data/wsdl/jboss-helloworld-ws.war/HelloWorldService.wsdl
    11:24:11,014 INFO  [org.jboss.as.webservices] (MSC service thread 1-3) JBAS015539: Iniciando service jboss.ws.port-component-link
    11:24:11,026 INFO  [org.jboss.as.webservices] (MSC service thread 1-3) JBAS015539: Iniciando service jboss.ws.endpoint."jboss-helloworld-ws.war".HelloWorldService
    

    When I access to http://localhost:8080/B/C/D.ws?wsdl

    <wsdl:definitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://www.jboss.org/jbossas/quickstarts/wshelloworld/HelloWorld" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:ns1="http://schemas.xmlsoap.org/soap/http" name="HelloWorldService" targetNamespace="http://www.jboss.org/jbossas/quickstarts/wshelloworld/HelloWorld">
    
    <!-- ... -->
      <wsdl:service name="HelloWorldService">
        <wsdl:port binding="tns:HelloWorldServiceSoapBinding" name="HelloWorld">
          <soap:address location="http://localhost:8080/B/C/D.ws"/>
        </wsdl:port>
      </wsdl:service>
    </wsdl:definitions>
    

    You can see the source of this example: https://github.com/fedesierr/jaxws-endpointurl

    Another alternative is to use a reverse proxy (apache) and set the url in the soap:address.

    I hope this help.