1 2 Previous Next 27 Replies Latest reply: Apr 13, 2011 12:15 AM by rakesh mehta RSS

Providing your own wsdl instead of the generated one.

David Owens Newbie

Alright, it took me a long time to put all the pieces together after searching the forums and jira. If you want to serve up your own wsdl instead of the generated one you do the following:

In the interface you specify the wsdlLocation:

@WebService(name = "Echo", targetNamespace = "http://echo/", wsdlLocation="META-INF/wsdl/EchoService.wsdl")


Then when you package your war file, you put the wsdl in the META-INF/wsdl directory of your war.

I apologize if this is obvious, but it took me a while to figure out.

Here is the full working example using top-down design:

First I started with EchoService.wsdl
<?xml version="1.0" encoding="UTF-8"?>
<definitions name='EchoService' targetNamespace='http://echo/' xmlns='http://schemas.xmlsoap.org/wsdl/' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:tns='http://echo/' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
 <types>
 <xs:schema targetNamespace='http://echo/' version='1.0' xmlns:tns='http://echo/' xmlns:xs='http://www.w3.org/2001/XMLSchema'>
 <xs:element name='echo' type='tns:echo'/>
 <xs:element name='echoResponse' type='tns:echoResponse'/>
 <xs:complexType name='echo'>
 <xs:sequence>
 <xs:element minOccurs='0' name='arg0' type='xs:string'/>
 </xs:sequence>
 </xs:complexType>
 <xs:complexType name='echoResponse'>
 <xs:sequence>
 <xs:element minOccurs='0' name='return' type='xs:string'/>
 </xs:sequence>
 </xs:complexType>
 </xs:schema>
 </types>
 <message name='Echo_echo'>
 <part element='tns:echo' name='echo'/>
 </message>
 <message name='Echo_echoResponse'>
 <part element='tns:echoResponse' name='echoResponse'/>
 </message>
 <portType name='Echo'>
 <operation name='echo' parameterOrder='echo'>
 <input message='tns:Echo_echo'/>
 <output message='tns:Echo_echoResponse'/>
 </operation>
 </portType>
 <binding name='EchoBinding' type='tns:Echo'>
 <soap:binding style='document' transport='http://schemas.xmlsoap.org/soap/http'/>
 <operation name='echo'>
 <soap:operation soapAction=''/>
 <input>
 <soap:body use='literal'/>
 </input>
 <output>
 <soap:body use='literal'/>
 </output>
 </operation>
 </binding>
 <service name='EchoService'>
 <documentation>Congrats! You have published your own WSDL!</documentation>
 <port binding='tns:EchoBinding' name='EchoPort'>
 <soap:address location='REPLACE_WITH_ACTUAL_URL'/>
 </port>
 </service>
</definitions>


Then I generated the java files using wsconsume:
$ wsconsume -k EchoService.wsdl
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java
echo/Echo.java
echo/EchoResponse.java
echo/EchoService.java
echo/Echo_Type.java
echo/ObjectFactory.java
echo/package-info.java


I promptly threw away EchoService.java because it's really for the client, not the server.

Next I implemented EchoImpl.java
package echo;

@javax.jws.WebService(endpointInterface="echo.Echo")
public class EchoImpl implements Echo
{
 public String echo(String arg0)
 {
 return arg0;
 }
}


Then I edited Echo.java and added wsdlLocation (bolded below)
package echo;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;


/**
 * JBossWS Generated Source
 * ....
 * JAX-WS Version: 2.0
 *
 */
@WebService(name = "Echo", targetNamespace = "http://echo/", wsdlLocation="META-INF/wsdl/EchoService.wsdl")
public interface Echo {


 /**
 *
 * @param arg0
 * @return
 * returns java.lang.String
 */
 @WebMethod
 @WebResult(targetNamespace = "")
 @RequestWrapper(localName = "echo", targetNamespace = "http://echo/", className = "echo.Echo_Type")
 @ResponseWrapper(localName = "echoResponse", targetNamespace = "http://echo/", className = "echo.EchoResponse")
 public String echo(
 @WebParam(name = "arg0", targetNamespace = "")
 String arg0);

}


