Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Next up is to configure the web.xml to be ready to use CXF so we can expose the webservice.
TODO: how to configure the web.xml, spring context listener, cxf files etc As Spring is the center of the universe, or at least is a very important framework in today's Java land we start with the listener that kick-starts Spring. This is the usual piece of code:

Code Block
xml
xml

	<!-- the listener that kick-starts Spring -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

And then we have the CXF part where we define the CXF servlet and its URI mappings to which we have chosen that all our webservices should be in the path /webservices/

Code Block
xml
xml

	<!-- CXF servlet -->
	<servlet>
		<servlet-name>CXFServlet</servlet-name>
		<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- all our webservices are mapped under this URI pattern -->
	<servlet-mapping>
		<servlet-name>CXFServlet</servlet-name>
		<url-pattern>/webservices/*</url-pattern>
	</servlet-mapping>

Then the last piece of the puzzle is to configure CXF, this is done in a spring XML that we link to fron the web.xml by the standard Spring contextConfigLocation property in the web.xml

Code Block
xml
xml

	<!-- location of spring xml files -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:cxf-config.xml</param-value>
	</context-param>

We have named our CXF configuration file cxf-config.xml and its located in the root of the classpath. In Maven land that is we can have the cxf-config.xml file in the src/main/resources folder. We could also have the file located in the WEB-INF folder for instance <param-value>/WEB-INF/cxf-config.xml</param-value>.

Configuration of CXF

The cxf-config.xml is as follows:

Code Block
xml
xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxws="http://cxf.apache.org/jaxws"
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

    <import resource="classpath:META-INF/cxf/cxf.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml"/>
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>

    <!-- implementation of the webservice -->
    <bean id="reportIncidentEndpoint" class="org.apache.camel.example.reportincident.ReportIncidentEndpoint"/>

    <!-- export the webservice using jaxws -->
    <jaxws:endpoint id="reportIncident"
                    implementor="#reportIncidentEndpoint"
                    address="/incident"
                    wsdlLocation="/WEB-INF/wsdl/report_incident.xml"
                    endpointName="s:ReportIncidentPort"
                    serviceName="s:ReportIncidentService"
                    xmlns:s="http://reportincident.example.camel.apache.org"/>

</beans>

The configuration is standard CXF and is documented at the Apache CXF website.

The 3 import elements is needed by CXF and they must be in the file.

Noticed that we have a spring bean reportIncidentEndpoint that is the implementation of the webservice endpoint we let CXF expose.
Its linked from the jaxws element with the implementator attribute as we use the # mark to identify its a reference to a spring bean. We could have statet the classname directly as implementor="org.apache.camel.example.reportincident.ReportIncidentEndpoint" but then we lose the ability to let the ReportIncidentEndpoint be configured by spring.
The address attribute defines the relative part of the URL of the exposed webservice. wsdlLocation is an optional parameter but for persons like me that likes contract-first we want to expose our own .wsdl contracts and not the auto generated by the frameworks, so with this attribute we can link to the real .wsdl file. The last stuff is needed by CXF as you could have several services so it needs to know which this one is. Configuring these is quite easy as all the information is in the wsdl already.

Implementing the ReportIncidentEndpoint

Phew after all these meta files its time for some java code so we should code the implementor of the webservice. So we fire up mvn compile to let CXF generate the POJO classes for our webservice and we are ready to fire up a Java editor.

You can use mvn idea:idea or mvn eclipse:eclipse to create project files for these editors so you can load the project. However IDEA has been smarter lately and can load a pom.xml directly.

As we want to quickly see our webservice we implement just a quick and dirty as it can get. At first beware that since its jaxws and Java1.5 we get annotations for the money:

Code Block
java
java

package org.apache.camel.example.reportincident;

import javax.jws.soap.SOAPBinding;
import javax.jws.WebResult;
import javax.jws.WebMethod;
import javax.jws.WebParam;

/**
 * The webservice we have implemented.
 */
public class ReportIncidentEndpoint implements ReportIncidentServiceImpl {
    @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
    @WebResult(name = "outputReportIncident",
        targetNamespace = "http://reportincident.example.camel.apache.org", partName = "parameters")
    @WebMethod(operationName = "ReportIncident",
        action = "http://reportincident.example.camel.apache.org/ReportIncident")
    public OutputReportIncident reportIncident(@WebParam(partName = "parameters",
        name = "inputReportIncident", targetNamespace = "http://reportincident.example.camel.apache.org")
    InputReportIncident parameters) {

        System.out.println("Hello ReportIncidentWebService is called from " + parameters.getGivenName());

        OutputReportIncident out = new OutputReportIncident();
        out.setCode("OK");
        return out;
    }
    
}

We just output the person that invokes this webservice and returns a OK response. This class should be in the maven source root folder src/main/java under the package name org.apache.camel.example.reportincident. Beware that the maven archetype tool didn't create the src/main/java folder, so you should create it manually.

To see if we are home free we run mvn clean compile.

Running our webservice

TODO: Adding Jetty to pom
TODO: Generation the code
TODO: Adding the System.out and dummy response
TODO: Starting Jetty and using SoapUI to hit the webservice
TODO: Starting Jetty in debug mode so we can debug online

...