Social Media

Category Archives for Web Services

Apache CXF – Contract/WSDL First

I introduced Apache CXF in my last post. I planned on writing some good examples of my own on using the framework, but to be honest I would struggle to beat the time and depth of examples the CXF download provides in its samples directory(Apache CXF Version 3)

Instead I decided it would be more interesting to provide commentary to some of these examples, including –

Thanks to the Apache CXF developers for providing this software, and these great examples. All code contained in this post is released by Apache under the Apache License.

WSDL First Demo

There are two approaches to building web services – contract first and contract last. Contract first is where the wsdl is defined first, and contract last is where the wsdl is defined last. Apache CXF supports both forms of development.

This example is found under apache-cxf\samples\wsdl_first, and is an examples of a contract first application

WSDL Contract

The wsdl follows the standard structure –

  • wsdl:types
  • wsdl:message
  • wsdl:operation
  • wsdl:binding
  • wsdl:service

It defines 2 operations –

  • <wsdl:operation name=”updateCustomer”>
  • <wsdl:operation name=”getCustomersByName”>

Finally the service defines 2 endpoints, one for standalone, and one for a tomcat deployment –

[sourcecode lang=”xml”] <wsdl:service name="CustomerServiceService">
<wsdl:port name="CustomerServicePort" binding="tns:CustomerServiceServiceSoapBinding">
<!– embedded deployment –>
<soap:address location="http://localhost:8080/wsdl_first/services/CustomerServicePort"/>
<!– Tomcat deployment, embedded or standalone –>
<!–soap:address location="http://localhost:8080/wsdl_first/services/CustomerServicePort"/–>
</wsdl:port>
</wsdl:service>
[/sourcecode]

Web Service Implementation – CustomerServiceImpl

The CustomerServiceImpl implements the CustomerService interface, which is created through the maven task – wsdl2java

[sourcecode lang=”java”] public class CustomerServiceImpl implements CustomerService {

// The WebServiceContext can be used to retrieve special attributes like the
// user principal. Normally it is not needed
@Resource
WebServiceContext wsContext;

public List&amp;lt;Customer&amp;gt; getCustomersByName(String name) throws NoSuchCustomerException {
// …
}

public void updateCustomer(Customer customer) {
// …
}

}
[/sourcecode]

The interface itself looks like, where you can see the autogenerated JAX-WS annotations –