Next I created a web.xml:
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
 version="2.4">

 <servlet>
 <servlet-name>echo</servlet-name>
 <servlet-class>echo.Echo</servlet-class>
 </servlet>

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

</web-app>


Then I packed them up into a echo.war:
META-INF/
META-INF/MANIFEST.MF
META-INF/wsdl/
META-INF/wsdl/EchoService.wsdl
WEB-INF/
WEB-INF/classes/
WEB-INF/classes/echo/
WEB-INF/classes/echo/Echo.class
WEB-INF/classes/echo/EchoImpl.class
WEB-INF/classes/echo/EchoResponse.class
WEB-INF/classes/echo/Echo_Type.class
WEB-INF/classes/echo/ObjectFactory.class
WEB-INF/classes/echo/package-info.class
WEB-INF/web.xml


Then I dropped it into the deploy directory.

When I looked at the log file, I saw it deployed my wsdl:
07:39:03,777 INFO [TomcatDeployer] deploy, ctxPath=/echo, warUrl=.../tmp/deploy/tmp45417echo-exp.war/
07:39:04,839 INFO [WSDLFilePublisher] WSDL published to: file:/D:/jboss/jboss-4.2.0.CR1/server/default/data/wsdl/echo.war/EchoService.wsdl
07:39:04,886 INFO [ServiceEndpointManager] WebService started: http://127.0.0.1:8080/echo


Instead of what it did when I didn't properly specify the wsdlLocation:
07:10:04,777 INFO [TomcatDeployer] undeploy, ctxPath=/echo, warUrl=.../tmp/deploy/tmp45397echo-exp.war/
07:10:06,449 INFO [TomcatDeployer] deploy, ctxPath=/echo, warUrl=.../tmp/deploy/tmp45400echo-exp.war/
07:10:06,730 INFO [WSDLFilePublisher] WSDL published to: file:/D:/jboss/jboss-4.2.0.CR1/server/default/data/wsdl/echo.war/EchoService45401.wsdl


Sure enough, going to http://127.0.0.1:8080/echo?wsdl displayed my wsdl, not the generated one.

