In the post on Spring web services, I had used a contract first approach for development. This being the only style supported by Spring.
JAX-WS and also CXF on the other hand support both code first and contact first approaches.
I decided to use the same wsdl file from my Spring post:
I used the wsdl2java command from CXF for the same.
This results in the files being generated by CXF:
The Service Endpoint Interface generated by the tool is :
The Implementation is as below:
I added a jax-ws endpoint bean ( a spring configuration file placed in the config folder)
The wsdl displayed had a change at two points:
To test the above I removed the WebResult, WebMethod and WebParam annotations.
Now if I run the code the details provided in the wsdl file is still reflected. For example the part names appear as set in the wsdl file. Also I modified the operations documentation element in my wsdl and the change was displayed.
So this means CXF uses the wsdl file specified. It will only auto-generate if one is not available.
What if you do not specify the wsdlLocation attribute ?
I next decided to remove the attribute while retaining my wsdl file on the classpath. CXF continued to use my wsdl file. Thus the attribute can even by avoided. When resolving a wsdl request for a service 'xyz' if CXF finds a wsdl named 'xyz.wsdl' on the classpath it chooses the use the file.
To test my webservice I created a simple client:
JAX-WS and also CXF on the other hand support both code first and contact first approaches.
I decided to use the same wsdl file from my Spring post:
<?xml version="1.0" encoding = "UTF-8" ?> <wsdl:definitions xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:random="http://ws.com/Service/xsd/random-schema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://ws.com/Service/samplews-ns" targetNamespace="http://ws.com/Service/samplews-ns"> <wsdl:types> <xs:schema> <xs:import namespace="http://ws.com/Service/xsd/random-schema" schemaLocation="xsd/RandomService.xsd" /> </xs:schema> </wsdl:types> <wsdl:message name="GetRandomRequest"> <wsdl:part element="random:GetRandomRequest" name="GetRandomRequest" /> </wsdl:message> <wsdl:message name="GetRandomResponse"> <wsdl:part element="random:GetRandomResponse" name="GetRandomResponse" /> </wsdl:message> <wsdl:portType name="SampleServiceOperationsPortType"> <wsdl:operation name="random"> <wsdl:documentation>Returns a random value from the application </wsdl:documentation> <wsdl:input message="tns:GetRandomRequest" name="GetRandomRequest" /> <wsdl:output message="tns:GetRandomResponse" name="GetRandomResponse" /> </wsdl:operation> </wsdl:portType> <wsdl:binding name="SampleServiceOperationsPortTypeSoap" type="tns:SampleServiceOperationsPortType"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" /> <wsdl:operation name="random"> <soap:operation soapAction="/Service/random" /> <wsdl:input name="GetRandomRequest"> <soap:body use="literal" /> </wsdl:input> <wsdl:output name="GetRandomResponse"> <soap:body use="literal" /> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="SampleServiceOperationsPortTypeSoap"> <wsdl:port binding="tns:SampleServiceOperationsPortTypeSoap" name="SampleServiceOperationsPortTypeSoap"> <soap:address location="randomService" /> </wsdl:port> </wsdl:service> </wsdl:definitions>The included xsd file is as below:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" xmlns:random="http://ws.com/Service/xsd/random-schema" targetNamespace="http://ws.com/Service/xsd/random-schema"> <xs:element name="GetRandomRequest"> <xs:complexType> <xs:all> <xs:element name="name" type="xs:string" maxOccurs="1" minOccurs="1" /> </xs:all> </xs:complexType> </xs:element> <xs:element name="GetRandomResponse"> <xs:complexType> <xs:all> <xs:element name="value" type="xs:int" maxOccurs="1" minOccurs="1" /> </xs:all> </xs:complexType> </xs:element> <xs:element name="GetRandomFault"> <xs:complexType> <xs:all> <xs:element name="faultMessage" type="xs:string" maxOccurs="1" minOccurs="1" /> </xs:all> </xs:complexType> </xs:element> </xs:schema>Now that the contract has been defined we need to generate the source code from the same.
I used the wsdl2java command from CXF for the same.
>wsdl2java -ant -impl -server -d . random.wsdlNavigate to the folder with the wsdl file and execute the command:
This results in the files being generated by CXF:
The Service Endpoint Interface generated by the tool is :
@WebService(name = "SampleServiceOperationsPortType",targetNamespace = "http://ws.com/Service/samplews-ns") @XmlSeeAlso({ com.ws.service.xsd.random_schema.ObjectFactory.class }) @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE) public interface SampleServiceOperationsPortType { /** * Returns a random value * */ @WebResult(name = "GetRandomResponse", targetNamespace = "http://ws.com/Service/xsd/random-schema", partName = "GetRandomResponse") @WebMethod(action = "/Service/random") public com.ws.service.xsd.random_schema.GetRandomResponse random( @WebParam(partName = "GetRandomRequest", name = "GetRandomRequest", targetNamespace = "http://ws.com/Service/xsd/random-schema") com.ws.service.xsd.random_schema.GetRandomRequest getRandomRequest); }Interesting point is that maximum annotation details is added to the interface. The documentation element details have been added to the code comments.
The Implementation is as below:
@javax.jws.WebService(serviceName = "SampleServiceOperationsPortTypeSoap", portName = "SampleServiceOperationsPortTypeSoap", targetNamespace = "http://ws.com/Service/samplews-ns", wsdlLocation = "random.wsdl", endpointInterface = "com.ws.service.samplews_ns.SampleServiceOperationsPortType") public class SampleServiceOperationsPortTypeImpl implements SampleServiceOperationsPortType { private static final Logger LOG = Logger .getLogger(SampleServiceOperationsPortTypeImpl.class.getName()); /* * (non-Javadoc) * * @see * com.ws.service.samplews_ns.SampleServiceOperationsPortType#random(com * .ws.service.xsd.random_schema.GetRandomRequest getRandomRequest )* */ public com.ws.service.xsd.random_schema.GetRandomResponse random( com.ws.service.xsd.random_schema.GetRandomRequest getRandomRequest) { LOG.info("Executing operation random"); System.out.println(getRandomRequest); try { com.ws.service.xsd.random_schema.GetRandomResponse _return = null; return _return; } catch (java.lang.Exception ex) { ex.printStackTrace(); throw new RuntimeException(ex); } } }Here the webservice annotation provides the SOAP details. The method is incomplete. I had to make some minor code changes to the below:
com.ws.service.xsd.random_schema.GetRandomResponse _return = new GetRandomResponse(); _return.setValue((int) (Math.random()*165));There are two more files that were generated:
- SampleServiceOperationsPortTypeSoap – This is a web-service client built using pure JAX-WS APIs
- SampleServiceOperationsPortType_SampleServiceOperationsPortTypeSoap_Server – This uses the Endpoint API to publish the webservice
I added a jax-ws endpoint bean ( a spring configuration file placed in the config folder)
<jaxws:endpoint id="randomWs" implementor="com.ws.service.samplews_ns.SampleServiceOperationsPortTypeImpl" wsdlLocation="random.wsdl" address="randomService"> <jaxws:properties> <entry key="schema-validation-enabled" value="true" /> </jaxws:properties> </jaxws:endpoint>I also added an entry for the CXFServlet in my 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>/services/*</url-pattern> </servlet-mapping>and tried to access the wsdl file at URL http://localhost:8080/WsdlFirst/services/randomService?wsdl
The wsdl displayed had a change at two points:
- It mapped the external xsd to a new URL - http://localhost:8080/WsdlFirst/services/randomService?xsd=xsd/RandomService.xsd.
- It modified the soap:address element's location attribute to refer to an absolute URL http://localhost:8080/WsdlFirst/services/randomService
To test the above I removed the WebResult, WebMethod and WebParam annotations.
Now if I run the code the details provided in the wsdl file is still reflected. For example the part names appear as set in the wsdl file. Also I modified the operations documentation element in my wsdl and the change was displayed.
So this means CXF uses the wsdl file specified. It will only auto-generate if one is not available.
What if you do not specify the wsdlLocation attribute ?
I next decided to remove the attribute while retaining my wsdl file on the classpath. CXF continued to use my wsdl file. Thus the attribute can even by avoided. When resolving a wsdl request for a service 'xyz' if CXF finds a wsdl named 'xyz.wsdl' on the classpath it chooses the use the file.
To test my webservice I created a simple client:
public static void main(String[] args) { final String endpointAddress = "http://localhost:8080/WsdlFirst/services/randomService"; JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(SampleServiceOperationsPortType.class); // the SEI factory.setAddress(endpointAddress); SampleServiceOperationsPortType client = (SampleServiceOperationsPortType) factory .create(); GetRandomRequest randomRequest = new GetRandomRequest(); randomRequest.setName("coolio"); GetRandomResponse reply = client.random(randomRequest); System.out.println("Server said: " + reply.getValue()); }The logs indicate successful execution:
Server said: 36
Ηavе you eveг thought abnout
ReplyDeletecreаting an ebook orr gueѕt authoring on other blοgs?
I haνе a blοg baѕed on the samе ѕubjectѕ you discusѕ аnd ωould lоve to haѵe
you ѕhare ѕοmе ѕtοгіеs/іnfoгmatiοn.
I know my ѵiewеrs wоuld value уour work.
If yоu аrе even гemοtely іnteresteԁ, feеl freе to senԁ mе an e-mаil.
Feel free to surf tο my wеbpage: affordable website maintenance services
Thanks. This article was very helpful.
ReplyDeleteNice post, very useful.. Thank you so much
ReplyDeleteThanks, nice post
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThanks for this blog, keep sharing your thoughts like this...
ReplyDeleteImportance of UI UX Design
What is Web developing