[sourcecode lang=”java”] @WebService(targetNamespace = &amp;quot;http://customerservice.example.com/&amp;quot;, name = &amp;quot;CustomerService&amp;quot;)
@XmlSeeAlso({ObjectFactory.class})
public interface CustomerService {

@Oneway
@RequestWrapper(localName = &amp;quot;updateCustomer&amp;quot;,
targetNamespace = &amp;quot;http://customerservice.example.com/&amp;quot;,
className = &amp;quot;com.example.customerservice.UpdateCustomer&amp;quot;)
@WebMethod
public void updateCustomer(@WebParam(name = &amp;quot;customer&amp;quot;, targetNamespace = &amp;quot;&amp;quot;)
com.example.customerservice.Customer customer
);

@WebResult(name = &amp;quot;return&amp;quot;, targetNamespace = &amp;quot;&amp;quot;)
@RequestWrapper(localName = &amp;quot;getCustomersByName&amp;quot;,
targetNamespace = &amp;quot;http://customerservice.example.com/&amp;quot;,
className = &amp;quot;com.example.customerservice.GetCustomersByName&amp;quot;)
@WebMethod
@ResponseWrapper(localName = &amp;quot;getCustomersByNameResponse&amp;quot;,
targetNamespace = &amp;quot;http://customerservice.example.com/&amp;quot;,
className = &amp;quot;com.example.customerservice.GetCustomersByNameResponse&amp;quot;)
public java.util.List&amp;lt;com.example.customerservice.Customer&amp;gt; getCustomersByName(
@WebParam(name = &amp;quot;name&amp;quot;, targetNamespace = &amp;quot;&amp;quot;) java.lang.String name
) throws NoSuchCustomerException;

}
[/sourcecode]

CXFServlet

web.xml defines the CXFServlet –

[sourcecode lang=”xml”] <servlet>
<description>Apache CXF Endpoint</description>
<display-name>cxf</display-name>
<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>
[/sourcecode]

The CXFServlet adds a Spring context, which is defined through a file called cxf.xml. This defines the end point, this is the default name and could be changed through web.xml configuration –

[sourcecode lang=”xml”] <!– comment this bean to disable schema validation in the client –>
<jaxws:client name="{http://apache.org/hello_world_soap_http}SoapPort" createdFromAPI="true">
<jaxws:properties>
<entry key="schema-validation-enabled" value="true"/>
</jaxws:properties>
</jaxws:client>
<jaxws:endpoint name="{http://apache.org/hello_world_soap_http}SoapPort"
wsdlLocation="wsdl/CustomerService.wsdl" createdFromAPI="true">
<jaxws:properties>
<entry key="schema-validation-enabled" value="true"/>
</jaxws:properties>
</jaxws:endpoint>
[/sourcecode]

Server Implementation

The intention of this tutorial is to deploy to JBoss Fuse, but I thought it was interesting to look at the different options offered in this example. The first uses JAX-WS or Spring

Spring – Injection of endpoint into jaxws server –

[sourcecode lang=”xml”] <!– HTTP Endpoint –>
<jaxws:endpoint xmlns:customer="http://customerservice.example.com/" id="CustomerServiceHTTP" address="http://localhost:8080/wsdl_first/services/CustomerServicePort" serviceName="customer:CustomerServiceService" endpointName="customer:CustomerServiceEndpoint" implementor="com.example.customerservice.server.CustomerServiceImpl">
<jaxws:features>
<bean class="org.apache.cxf.feature.LoggingFeature"/>
</jaxws:features>
</jaxws:endpoint>
[/sourcecode]

JAX-WS – The Endpoint is coded directly –

[sourcecode lang=”java”] CustomerService implementor = new CustomerServiceImpl();
EndpointImpl ep = (EndpointImpl)
Endpoint.publish(&amp;quot;http://localhost:8080/wsdl_first/services/CustomerServicePort&amp;quot;, implementor);

// Adding logging for incoming and outgoing messages
ep.getServer().getEndpoint().getInInterceptors().add(new LoggingInInterceptor());
ep.getServer().getEndpoint().getOutInterceptors().add(new LoggingOutInterceptor());
[/sourcecode]

Build (pom.xml)

The core part of the pom is the cxf-codegen-plugin. This plugin takes the wsdl and generates the java source code through its wsdl2java goal –

[sourcecode lang=”xml”] <plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${project.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<wsdlOptions>
<wsdlOption>
<wsdl>src/main/resources/CustomerService.wsdl</wsdl>
<frontEnd>jaxws21</frontEnd>
<faultSerialVersionUID>1</faultSerialVersionUID>
<bindingFiles>
<bindingFile>src/main/resources/binding.xml</bindingFile>
</bindingFiles>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
[/sourcecode]

Key points –

  • <id> and <phase> – generate-sources
  • <wsdl> – allows multiple wsdls
  • <binding> – This is a specific binding for Java to use Java consistent date formats instead of the default XMLGregorianCalendar

Putting it all together

The tutorial instructions are quite simple –

mvn clean install   (builds the demo and creates a WAR file for optional Tomcat deployment)
mvn -Pserver  (from one command line window — only if using embedded Jetty)
mvn -Pclient  (from a second command line window)

Or change the CustomerService.wsdl, and rerun maven. Then copy the wsdl_first.war to the deploy directory of tomcat. You can test the installation by running –

http://localhost:8080/wsdl_first/services/CustomerServicePort?wsdl

You can then test this installation using a tool like SOAPUI, and sending a message like –

[sourcecode lang=”xml”] <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cus="http://customerservice.example.com/">
<soapenv:Header/>
<soapenv:Body>
<cus:getCustomersByName>
<!–Optional:–>
<name>Martin</name>
</cus:getCustomersByName>
</soapenv:Body>
</soapenv:Envelope>
[/sourcecode]

Or to update the customer –

[sourcecode lang=”xml”] <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cus="http://customerservice.example.com/">
<soapenv:Header/>
<soapenv:Body>
<cus:updateCustomer>
<!–Optional:–>
<customer>
<customerId>0</customerId>
<!–Optional:–>
<name>Smith</name>
</customer>
</cus:updateCustomer>
</soapenv:Body>
</soapenv:Envelope>
[/sourcecode]

The tomcat log shows the interaction

update request was received
Customer was updated