Hope this helps some of you out there.

  • 1. Re: Providing your own wsdl instead of the generated one.
    Peter Johnson Master

    I did the same (see my post at http://www.jboss.com/index.html?module=bb&op=viewtopic&t=104664). All of this works fine. Have you tried to access the web service from a client yet? When I attempt to do this, the web services container attempts to instantiate the interface instead of the class, which of course fails miserably. My current hunch is that the web services container is ignoring the WebService annotation on the class (hence the reason why placing wsdlLocation there is ignored). Of course, no-one from the JBossWS team has replied to my post...

  • 2. Re: Providing your own wsdl instead of the generated one.
    David Owens Newbie

    Yeppers, just started doing the clinet, and go the same thing:

    07:39:04,886 INFO [ServiceEndpointManager] WebService started: http://127.0.0.1:8080/echo
    08:31:07,730 ERROR [SOAPFaultHelperJAXWS] SOAP request exception
    java.lang.InstantiationException: echo.Echo
     at java.lang.Class.newInstance0(Class.java:335)


    But I get my wsdl... now I have to figure out what I messed up now.

  • 3. Re: Providing your own wsdl instead of the generated one.
    Peter Johnson Master

    I have tried a wide variety of combinations of elements on the WebService annotation on both the class and the interface to no success. The only thing that works is deleting the interface, renaming the class to Echo.

    That (and the fact that the wsdlLocation has no effect when added the WebService on the class) is what lead me to think the container is ignoring the WebService annotation on the class - it is as if the endpointInterface element is being totally ignored.

  • 4. Re: Providing your own wsdl instead of the generated one.
    David Owens Newbie

    I'll try doing some of what you suggest and see what I can get to happen.

    Over here http://www.jboss.com/index.html?module=bb&op=viewtopic&t=99158
    dwin seems to have been able to make it happen. I wonder if s/he ran a client.

    dwin mentions

    you just have to ensure that the wsdl in wsdl location does not contradict the web service implementation.


    I'm not sure what exaclty s/he is referring to, but perhaps there is something in the hand coded wsdl which contradicts the annotation, thus cases this problem. Maybe by investigating the difference in the generated and hand coded, I can find the answer.

    Let me know if you get it working, and I will do the same.

  • 5. Re: Providing your own wsdl instead of the generated one.
    David Owens Newbie

     

    "ngtdave" wrote:

    07:39:04,886 INFO [ServiceEndpointManager] WebService started: http://127.0.0.1:8080/echo
    08:31:07,730 ERROR [SOAPFaultHelperJAXWS] SOAP request exception
    java.lang.InstantiationException: echo.Echo
     at java.lang.Class.newInstance0(Class.java:335)



    Alright, I get this error without the wsdlLocation change I made, so it's not that.

    BTW I'm using JBoss 4.2.0.CR1 with jbossws-1.2.0.GA (build=200703010320)
    and java 1.5.0_11-b03

  • 6. Re: Providing your own wsdl instead of the generated one.
    David Owens Newbie

    Alright, I got it working.

    First I changed my web.xml to use the impl bean:

    <servlet-class>echo.EchoImpl</servlet-class>

    per this discussion:
    http://www.jboss.com/index.html?module=bb&op=viewtopic&t=70837
    where Diesler says:
    So this is trying to instanciate an interface. Your web.xml should contain the endpoint impl bean not the SEI. Is that the case?


    but then I got this error:
    9:55:24,824 ERROR [ServiceEndpointDeployer] Cannot create service endpoint
    rg.jboss.ws.WSException: Cannot find port in wsdl: {http://echo/}EchoImplPort


    So then I remembered:
    https://jax-ws.dev.java.net/jax-ws-ea3/docs/annotations.html#2.1%20javax.jws.WebService%7Coutline
    specifies:
    javax.jws.WebService.portName - The wsdl:portName


    So I tried to change Echo.java to declare the port, but I got an error:
    09:56:05,683 ERROR [MainDeployer] Could not create deployment: file:/D:/jboss/jboss-4.2.0.CR1/server/default/deploy/echo.war
    org.jboss.deployment.DeploymentException: Cannot create service endpoint; - nested throwable: (org.jboss.ws.WSException: @WebService[portName,serviceName,endpoi
    ntInterface] MUST NOT be defined on: echo.Echo)


    So I changed EchoImple.java:
    @javax.jws.WebService(endpointInterface="echo.Echo",portName="EchoPort")
    public class EchoImpl implements Echo
    ....
    



    Now it works and it still serves out my wsdl.

    I'm not sure if this is a bug or not because the docs here https://jax-ws.dev.java.net/jax-ws-ea3/docs/annotations.html#2.1%20javax.jws.WebService%7Coutline
    say:
    endpointInterface - The qualified name of the service endpoint interface. This annotation allows the separation of interface contract from implementation. If this property is specified, all other WebService properties are ignored as are all other 181 annotations. Only the annotations on the service endpoint interface will be taken into consideration. The endpoint implementation class is not required to implement the endpointInterface.

    Which I take to mean the other parameters (portName) should be ignored if endpointInterface is specified.


  • 7. Re: Providing your own wsdl instead of the generated one.
    David Owens Newbie

    Just to be clear which versions I'm using:
    Boss 4.2.0.CR1
    jbossws-1.2.0.GA (build=200703010320)
    java 1.5.0_11-b03

    Here are the final files.

    EchoService.wsdl (note the \<documentation\> tag near the bottom)

    <?xml version="1.0" encoding="UTF-8"?>
    <definitions name='EchoService' targetNamespace='http://echo/' xmlns='http://schemas.xmlsoap.org/wsdl/' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:tns='http://echo/' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
     <types>
     <xs:schema targetNamespace='http://echo/' version='1.0' xmlns:tns='http://echo/' xmlns:xs='http://www.w3.org/2001/XMLSchema'>
     <xs:element name='echo' type='tns:echo'/>
     <xs:element name='echoResponse' type='tns:echoResponse'/>
     <xs:complexType name='echo'>
     <xs:sequence>
     <xs:element minOccurs='0' name='arg0' type='xs:string'/>
     </xs:sequence>
     </xs:complexType>
     <xs:complexType name='echoResponse'>
     <xs:sequence>
     <xs:element minOccurs='0' name='return' type='xs:string'/>
     </xs:sequence>
     </xs:complexType>
     </xs:schema>
     </types>
     <message name='Echo_echo'>
     <part element='tns:echo' name='echo'/>
     </message>
     <message name='Echo_echoResponse'>
     <part element='tns:echoResponse' name='echoResponse'/>
     </message>
     <portType name='Echo'>
     <operation name='echo' parameterOrder='echo'>
     <input message='tns:Echo_echo'/>
     <output message='tns:Echo_echoResponse'/>
     </operation>
     </portType>
     <binding name='EchoBinding' type='tns:Echo'>
     <soap:binding style='document' transport='http://schemas.xmlsoap.org/soap/http'/>
     <operation name='echo'>
     <soap:operation soapAction=''/>
     <input>
     <soap:body use='literal'/>
     </input>
     <output>
     <soap:body use='literal'/>
     </output>
     </operation>
     </binding>
     <service name='EchoService'>
     <documentation>Congrats! You have published your own WSDL!</documentation>
     <port binding='tns:EchoBinding' name='EchoPort'>
     <soap:address location='REPLACE_WITH_ACTUAL_URL'/>
     </port>
     </service>
    </definitions>



    web.xml (note <servlet-class> specifies the imple):
    <?xml version="1.0" encoding="UTF-8"?>
    
    <web-app xmlns="http://java.sun.com/xml/ns/j2ee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
     version="2.4">
    
     <servlet>
     <servlet-name>echo</servlet-name>
     <servlet-class>echo.EchoImpl</servlet-class>
     </servlet>
    
     <servlet-mapping>
     <servlet-name>echo</servlet-name>
     <url-pattern>/*</url-pattern>
     </servlet-mapping>
    
    </web-app>


    Echo.java (note wsdlLocation added by hand to @WebService)
    package echo;
    
    import javax.jws.WebMethod;
    import javax.jws.WebParam;
    import javax.jws.WebResult;
    import javax.jws.WebService;
    import javax.xml.ws.RequestWrapper;
    import javax.xml.ws.ResponseWrapper;
    
    
    /**
     * JBossWS Generated Source
     *
     * ...
     * JAX-WS Version: 2.0
     *
     */
    @WebService(name = "Echo", targetNamespace = "http://echo/", wsdlLocation="META-INF/wsdl/EchoService.wsdl")
    public interface Echo {
    
    
     /**
     *
     * @param arg0
     * @return
     * returns java.lang.String
     */
     @WebMethod
     @WebResult(targetNamespace = "")
     @RequestWrapper(localName = "echo", targetNamespace = "http://echo/", className = "echo.Echo_Type")
     @ResponseWrapper(localName = "echoResponse", targetNamespace = "http://echo/", className = "echo.EchoResponse")
     public String echo(
     @WebParam(name = "arg0", targetNamespace = "")
     String arg0);
    
    }
    


    and finally EchoImpl.java (not the portName)
    package echo;
    
    @javax.jws.WebService(endpointInterface="echo.Echo", portName="EchoPort")
    public class EchoImpl implements Echo
    {
     public String echo(String arg0)
     {
     return arg0;
     }
    }


    And for completeness, the war structure
    META-INF/
    META-INF/MANIFEST.MF
    META-INF/wsdl/
    META-INF/wsdl/EchoService.wsdl
    WEB-INF/
    WEB-INF/classes/
    WEB-INF/classes/echo/
    WEB-INF/classes/echo/Echo.class
    WEB-INF/classes/echo/EchoImpl.class
    WEB-INF/classes/echo/EchoResponse.class
    WEB-INF/classes/echo/Echo_Type.class
    WEB-INF/classes/echo/ObjectFactory.class
    WEB-INF/classes/echo/package-info.class
    WEB-INF/web.xml






  • 8. Re: Providing your own wsdl instead of the generated one.
    Peter Johnson Master

    One more thing. You can now move the wsdlLocation from the interface to the class. This way, you do not have to modify the generated files (not a big deal in this example, but a real big deal if you have many endpoints and are generating the stubs quite often).

  • 9. Re: Providing your own wsdl instead of the generated one.
    Jason Greene Master

    Yes it makes more sense on the implementation bean than the interface. Although the spec unfortunately requires that we support it on the interface:

    From JAXWSWebServiceMetaDataBuilder:

    // The spec states that WSDL location should be allowed on an SEI, although it
    // makes far more sense on the implementation bean, so we ALWAYS override the SEI
    // when wsdlLocation is defined on the bean
    if (wsdlLocation.length() == 0)
     wsdlLocation = seiAnnotation.wsdlLocation();
    


    -Jason

  • 10. Re: Providing your own wsdl instead of the generated one.
    Adriano Basile Newbie

    I followed this steps, but wsconsume generate only 2 class: the interface and the class which implement it.

    I create the web.xml, generate the war file, and when I put it in jboss I obtain this:

    09:39:15,267 ERROR [MainDeployer] Could not create deployment: file:/C:/jboss-4.
    0.5.GA/server/default/deploy/WPM3.war
    org.jboss.deployment.DeploymentException: Cannot create service endpoint; - nest
    ed throwable: (org.jboss.ws.WSException: Cannot find required security resource:
    WEB-INF/wsse.keystore)

    So, I create an empty file called wsse.keystore, and I obtain this:


    09:40:26,803 ERROR [MainDeployer] Could not create deployment: file:/C:/jboss-4.
    0.5.GA/server/default/deploy/WPM3.war
    org.jboss.deployment.DeploymentException: Cannot create service endpoint; - nest
    ed throwable: (org.jboss.ws.WSException: Cannot find required security resource:
    WEB-INF/wsse.truststore)


    So, I create an empty file called wsse.truststore, and I obtain this:



    09:45:19,415 ERROR [MainDeployer] Could not create deployment: file:/C:/jboss-4.
    0.5.GA/server/default/deploy/WPM3.war
    org.jboss.deployment.DeploymentException: Cannot create service endpoint; - nest
    ed throwable: (org.jboss.ws.WSException: Cannot find port in wsdl: {http://local
    host:8080/WPM3}wpmPort)



    Can you help me?

  • 11. Re: Providing your own wsdl instead of the generated one.
    David Owens Newbie

    sgof,

    I am not using any sort of security, so I'm not sure what those errors are about. The last error sounds like your wsdl is not syntactically correct. I would suggest starting with a simple example wsdl like the one I provided and a plain JBoss 4.0.5.GA install and get that working first. Once that works, try modifying the project bit by bit to fit what you are trying to do.

    Hope this helps.

  • 12. Re: Providing your own wsdl instead of the generated one.
    Matt Jacobs Newbie

    ngtdave and PeterJ:

    Thank you for this topic. It was quite helpful.

  • 13. Re: Providing your own wsdl instead of the generated one.
    David Owens Newbie

    Glad to have helped. :)

    "jacobsm" wrote:
    ngtdave and PeterJ:

    Thank you for this topic. It was quite helpful.


  • 14. Re: Providing your own wsdl instead of the generated one.
    Anuradha Rahurkar Newbie

    ngtdave and PeterJ:

    Thank you very much for the post. It was quite helpful. I was able to publish the EchoService.wsdl.
    However, the EchoClient as per the JBossWSUserGuide(http://www.jboss.org/jbossws/docs/jaxws_userguide-2.0/index.html#d0e741)
    gives me the following Exception:

    Command:
    wsrunclient.bat EchoClient 'HelloWorld'
    Exception in thread "main" javax.xml.ws.WebServiceException: java.lang.IllegalStateException: Could not setup remoting client
    at org.jboss.ws.core.jaxws.client.ClientImpl.handleRemoteException(Clien
    tImpl.java:304)
    at org.jboss.ws.core.jaxws.client.ClientImpl.invoke(ClientImpl.java:242)
    at org.jboss.ws.core.jaxws.client.ClientProxy.invoke(ClientProxy.java:16
    4)
    at org.jboss.ws.core.jaxws.client.ClientProxy.invoke(ClientProxy.java:15
    0)
    at $Proxy15.echo(Unknown Source)
    at echo.EchoClient.main(EchoClient.java:15)
    Caused by: java.lang.IllegalStateException: Could not setup remoting client
    at org.jboss.ws.core.client.RemotingConnectionImpl.createRemotingClient(
    RemotingConnectionImpl.java:240)

    Any pointers?

1 2 Previous Next