{"id":21,"date":"2008-10-23T21:38:36","date_gmt":"2008-10-24T01:38:36","guid":{"rendered":"http:\/\/joemorrison.org\/blog\/?p=21"},"modified":"2008-10-23T21:38:36","modified_gmt":"2008-10-24T01:38:36","slug":"cxf-wsdl-first","status":"publish","type":"post","link":"https:\/\/morrison.today\/blog\/2008\/10\/23\/cxf-wsdl-first\/","title":{"rendered":"Java template for WSDL-first web services using CXF (for Maven2 and Eclipse)"},"content":{"rendered":"<p>This took me a while to put together so I thought I&#8217;d post it. I wanted the simplest possible template for building a web service in Java. I wanted it to be <a title=\"JAX-WS\" href=\"http:\/\/en.wikipedia.org\/wiki\/JAX-WS\">JAX-WS<\/a> compliant, so I used the <a title=\"CXF\" href=\"http:\/\/cxf.apache.org\/\">CXF<\/a> open source implementation which is not only compliant, but also flexible and fast. I also wanted the template to be <a title=\"WSDL first\" href=\"http:\/\/webservices.xml.com\/pub\/a\/ws\/2003\/07\/22\/wsdlfirst.html\">WSDL first<\/a>, meaning that I should be able to edit the WSDL by hand to maintain total control over the service contract, then from that, generate Java code to make it easy to fill in the implementation.\u00a0 (I consider that to be an important part of web service best practices. Doing it the other way &#8211; automatically generating WSDL from code &#8211; is simpler, but results in messy, sometimes incorrect WSDL that limits your ability to change web service implementations later.) Furthermore, I didn&#8217;t want to edit any generated code. I wanted to be able to fill in the implementation details by inheriting from a generated class or implementing a generated interface. Finally, I wanted to take advantage of <a title=\"Maven\" href=\"http:\/\/maven.apache.org\/\">Maven<\/a> to build the project, but also be able to work on it in <a title=\"Eclipse\" href=\"http:\/\/www.eclipse.org\/\">Eclipse<\/a>, taking advantage of its <a title=\"WTP\" href=\"http:\/\/www.eclipse.org\/webtools\/\">Web Tools Platform (WTP)<\/a> to allow synchronization with a live application server. Here&#8217;s the result in just under 300 lines of code. (Or you can cut to the chase and just <a title=\"Java template for WSDL-first web services\" href=\"http:\/\/joemorrison.org\/downloads\/ws-example.zip\">download the zip file<\/a> and follow the instructions at the end of this posting.)<br \/>\n<!--more--><br \/>\nFirst, here is the <code>trade.xsd<\/code> schema file containing the input and output datatypes used by the web services:<\/p>\n<pre>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n\r\n&lt;xsd:schema targetNamespace=\"http:\/\/com.joemo.schema.trade\" xmlns=\"http:\/\/com.joemo.schema.trade\"\r\n\txmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\"&gt;\r\n\r\n\t&lt;!-- web service input types --&gt;\r\n\r\n\t&lt;xsd:element name=\"trade\"&gt;\r\n\t\t&lt;xsd:complexType&gt;\r\n\t\t\t&lt;xsd:sequence&gt;\r\n\t\t\t\t&lt;xsd:element name=\"security\" type=\"xsd:string\" minOccurs=\"1\" maxOccurs=\"1\" \/&gt;\r\n\t\t\t\t&lt;xsd:element name=\"quantity\" type=\"xsd:integer\" minOccurs=\"1\" maxOccurs=\"1\" \/&gt;\r\n\t\t\t\t&lt;!-- note the use of \"unbounded\"; comments can occur multiple times --&gt;\r\n\t\t\t\t&lt;xsd:element name=\"comments\" type=\"comment\" minOccurs=\"1\" maxOccurs=\"unbounded\" \/&gt;\r\n\t\t\t&lt;\/xsd:sequence&gt;\r\n\t\t&lt;\/xsd:complexType&gt;\r\n\t&lt;\/xsd:element&gt;\r\n\r\n\t&lt;xsd:complexType name=\"comment\"&gt;\r\n\t\t&lt;xsd:sequence&gt;\r\n\t\t\t&lt;xsd:element name=\"message\" type=\"xsd:string\" minOccurs=\"1\" maxOccurs=\"1\" \/&gt;\r\n\t\t\t&lt;xsd:element name=\"author\" type=\"xsd:string\" minOccurs=\"1\" maxOccurs=\"1\" \/&gt;\r\n\t\t&lt;\/xsd:sequence&gt;\r\n\t&lt;\/xsd:complexType&gt;\r\n\r\n\t&lt;!-- web service output types --&gt;\r\n\r\n\t&lt;xsd:element name=\"status\"&gt;\r\n\t\t&lt;xsd:complexType&gt;\r\n\t\t\t&lt;xsd:sequence&gt;\r\n\t\t\t\t&lt;xsd:element name=\"id\" type=\"xsd:string\" minOccurs=\"1\" maxOccurs=\"1\" \/&gt;\r\n\t\t\t\t&lt;xsd:element name=\"message\" type=\"xsd:string\" minOccurs=\"1\" maxOccurs=\"1\" \/&gt;\r\n\t\t\t&lt;\/xsd:sequence&gt;\r\n\t\t&lt;\/xsd:complexType&gt;\r\n\t&lt;\/xsd:element&gt;\r\n\r\n&lt;\/xsd:schema&gt;<\/pre>\n<p>Next, we need the <code>trade.wsdl<\/code> file which imports the schema file and completes the WSDL definition:<\/p>\n<pre>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n&lt;wsdl:definitions targetNamespace=\"http:\/\/com.joemo.schema.tradeservice\"\r\n\txmlns=\"http:\/\/com.joemo.schema.tradeservice\"\r\n\txmlns:tr=\"http:\/\/com.joemo.schema.trade\"\r\n\txmlns:soapenc=\"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/\" xmlns:wsdl=\"http:\/\/schemas.xmlsoap.org\/wsdl\/\"\r\n\txmlns:wsdlsoap=\"http:\/\/schemas.xmlsoap.org\/wsdl\/soap\/\" xmlns:xsd=\"http:\/\/www.w3.org\/2001\/XMLSchema\"&gt;\r\n\r\n\t&lt;wsdl:types&gt;\r\n\t\t&lt;xsd:schema targetNamespace=\"http:\/\/com.joemo.schema.tradeservice\"&gt;\r\n\t\t\t&lt;xsd:import namespace=\"http:\/\/com.joemo.schema.trade\" schemaLocation=\"trade.xsd\" \/&gt;\r\n\t\t&lt;\/xsd:schema&gt;\r\n\t&lt;\/wsdl:types&gt;\r\n\r\n\t&lt;wsdl:message name=\"tradeInput\"&gt;\r\n\t\t&lt;wsdl:part name=\"trade\" element=\"tr:trade\" \/&gt;\r\n\t&lt;\/wsdl:message&gt;\r\n\r\n\t&lt;wsdl:message name=\"tradeOutput\"&gt;\r\n\t\t&lt;wsdl:part name=\"status\" element=\"tr:status\" \/&gt;\r\n\t&lt;\/wsdl:message&gt;\r\n\r\n\t&lt;wsdl:portType name=\"TradeService\"&gt;\r\n\t\t&lt;wsdl:operation name=\"book\"&gt;\r\n\t\t\t&lt;wsdl:input message=\"tradeInput\" \/&gt;\r\n\t\t\t&lt;wsdl:output message=\"tradeOutput\" \/&gt;\r\n\t\t&lt;\/wsdl:operation&gt;\r\n\t&lt;\/wsdl:portType&gt;\r\n\r\n\t&lt;wsdl:binding name=\"TradeServiceHTTPBinding\" type=\"TradeService\"&gt;\r\n\t\t&lt;wsdlsoap:binding style=\"document\"\r\n\t\t\ttransport=\"http:\/\/schemas.xmlsoap.org\/soap\/http\" \/&gt;\r\n\t\t&lt;wsdl:operation name=\"book\"&gt;\r\n\t\t\t&lt;wsdlsoap:operation soapAction=\"\" \/&gt;\r\n\t\t\t&lt;wsdl:input&gt;\r\n\t\t\t\t&lt;wsdlsoap:body use=\"literal\" \/&gt;\r\n\t\t\t&lt;\/wsdl:input&gt;\r\n\t\t\t&lt;wsdl:output&gt;\r\n\t\t\t\t&lt;wsdlsoap:body use=\"literal\" \/&gt;\r\n\t\t\t&lt;\/wsdl:output&gt;\r\n\t\t&lt;\/wsdl:operation&gt;\r\n\t&lt;\/wsdl:binding&gt;\r\n\r\n\t&lt;wsdl:service name=\"TradeServicePorts\"&gt;\r\n\t\t&lt;wsdl:port binding=\"TradeServiceHTTPBinding\" name=\"TradeService\"&gt;\r\n\t\t\t&lt;wsdlsoap:address\r\n\t\t\t\tlocation=\"http:\/\/localhost:9084\/tradeService\/TradeServicePorts\" \/&gt;\r\n\t\t&lt;\/wsdl:port&gt;\r\n\t&lt;\/wsdl:service&gt;\r\n\r\n&lt;\/wsdl:definitions&gt;<\/pre>\n<p>Now we need a Maven project file that will take this WSDL and generate the Java code. Here&#8217;s what the <code>pom.xml<\/code> file looks like. It&#8217;s long and messy but it does a lot. It specifies all the dependencies and the compiler level, includes the rule to generate Java code from WSDL whenever necessary, and includes Jetty and WTP support for testing and running the web services in different environments.<\/p>\n<pre>&lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/maven-v4_0_0.xsd\"&gt;\r\n\t&lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\r\n\t&lt;groupId&gt;com.joemo&lt;\/groupId&gt;\r\n\t&lt;artifactId&gt;ws-example&lt;\/artifactId&gt;\r\n\t&lt;packaging&gt;war&lt;\/packaging&gt;\r\n\t&lt;version&gt;0.1&lt;\/version&gt;\r\n\t&lt;name&gt;ws-example&lt;\/name&gt;\r\n\t&lt;url&gt;http:\/\/maven.apache.org&lt;\/url&gt;\r\n\t&lt;properties&gt;\r\n\t\t&lt;cxf.version&gt;2.1&lt;\/cxf.version&gt;\r\n\t\t&lt;spring.version&gt;2.5&lt;\/spring.version&gt;\r\n\t&lt;\/properties&gt;\r\n\t&lt;dependencies&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.apache.cxf&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;cxf-rt-core&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${cxf.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.apache.cxf&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;cxf-rt-frontend-jaxws&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${cxf.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.apache.cxf&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;cxf-rt-transports-http&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${cxf.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.apache.cxf&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;cxf-common-utilities&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${cxf.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.springframework&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;spring-core&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${spring.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;org.springframework&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;spring-beans&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;${spring.version}&lt;\/version&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t\t&lt;dependency&gt;\r\n\t\t\t&lt;groupId&gt;junit&lt;\/groupId&gt;\r\n\t\t\t&lt;artifactId&gt;junit&lt;\/artifactId&gt;\r\n\t\t\t&lt;version&gt;4.4&lt;\/version&gt;\r\n\t\t\t&lt;scope&gt;test&lt;\/scope&gt;\r\n\t\t&lt;\/dependency&gt;\r\n\t&lt;\/dependencies&gt;\r\n\t&lt;build&gt;\r\n\t\t&lt;plugins&gt;\r\n\t\t\t&lt;!-- Use Java 5 --&gt;\r\n\t\t\t&lt;plugin&gt;\r\n\t\t\t\t&lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\r\n\t\t\t\t&lt;artifactId&gt;maven-compiler-plugin&lt;\/artifactId&gt;\r\n\t\t\t\t&lt;configuration&gt;\r\n\t\t\t\t\t&lt;source&gt;1.5&lt;\/source&gt;\r\n\t\t\t\t\t&lt;target&gt;1.5&lt;\/target&gt;\r\n\t\t\t\t&lt;\/configuration&gt;\r\n\t\t\t&lt;\/plugin&gt;\r\n\r\n\t\t\t&lt;!-- CXF WSDL-to-Java code generation --&gt;\r\n\t\t\t&lt;plugin&gt;\r\n\t\t\t\t&lt;groupId&gt;org.apache.cxf&lt;\/groupId&gt;\r\n\t\t\t\t&lt;artifactId&gt;cxf-codegen-plugin&lt;\/artifactId&gt;\r\n\t\t\t\t&lt;version&gt;2.0.6&lt;\/version&gt;\r\n\t\t\t\t&lt;executions&gt;\r\n\t\t\t\t\t&lt;execution&gt;\r\n\t\t\t\t\t\t&lt;id&gt;generate-sources&lt;\/id&gt;\r\n\t\t\t\t\t\t&lt;phase&gt;generate-sources&lt;\/phase&gt;\r\n\t\t\t\t\t\t&lt;configuration&gt;\r\n\t\t\t\t\t\t\t&lt;sourceRoot&gt;${basedir}\/target\/generated\/src\/main\/java&lt;\/sourceRoot&gt;\r\n\t\t\t\t\t\t\t&lt;wsdlOptions&gt;\r\n\t\t\t\t\t\t\t\t&lt;wsdlOption&gt;\r\n\t\t\t\t\t\t\t\t\t&lt;wsdl&gt;src\/main\/resources\/trade.wsdl&lt;\/wsdl&gt;\r\n\t\t\t\t\t\t\t\t&lt;\/wsdlOption&gt;\r\n\t\t\t\t\t\t\t&lt;\/wsdlOptions&gt;\r\n\t\t\t\t\t\t&lt;\/configuration&gt;\r\n\t\t\t\t\t\t&lt;goals&gt;\r\n\t\t\t\t\t\t\t&lt;goal&gt;wsdl2java&lt;\/goal&gt;\r\n\t\t\t\t\t\t&lt;\/goals&gt;\r\n\t\t\t\t\t&lt;\/execution&gt;\r\n\t\t\t\t&lt;\/executions&gt;\r\n\t\t\t&lt;\/plugin&gt;\r\n\t\t\t&lt;!-- Jetty support for testing --&gt;\r\n\t\t\t&lt;plugin&gt;\r\n\t\t\t\t&lt;groupId&gt;org.mortbay.jetty&lt;\/groupId&gt;\r\n\t\t\t\t&lt;artifactId&gt;maven-jetty-plugin&lt;\/artifactId&gt;\r\n\t\t\t&lt;\/plugin&gt;\r\n\t\t&lt;\/plugins&gt;\r\n\t\t&lt;!-- Eclipse WTP support --&gt;\r\n\t\t&lt;pluginManagement&gt;\r\n\t\t\t&lt;plugins&gt;\r\n\t\t\t\t&lt;plugin&gt;\r\n\t\t\t\t\t&lt;artifactId&gt;maven-eclipse-plugin&lt;\/artifactId&gt;\r\n\t\t\t\t\t&lt;configuration&gt;\r\n\t\t\t\t\t\t&lt;wtpversion&gt;2.0&lt;\/wtpversion&gt;\r\n\t\t\t\t\t\t&lt;wtpapplicationxml&gt;true&lt;\/wtpapplicationxml&gt;\r\n\t\t\t\t\t\t&lt;wtpmanifest&gt;true&lt;\/wtpmanifest&gt;\r\n\t\t\t\t\t\t&lt;downloadSources&gt;true&lt;\/downloadSources&gt;\r\n\t\t\t\t\t\t&lt;downloadJavadocs&gt;true&lt;\/downloadJavadocs&gt;\r\n\t\t\t\t\t\t&lt;projectNameTemplate&gt;[artifactId]-[version]&lt;\/projectNameTemplate&gt;\r\n\t\t\t\t\t\t&lt;manifest&gt;${basedir}\/src\/main\/resources\/META-INF\/MANIFEST.MF&lt;\/manifest&gt;\r\n\t\t\t\t\t&lt;\/configuration&gt;\r\n\t\t\t\t&lt;\/plugin&gt;\r\n\t\t\t&lt;\/plugins&gt;\r\n\t\t&lt;\/pluginManagement&gt;\r\n\t&lt;\/build&gt;\r\n&lt;\/project&gt;<\/pre>\n<p>Among other things, the rules in this <code>pom.xml<\/code> file will generate a Java interface called <code>TradeService<\/code> (based on the names in the WSDL file). The only code we will have to write is the implementation of this interface. Although this generation is done automatically by any Maven commands that need it (e.g. <code>mvn package<\/code> or <code>mvn install<\/code>) you might want to force it to be done sooner rather than later, so that you can refresh your Eclipse project with the generated code, enabling Eclipse to recognize the interface that you&#8217;re trying to implement. You can do this using the commands:<\/p>\n<pre>mvn generate-sources\r\nmvn eclipse:clean eclipse:eclipse<\/pre>\n<p>This generates Java code from the WSDL, then regenerates the Eclipse project files, after which you should be able to refresh the project in Eclipse. If you see errors about libraries not being found, you may need to configure Eclipse to know about your Maven repository, i.e. select Eclipse \/ Window \/ Preferences \/ Java \/ Build Path \/ Classpath Variables, then enter the appropriate settings, e.g.<\/p>\n<pre>Name: M2_REPO\r\nPath: C:\/Documents and Settings\/MyAccount\/.m2\/repository<\/pre>\n<p>Once the project is properly configured in Eclipse, you can fill in the implementation:<\/p>\n<pre>package com.joemo.service;\r\n\r\nimport trade.schema.joemo.com.Comment;\r\nimport trade.schema.joemo.com.Status;\r\nimport trade.schema.joemo.com.Trade;\r\nimport tradeservice.schema.joemo.com.TradeService;\r\n\r\npublic class TradeServiceImpl implements TradeService {\r\n\r\n\tpublic Status book(Trade trade) {\r\n\t\tSystem.out.print (\"Booking security \");\r\n\t\tSystem.out.print (trade.getSecurity());\r\n\t\tSystem.out.print (\", quantity \");\r\n\t\tSystem.out.print (trade.getQuantity());\r\n\t\tSystem.out.println();\r\n\t\tif (trade.getComments() != null) {\r\n\t\t\tSystem.out.println (\"Comments:\");\r\n\t\t\tfor (Comment c : trade.getComments()) {\r\n\t\t\t\tSystem.out.print (c.getAuthor());\r\n\t\t\t\tSystem.out.print (\": \");\r\n\t\t\t\tSystem.out.print (c.getMessage());\r\n\t\t\t\tSystem.out.println();\r\n\t\t\t}\r\n\t\t}\r\n\t\tStatus s = new Status();\r\n\t\ts.setId(\"12345\");\r\n\t\ts.setMessage(\"ok\");\r\n\t\treturn s;\r\n\t}\r\n\r\n}<\/pre>\n<p>We are almost done. We still need a <code>web.xml<\/code> file which will direct SOAP requests to the CXF infrastructure:<\/p>\n<pre>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n&lt;web-app id=\"WebApp_9\" version=\"2.4\" xmlns=\"http:\/\/java.sun.com\/xml\/ns\/j2ee\"\r\n\txmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n\txsi:schemaLocation=\"http:\/\/java.sun.com\/xml\/ns\/j2ee http:\/\/java.sun.com\/xml\/ns\/j2ee\/web-app_2_4.xsd\"&gt;\r\n\t&lt;context-param&gt;\r\n\t\t&lt;param-name&gt;contextConfigLocation&lt;\/param-name&gt;\r\n\t\t&lt;param-value&gt;classpath:appContext.xml&lt;\/param-value&gt;\r\n\t&lt;\/context-param&gt;\r\n\t&lt;listener&gt;\r\n\t\t&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;\/listener-class&gt;\r\n\t&lt;\/listener&gt;\r\n\t&lt;servlet&gt;\r\n\t\t&lt;servlet-name&gt;dispatcher&lt;\/servlet-name&gt;\r\n\t\t&lt;servlet-class&gt;org.apache.cxf.transport.servlet.CXFServlet&lt;\/servlet-class&gt;\r\n\t\t&lt;load-on-startup&gt;1&lt;\/load-on-startup&gt;\r\n\t&lt;\/servlet&gt;\r\n\t&lt;servlet-mapping&gt;\r\n\t\t&lt;servlet-name&gt;dispatcher&lt;\/servlet-name&gt;\r\n\t\t&lt;url-pattern&gt;\/*&lt;\/url-pattern&gt;\r\n\t&lt;\/servlet-mapping&gt;\r\n&lt;\/web-app&gt;<\/pre>\n<p>Finally, we need the <code>appContext.xml<\/code> file, which is the Spring configuration file loaded by CXF that defines the web service endpoint:<\/p>\n<pre>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\r\n\txmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\" xmlns:context=\"http:\/\/www.springframework.org\/schema\/context\"\r\n\txmlns:jee=\"http:\/\/www.springframework.org\/schema\/jee\" xmlns:jaxws=\"http:\/\/cxf.apache.org\/jaxws\"\r\n\txsi:schemaLocation=\"http:\/\/www.springframework.org\/schema\/beans http:\/\/www.springframework.org\/schema\/beans\/spring-beans-2.5.xsd\r\nhttp:\/\/www.springframework.org\/schema\/jee http:\/\/www.springframework.org\/schema\/jee\/spring-jee-2.5.xsd\r\nhttp:\/\/www.springframework.org\/schema\/context http:\/\/www.springframework.org\/schema\/context\/spring-context-2.5.xsd\r\nhttp:\/\/cxf.apache.org\/jaxws http:\/\/cxf.apache.org\/schemas\/jaxws.xsd\"\r\n\tdefault-dependency-check=\"none\" default-lazy-init=\"false\"&gt;\r\n\r\n\t&lt;!-- Load the needed resources that are present in the cxf* jars --&gt;\r\n\t&lt;import resource=\"classpath:META-INF\/cxf\/cxf.xml\" \/&gt;\r\n\t&lt;import resource=\"classpath:META-INF\/cxf\/cxf-extension-soap.xml\" \/&gt;\r\n\t&lt;import resource=\"classpath:META-INF\/cxf\/cxf-servlet.xml\" \/&gt;\r\n\r\n\t&lt;!-- Hook up the web service --&gt;\r\n\t&lt;jaxws:endpoint id=\"ws-example\" implementor=\"com.joemo.service.TradeServiceImpl\"\r\n\t\taddress=\"\/ws-example\" \/&gt;\r\n\r\n&lt;\/beans&gt;<\/pre>\n<p>That&#8217;s everything. There are six files, only one of which contains any Java code. You need to make sure you put each file in the right place:<\/p>\n<pre>ws-example\/pom.xml\r\nws-example\/src\/main\/resources\/trade.xsd\r\nws-example\/src\/main\/resources\/trade.wsdl\r\nws-example\/src\/main\/resources\/appContext.xml\r\nws-example\/src\/main\/webapp\/WEB-INF\/web.xml\r\nws-example\/src\/main\/java\/com\/joemo\/service\/TradeServiceImpl.java<\/pre>\n<p>A zip file of this example is available for download <a title=\"Java template for WSDL-first web services\" href=\"http:\/\/joemorrison.org\/downloads\/ws-example.zip\">here<\/a>. To build and run it, you will need Maven to be installed on your development system. Unzip the file, and in the directory containing the <code>pom.xml<\/code> file, run the command:<\/p>\n<pre>mvn jetty:run<\/pre>\n<p>That will generate the Java code from the WSDL, build the example, and run the web service in the <a href=\"http:\/\/www.mortbay.org\/jetty\/\">Jetty<\/a> container. You should be able to visit the URL <code>http:\/\/localhost:8080\/ws-example\/ws-example?wsdl<\/code> from a web browser and see the WSDL for the web service, test the web service using <a title=\"SoapUI\" href=\"http:\/\/www.soapui.org\/\">SoapUI<\/a>, and so on.<\/p>\n<p>Alternatively you can run the command:<\/p>\n<pre>mvn eclipse:eclipse<\/pre>\n<p>and follow the directions from my <a title=\"Developing Web applications with Maven and Eclipse\" href=\"https:\/\/morrison.today\/blog\/2008\/06\/01\/developing-web-applications-with-maven-and-eclipse-you-can-have-it-all\/\">earlier blog entry<\/a> to run the example using Eclipse WTP, which will allow you to edit the code while keeping it synchronized with a live application server. <\/p>\n<p>Good luck! If you encounter any problems using this template, please email me or post a comment so that I can look into it and revise the instructions if necessary. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>This took me a while to put together so I thought I&#8217;d post it. I wanted the simplest possible template for building a web service in Java. I wanted it to be JAX-WS compliant, so I used the CXF open source implementation which is not only compliant, but also flexible and fast. I also wanted [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7,3,5],"tags":[18,20,42,19,16],"class_list":["post-21","post","type-post","status-publish","format-standard","hentry","category-java","category-open-source","category-soa","tag-cxf","tag-eclipse","tag-java","tag-maven","tag-soap"],"blocksy_meta":"","_links":{"self":[{"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/posts\/21","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/comments?post=21"}],"version-history":[{"count":15,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/posts\/21\/revisions"}],"predecessor-version":[{"id":36,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/posts\/21\/revisions\/36"}],"wp:attachment":[{"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/media?parent=21"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/categories?post=21"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/morrison.today\/blog\/wp-json\/wp\/v2\/tags?post=21"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}