camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Camel > Tutorial-Example-ReportIncident-Part1
Date Sun, 27 Jan 2013 11:16:00 GMT
<html>
<head>
    <base href="https://cwiki.apache.org/confluence">
            <link rel="stylesheet" href="/confluence/s/2042/9/1/_/styles/combined.css?spaceKey=CAMEL&amp;forWysiwyg=true" type="text/css">
    </head>
<body style="background: white;" bgcolor="white" class="email-body">
<div id="pageContent">
<div id="notificationFormat">
<div class="wiki-content">
<div class="email">
    <h2><a href="https://cwiki.apache.org/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part1">Tutorial-Example-ReportIncident-Part1</a></h2>
    <h4>Page <b>edited</b> by             <a href="https://cwiki.apache.org/confluence/display/~davsclaus">Claus Ibsen</a>
    </h4>
        <br/>
                         <h4>Changes (1)</h4>
                                 
    
<div id="page-diffs">
                    <table class="diff" cellpadding="0" cellspacing="0">
    
            <tr><td class="diff-snipped" >...<br></td></tr>
            <tr><td class="diff-unchanged" >- [Part 4|Tutorial-Example-ReportIncident-Part4] <br>- [Part 5|Tutorial-Example-ReportIncident-Part5] <br></td></tr>
            <tr><td class="diff-added-lines" style="background-color: #dfd;">- [Part 6|Tutorial-Example-ReportIncident-Part6] <br></td></tr>
    
            </table>
    </div>                            <h4>Full Content</h4>
                    <div class="notificationGreySide">
        <h2><a name="Tutorial-Example-ReportIncident-Part1-Part1"></a>Part 1</h2>

<h2><a name="Tutorial-Example-ReportIncident-Part1-Prerequisites"></a>Prerequisites</h2>
<p>This tutorial uses the following frameworks:</p>
<ul>
	<li>Maven 3.0.4</li>
	<li>Apache Camel 2.10.0</li>
	<li>Apache CXF 2.6.1</li>
	<li>Spring 3.0.7</li>
</ul>


<p><b>Note:</b> The sample project can be downloaded, see the <a href="#Tutorial-Example-ReportIncident-Part1-Resources">resources</a> section.</p>

<h2><a name="Tutorial-Example-ReportIncident-Part1-InitialProjectSetup"></a>Initial Project Setup</h2>
<p>We want the integration to be a standard .war application that can be deployed in any web container such as Tomcat, Jetty or even heavy weight application servers such as WebLogic or WebSphere. There fore we start off with the standard Maven webapp project that is created with the following long archetype command:</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
mvn archetype:create -DgroupId=org.apache.camel -DartifactId=camel-example-reportincident -DarchetypeArtifactId=maven-archetype-webapp
</pre>
</div></div>

<p>Notice that the groupId etc. doens't have to be org.apache.camel it can be com.mycompany.whatever. But I have used these package names as the example is an official part of the Camel distribution.</p>

<p>Then we have the basic maven folder layout. We start out with the webservice part where we want to use Apache CXF for the webservice stuff. So we add this to the pom.xml</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
    <span class="code-tag">&lt;properties&gt;</span>
        <span class="code-tag">&lt;cxf-version&gt;</span>2.6.1<span class="code-tag">&lt;/cxf-version&gt;</span>
    <span class="code-tag">&lt;/properties&gt;</span>

    <span class="code-tag">&lt;dependency&gt;</span>
        <span class="code-tag">&lt;groupId&gt;</span>org.apache.cxf<span class="code-tag">&lt;/groupId&gt;</span>
        <span class="code-tag">&lt;artifactId&gt;</span>cxf-rt-core<span class="code-tag">&lt;/artifactId&gt;</span>
        <span class="code-tag">&lt;version&gt;</span>${cxf-version}<span class="code-tag">&lt;/version&gt;</span>
    <span class="code-tag">&lt;/dependency&gt;</span>
    <span class="code-tag">&lt;dependency&gt;</span>
        <span class="code-tag">&lt;groupId&gt;</span>org.apache.cxf<span class="code-tag">&lt;/groupId&gt;</span>
        <span class="code-tag">&lt;artifactId&gt;</span>cxf-rt-frontend-jaxws<span class="code-tag">&lt;/artifactId&gt;</span>
        <span class="code-tag">&lt;version&gt;</span>${cxf-version}<span class="code-tag">&lt;/version&gt;</span>
    <span class="code-tag">&lt;/dependency&gt;</span>
    <span class="code-tag">&lt;dependency&gt;</span>
        <span class="code-tag">&lt;groupId&gt;</span>org.apache.cxf<span class="code-tag">&lt;/groupId&gt;</span>
        <span class="code-tag">&lt;artifactId&gt;</span>cxf-rt-transports-http<span class="code-tag">&lt;/artifactId&gt;</span>
        <span class="code-tag">&lt;version&gt;</span>${cxf-version}<span class="code-tag">&lt;/version&gt;</span>
    <span class="code-tag">&lt;/dependency&gt;</span>
</pre>
</div></div>

<h2><a name="Tutorial-Example-ReportIncident-Part1-DevelopingtheWebService"></a>Developing the WebService</h2>
<p>As we want to develop webservice with the contract first approach we create our .wsdl file. As this is a example we have simplified the model of the incident to only include 8 fields. In real life the model would be a bit more complex, but not to much.</p>

<p>We put the wsdl file in the folder <tt>src/main/webapp/WEB-INF/wsdl</tt> and name the file <tt>report_incident.wsdl</tt>.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
<span class="code-tag">&lt;?xml version=<span class="code-quote">"1.0"</span> encoding=<span class="code-quote">"ISO-8859-1"</span>?&gt;</span>
&lt;wsdl:definitions <span class="code-keyword">xmlns:soap</span>=<span class="code-quote">"http://schemas.xmlsoap.org/wsdl/soap/"</span>
	<span class="code-keyword">xmlns:tns</span>=<span class="code-quote">"http://reportincident.example.camel.apache.org"</span>
	<span class="code-keyword">xmlns:xs</span>=<span class="code-quote">"http://www.w3.org/2001/XMLSchema"</span>
	<span class="code-keyword">xmlns:http</span>=<span class="code-quote">"http://schemas.xmlsoap.org/wsdl/http/"</span>
	<span class="code-keyword">xmlns:wsdl</span>=<span class="code-quote">"http://schemas.xmlsoap.org/wsdl/"</span>
	targetNamespace=<span class="code-quote">"http://reportincident.example.camel.apache.org"</span>&gt;

	<span class="code-tag"><span class="code-comment">&lt;!-- Type definitions for input- and output parameters for webservice --&gt;</span></span>
	<span class="code-tag">&lt;wsdl:types&gt;</span>
	<span class="code-tag">&lt;xs:schema targetNamespace=<span class="code-quote">"http://reportincident.example.camel.apache.org"</span>&gt;</span>
			<span class="code-tag">&lt;xs:element name=<span class="code-quote">"inputReportIncident"</span>&gt;</span>
				<span class="code-tag">&lt;xs:complexType&gt;</span>
					<span class="code-tag">&lt;xs:sequence&gt;</span>
						<span class="code-tag">&lt;xs:element type=<span class="code-quote">"xs:string"</span>  name=<span class="code-quote">"incidentId"</span>/&gt;</span>
						<span class="code-tag">&lt;xs:element type=<span class="code-quote">"xs:string"</span>  name=<span class="code-quote">"incidentDate"</span>/&gt;</span>
						<span class="code-tag">&lt;xs:element type=<span class="code-quote">"xs:string"</span>  name=<span class="code-quote">"givenName"</span>/&gt;</span>
						<span class="code-tag">&lt;xs:element type=<span class="code-quote">"xs:string"</span>  name=<span class="code-quote">"familyName"</span>/&gt;</span>
						<span class="code-tag">&lt;xs:element type=<span class="code-quote">"xs:string"</span>  name=<span class="code-quote">"summary"</span>/&gt;</span>
						<span class="code-tag">&lt;xs:element type=<span class="code-quote">"xs:string"</span>  name=<span class="code-quote">"details"</span>/&gt;</span>
						<span class="code-tag">&lt;xs:element type=<span class="code-quote">"xs:string"</span>  name=<span class="code-quote">"email"</span>/&gt;</span>
						<span class="code-tag">&lt;xs:element type=<span class="code-quote">"xs:string"</span>  name=<span class="code-quote">"phone"</span>/&gt;</span>
					<span class="code-tag">&lt;/xs:sequence&gt;</span>
				<span class="code-tag">&lt;/xs:complexType&gt;</span>
			<span class="code-tag">&lt;/xs:element&gt;</span>
			<span class="code-tag">&lt;xs:element name=<span class="code-quote">"outputReportIncident"</span>&gt;</span>
				<span class="code-tag">&lt;xs:complexType&gt;</span>
					<span class="code-tag">&lt;xs:sequence&gt;</span>
						<span class="code-tag">&lt;xs:element type=<span class="code-quote">"xs:string"</span> name=<span class="code-quote">"code"</span>/&gt;</span>
					<span class="code-tag">&lt;/xs:sequence&gt;</span>
				<span class="code-tag">&lt;/xs:complexType&gt;</span>
			<span class="code-tag">&lt;/xs:element&gt;</span>
		<span class="code-tag">&lt;/xs:schema&gt;</span>
	<span class="code-tag">&lt;/wsdl:types&gt;</span>

	<span class="code-tag"><span class="code-comment">&lt;!-- Message definitions for input and output --&gt;</span></span>
	<span class="code-tag">&lt;wsdl:message name=<span class="code-quote">"inputReportIncident"</span>&gt;</span>
		<span class="code-tag">&lt;wsdl:part name=<span class="code-quote">"parameters"</span> element=<span class="code-quote">"tns:inputReportIncident"</span>/&gt;</span>
	<span class="code-tag">&lt;/wsdl:message&gt;</span>
	<span class="code-tag">&lt;wsdl:message name=<span class="code-quote">"outputReportIncident"</span>&gt;</span>
		<span class="code-tag">&lt;wsdl:part name=<span class="code-quote">"parameters"</span> element=<span class="code-quote">"tns:outputReportIncident"</span>/&gt;</span>
	<span class="code-tag">&lt;/wsdl:message&gt;</span>

	<span class="code-tag"><span class="code-comment">&lt;!-- Port (interface) definitions --&gt;</span></span>
	<span class="code-tag">&lt;wsdl:portType name=<span class="code-quote">"ReportIncidentEndpoint"</span>&gt;</span>
		<span class="code-tag">&lt;wsdl:operation name=<span class="code-quote">"ReportIncident"</span>&gt;</span>
			<span class="code-tag">&lt;wsdl:input message=<span class="code-quote">"tns:inputReportIncident"</span>/&gt;</span>
			<span class="code-tag">&lt;wsdl:output message=<span class="code-quote">"tns:outputReportIncident"</span>/&gt;</span>
		<span class="code-tag">&lt;/wsdl:operation&gt;</span>
	<span class="code-tag">&lt;/wsdl:portType&gt;</span>

	<span class="code-tag"><span class="code-comment">&lt;!-- Port bindings to transports and encoding - HTTP, document literal encoding is used --&gt;</span></span>
	<span class="code-tag">&lt;wsdl:binding name=<span class="code-quote">"ReportIncidentBinding"</span> type=<span class="code-quote">"tns:ReportIncidentEndpoint"</span>&gt;</span>
		<span class="code-tag">&lt;soap:binding transport=<span class="code-quote">"http://schemas.xmlsoap.org/soap/http"</span>/&gt;</span>
		<span class="code-tag">&lt;wsdl:operation name=<span class="code-quote">"ReportIncident"</span>&gt;</span>
			&lt;soap:operation
				soapAction=<span class="code-quote">"http://reportincident.example.camel.apache.org/ReportIncident"</span>
				style=<span class="code-quote">"document"</span>/&gt;
			<span class="code-tag">&lt;wsdl:input&gt;</span>
				<span class="code-tag">&lt;soap:body parts=<span class="code-quote">"parameters"</span> use=<span class="code-quote">"literal"</span>/&gt;</span>
			<span class="code-tag">&lt;/wsdl:input&gt;</span>
			<span class="code-tag">&lt;wsdl:output&gt;</span>
				<span class="code-tag">&lt;soap:body parts=<span class="code-quote">"parameters"</span> use=<span class="code-quote">"literal"</span>/&gt;</span>
			<span class="code-tag">&lt;/wsdl:output&gt;</span>
		<span class="code-tag">&lt;/wsdl:operation&gt;</span>
	<span class="code-tag">&lt;/wsdl:binding&gt;</span>

	<span class="code-tag"><span class="code-comment">&lt;!-- Service definition --&gt;</span></span>
	<span class="code-tag">&lt;wsdl:service name=<span class="code-quote">"ReportIncidentService"</span>&gt;</span>
		<span class="code-tag">&lt;wsdl:port name=<span class="code-quote">"ReportIncidentPort"</span> binding=<span class="code-quote">"tns:ReportIncidentBinding"</span>&gt;</span>
			<span class="code-tag">&lt;soap:address location=<span class="code-quote">"http://reportincident.example.camel.apache.org"</span>/&gt;</span>
		<span class="code-tag">&lt;/wsdl:port&gt;</span>
	<span class="code-tag">&lt;/wsdl:service&gt;</span>

<span class="code-tag">&lt;/wsdl:definitions&gt;</span>
</pre>
</div></div>
<h3><a name="Tutorial-Example-ReportIncident-Part1-CXFwsdl2java"></a>CXF wsdl2java</h3>
<p>Then we integration the CXF wsdl2java generator in the pom.xml so we have CXF generate the needed POJO classes for our webservice contract. <br/>
However at first we must configure maven to live in the modern world of Java 1.6 so we must add this to the pom.xml</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
			<span class="code-tag"><span class="code-comment">&lt;!-- to compile with 1.6 --&gt;</span></span>
			<span class="code-tag">&lt;plugin&gt;</span>
				<span class="code-tag">&lt;groupId&gt;</span>org.apache.maven.plugins<span class="code-tag">&lt;/groupId&gt;</span>
				<span class="code-tag">&lt;artifactId&gt;</span>maven-compiler-plugin<span class="code-tag">&lt;/artifactId&gt;</span>
				<span class="code-tag">&lt;configuration&gt;</span>
					<span class="code-tag">&lt;source&gt;</span>1.6<span class="code-tag">&lt;/source&gt;</span>
					<span class="code-tag">&lt;target&gt;</span>1.6<span class="code-tag">&lt;/target&gt;</span>
				<span class="code-tag">&lt;/configuration&gt;</span>
			<span class="code-tag">&lt;/plugin&gt;</span>
</pre>
</div></div>

<p>And then we can add the CXF wsdl2java code generator that will hook into the compile goal so its automatic run all the time:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
			<span class="code-tag"><span class="code-comment">&lt;!-- CXF wsdl2java generator, will plugin to the compile goal --&gt;</span></span>
			<span class="code-tag">&lt;plugin&gt;</span>
				<span class="code-tag">&lt;groupId&gt;</span>org.apache.cxf<span class="code-tag">&lt;/groupId&gt;</span>
				<span class="code-tag">&lt;artifactId&gt;</span>cxf-codegen-plugin<span class="code-tag">&lt;/artifactId&gt;</span>
				<span class="code-tag">&lt;version&gt;</span>${cxf-version}<span class="code-tag">&lt;/version&gt;</span>
				<span class="code-tag">&lt;executions&gt;</span>
					<span class="code-tag">&lt;execution&gt;</span>
						<span class="code-tag">&lt;id&gt;</span>generate-sources<span class="code-tag">&lt;/id&gt;</span>
						<span class="code-tag">&lt;phase&gt;</span>generate-sources<span class="code-tag">&lt;/phase&gt;</span>
						<span class="code-tag">&lt;configuration&gt;</span>
							<span class="code-tag">&lt;sourceRoot&gt;</span>${basedir}/target/generated/src/main/java<span class="code-tag">&lt;/sourceRoot&gt;</span>
							<span class="code-tag">&lt;wsdlOptions&gt;</span>
								<span class="code-tag">&lt;wsdlOption&gt;</span>
									<span class="code-tag">&lt;wsdl&gt;</span>${basedir}/src/main/webapp/WEB-INF/wsdl/report_incident.wsdl<span class="code-tag">&lt;/wsdl&gt;</span>
								<span class="code-tag">&lt;/wsdlOption&gt;</span>
							<span class="code-tag">&lt;/wsdlOptions&gt;</span>
						<span class="code-tag">&lt;/configuration&gt;</span>
						<span class="code-tag">&lt;goals&gt;</span>
							<span class="code-tag">&lt;goal&gt;</span>wsdl2java<span class="code-tag">&lt;/goal&gt;</span>
						<span class="code-tag">&lt;/goals&gt;</span>
					<span class="code-tag">&lt;/execution&gt;</span>
				<span class="code-tag">&lt;/executions&gt;</span>
			<span class="code-tag">&lt;/plugin&gt;</span>
</pre>
</div></div>

<p>You are now setup and should be able to compile the project. So running the <tt>mvn compile</tt> should run the CXF wsdl2java and generate the source code in the folder <tt>&amp;{basedir}/target/generated/src/main/java</tt> that we specified in the pom.xml above. Since its in the <tt>target/generated/src/main/java</tt> maven will pick it up and include it in the build process. </p>

<h3><a name="Tutorial-Example-ReportIncident-Part1-Configurationoftheweb.xml"></a>Configuration of the web.xml</h3>
<p>Next up is to configure the web.xml to be ready to use CXF so we can expose the webservice.<br/>
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:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
	<span class="code-tag"><span class="code-comment">&lt;!-- the listener that kick-starts Spring --&gt;</span></span>
	<span class="code-tag">&lt;listener&gt;</span>
		<span class="code-tag">&lt;listener-class&gt;</span>org.springframework.web.context.ContextLoaderListener<span class="code-tag">&lt;/listener-class&gt;</span>
	<span class="code-tag">&lt;/listener&gt;</span>
</pre>
</div></div>
<p>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 <tt>/webservices/</tt></p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
	<span class="code-tag"><span class="code-comment">&lt;!-- CXF servlet --&gt;</span></span>
	<span class="code-tag">&lt;servlet&gt;</span>
		<span class="code-tag">&lt;servlet-name&gt;</span>CXFServlet<span class="code-tag">&lt;/servlet-name&gt;</span>
		<span class="code-tag">&lt;servlet-class&gt;</span>org.apache.cxf.transport.servlet.CXFServlet<span class="code-tag">&lt;/servlet-class&gt;</span>
		<span class="code-tag">&lt;load-on-startup&gt;</span>1<span class="code-tag">&lt;/load-on-startup&gt;</span>
	<span class="code-tag">&lt;/servlet&gt;</span>

	<span class="code-tag"><span class="code-comment">&lt;!-- all our webservices are mapped under this URI pattern --&gt;</span></span>
	<span class="code-tag">&lt;servlet-mapping&gt;</span>
		<span class="code-tag">&lt;servlet-name&gt;</span>CXFServlet<span class="code-tag">&lt;/servlet-name&gt;</span>
		<span class="code-tag">&lt;url-pattern&gt;</span>/webservices/*<span class="code-tag">&lt;/url-pattern&gt;</span>
	<span class="code-tag">&lt;/servlet-mapping&gt;</span>
</pre>
</div></div>

<p>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 <tt>contextConfigLocation</tt> property in the web.xml</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
	<span class="code-tag"><span class="code-comment">&lt;!-- location of spring xml files --&gt;</span></span>
	<span class="code-tag">&lt;context-param&gt;</span>
		<span class="code-tag">&lt;param-name&gt;</span>contextConfigLocation<span class="code-tag">&lt;/param-name&gt;</span>
		<span class="code-tag">&lt;param-value&gt;</span>classpath:cxf-config.xml<span class="code-tag">&lt;/param-value&gt;</span>
	<span class="code-tag">&lt;/context-param&gt;</span>
</pre>
</div></div>
<p>We have named our CXF configuration file <tt>cxf-config.xml</tt> and its located in the root of the classpath. In Maven land that is we can have the <tt>cxf-config.xml</tt> file in the <tt>src/main/resources</tt> folder. We could also have the file located in the WEB-INF folder for instance <tt>&lt;param-value&gt;/WEB-INF/cxf-config.xml&lt;/param-value&gt;</tt>.</p>

<h3><a name="Tutorial-Example-ReportIncident-Part1-Gettingridoftheoldjspworld"></a>Getting rid of the old jsp world</h3>
<p>The maven archetype that created the basic folder structure also created a sample .jsp file index.jsp. This file <tt>src/main/webapp/index.jsp</tt> should be deleted. </p>

<h3><a name="Tutorial-Example-ReportIncident-Part1-ConfigurationofCXF"></a>Configuration of CXF</h3>
<p>The cxf-config.xml is as follows:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
&lt;beans xmlns=<span class="code-quote">"http://www.springframework.org/schema/beans"</span>
       <span class="code-keyword">xmlns:xsi</span>=<span class="code-quote">"http://www.w3.org/2001/XMLSchema-instance"</span>
       <span class="code-keyword">xmlns:jaxws</span>=<span class="code-quote">"http://cxf.apache.org/jaxws"</span>
       xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"&gt;

    <span class="code-tag">&lt;import resource=<span class="code-quote">"classpath:META-INF/cxf/cxf.xml"</span>/&gt;</span>
    <span class="code-tag">&lt;import resource=<span class="code-quote">"classpath:META-INF/cxf/cxf-extension-soap.xml"</span>/&gt;</span>
    <span class="code-tag">&lt;import resource=<span class="code-quote">"classpath:META-INF/cxf/cxf-servlet.xml"</span>/&gt;</span>

    <span class="code-tag"><span class="code-comment">&lt;!-- implementation of the webservice --&gt;</span></span>
    <span class="code-tag">&lt;bean id=<span class="code-quote">"reportIncidentEndpoint"</span> class=<span class="code-quote">"org.apache.camel.example.reportincident.ReportIncidentEndpointImpl"</span>/&gt;</span>

    <span class="code-tag"><span class="code-comment">&lt;!-- export the webservice using jaxws --&gt;</span></span>
    &lt;jaxws:endpoint id=<span class="code-quote">"reportIncident"</span>
                    implementor=<span class="code-quote">"#reportIncidentEndpoint"</span>
                    address=<span class="code-quote">"/incident"</span>
                    wsdlLocation=<span class="code-quote">"/WEB-INF/wsdl/report_incident.wsdl"</span>
                    endpointName=<span class="code-quote">"s:ReportIncidentPort"</span>
                    serviceName=<span class="code-quote">"s:ReportIncidentService"</span>
                    <span class="code-keyword">xmlns:s</span>=<span class="code-quote">"http://reportincident.example.camel.apache.org"</span>/&gt;

<span class="code-tag">&lt;/beans&gt;</span>
</pre>
</div></div>

<p>The configuration is standard <a href="/confluence/display/CAMEL/CXF" title="CXF">CXF</a> and is documented at the <a href="http://cxf.apache.org/" class="external-link" rel="nofollow">Apache CXF website</a>.</p>

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

<p>Noticed that we have a spring bean <b>reportIncidentEndpoint</b> that is the implementation of the webservice endpoint we let CXF expose.<br/>
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 stated the classname directly as <tt>implementor="org.apache.camel.example.reportincident.ReportIncidentEndpoint"</tt> but then we lose the ability to let the ReportIncidentEndpoint be configured by spring.<br/>
The <b>address</b> attribute defines the relative part of the URL of the exposed webservice. <b>wsdlLocation</b> 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.</p>

<h3><a name="Tutorial-Example-ReportIncident-Part1-ImplementingtheReportIncidentEndpoint"></a>Implementing the ReportIncidentEndpoint</h3>
<p>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 <tt>mvn compile</tt> to let CXF generate the POJO classes for our webservice and we are ready to fire up a Java editor.</p>

<p>You can use <tt>mvn idea:idea</tt> or <tt>mvn eclipse:eclipse</tt> 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.</p>

<p>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 Java 1.5 we get annotations for the money, but they reside on the interface so we can remove them from our implementations so its a nice plain POJO again:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">package</span> org.apache.camel.example.reportincident;

/**
 * The webservice we have implemented.
 */
<span class="code-keyword">public</span> class ReportIncidentEndpointImpl <span class="code-keyword">implements</span> ReportIncidentEndpoint {

    <span class="code-keyword">public</span> OutputReportIncident reportIncident(InputReportIncident parameters) {
        <span class="code-object">System</span>.out.println(<span class="code-quote">"Hello ReportIncidentEndpointImpl is called from "</span> + parameters.getGivenName());

        OutputReportIncident out = <span class="code-keyword">new</span> OutputReportIncident();
        out.setCode(<span class="code-quote">"OK"</span>);
        <span class="code-keyword">return</span> out;
    }

}
</pre>
</div></div>

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

<p>To test if we are home free we run <tt>mvn clean compile</tt>.</p>

<h3><a name="Tutorial-Example-ReportIncident-Part1-Runningourwebservice"></a>Running our webservice</h3>
<p>Now that the code compiles we would like to run it inside a web container, for this purpose we make use of Jetty which we will bootstrap using it's plugin <tt>org.mortbay.jetty:maven-jetty-plugin</tt>:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
       <span class="code-tag">&lt;build&gt;</span>
           <span class="code-tag">&lt;plugins&gt;</span>
               ...
               <span class="code-tag"><span class="code-comment">&lt;!-- so we can run mvn jetty:run --&gt;</span></span>
               <span class="code-tag">&lt;plugin&gt;</span>
                   <span class="code-tag">&lt;groupId&gt;</span>org.mortbay.jetty<span class="code-tag">&lt;/groupId&gt;</span>
                   <span class="code-tag">&lt;artifactId&gt;</span>maven-jetty-plugin<span class="code-tag">&lt;/artifactId&gt;</span>
                   <span class="code-tag">&lt;version&gt;</span>${jetty-version}<span class="code-tag">&lt;/version&gt;</span>
               <span class="code-tag">&lt;/plugin&gt;</span>
</pre>
</div></div>
<p><b>Notice:</b> We make use of the Jetty version being defined inside the <a href="https://svn.apache.org/repos/asf/camel/trunk/parent/pom.xml" class="external-link" rel="nofollow">Camel's Parent POM</a>.</p>

<p>So to see if everything is in order we fire up jetty with <tt>mvn jetty:run</tt> and if everything is okay you should be able to access <tt><a href="http://localhost:8080" class="external-link" rel="nofollow">http://localhost:8080</a></tt>.<br/>
Jetty is smart that it will list the correct URI on the page to our web application, so just click on the link. This is smart as you don't have to remember the exact web context URI for your application - just fire up the default page and Jetty will help you.</p>

<p>So where is the damn webservice then? Well as we did configure the web.xml to instruct the CXF servlet to accept the pattern <tt>/webservices/*</tt> we should hit this URL to get the attention of CXF: <tt><a href="http://localhost:8080/camel-example-reportincident/webservices" class="external-link" rel="nofollow">http://localhost:8080/camel-example-reportincident/webservices</a></tt>.<br/>
<span class="image-wrap" style=""><img src="/confluence/download/attachments/90920/tutorial_reportincident_cxf_servicelist2.png?version=1&amp;modificationDate=1216691617000" style="border: 0px solid black" /></span><br/>
&nbsp;</p>

<h3><a name="Tutorial-Example-ReportIncident-Part1-Hittingthewebservice"></a>Hitting the webservice</h3>
<p>Now we have the webservice running in a standard .war application in a standard web container such as Jetty we would like to invoke the webservice and see if we get our code executed. Unfortunately this isn't the easiest task in the world - its not so easy as a REST URL, so we need tools for this. So we fire up our trusty webservice tool <a href="http://www.soapui.org/" class="external-link" rel="nofollow">SoapUI</a> and let it be the one to fire the webservice request and see the response.</p>

<p>Using SoapUI we sent a request to our webservice and we got the expected OK response and the console outputs the System.out so we are ready to code.<br/>
<span class="image-wrap" style=""><img src="/confluence/download/attachments/90920/tutorial_reportincident_soapui2.png?version=1&amp;modificationDate=1216691574000" style="border: 0px solid black" /></span><br/>
&nbsp;</p>

<h3><a name="Tutorial-Example-ReportIncident-Part1-RemoteDebugging"></a>Remote Debugging</h3>
<p>Okay a little sidestep but wouldn't it be cool to be able to debug your code when its fired up under Jetty? As Jetty is started from maven, we need to instruct maven to use debug mode. <br/>
Se we set the <tt>MAVEN_OPTS</tt> environment to start in debug mode and listen on port 5005.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
MAVEN_OPTS=-Xmx512m -XX:MaxPermSize=128m -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005
</pre>
</div></div>

<p>Then you need to restart Jetty so its stopped with <b>ctrl + c</b>. Remember to start a new shell to pickup the new environment settings. And start jetty again.</p>

<p>Then we can from our IDE attach a remote debugger and debug as we want.<br/>
First we configure IDEA to attach to a remote debugger on port 5005:<br/>
<span class="image-wrap" style=""><img src="/confluence/download/attachments/90920/tutorial_reportincident_remotedebug_idea_setup2.png?version=1&amp;modificationDate=1216691605000" style="border: 0px solid black" /></span><br/>
&nbsp;</p>

<p>Then we set a breakpoint in our code <tt>ReportIncidentEndpoint</tt> and hit the SoapUI once again and we are breaked at the breakpoint where we can inspect the parameters:<br/>
<span class="image-wrap" style=""><img src="/confluence/download/attachments/90920/tutorial_reportincident_remotedebug_idea_breakpoint2.png?version=1&amp;modificationDate=1216691590000" style="border: 0px solid black" /></span><br/>
&nbsp;</p>

<h3><a name="Tutorial-Example-ReportIncident-Part1-Addingaunittest"></a>Adding a unit test</h3>
<p>Oh so much hard work just to hit a webservice, why can't we just use an unit test to invoke our webservice? Yes of course we can do this, and that's the next step.<br/>
First we create the folder structure <tt>src/test/java</tt> and <tt>src/test/resources</tt>. We then create the unit test in the <tt>src/test/java</tt> folder.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
<span class="code-keyword">package</span> org.apache.camel.example.reportincident;

<span class="code-keyword">import</span> junit.framework.TestCase;

/**
 * Plain JUnit test of our webservice.
 */
<span class="code-keyword">public</span> class ReportIncidentEndpointTest <span class="code-keyword">extends</span> TestCase {

}
</pre>
</div></div>
<p>Here we have a plain old JUnit class. As we want to test webservices we need to start and expose our webservice in the unit test before we can test it. And JAXWS has pretty decent methods to help us here, the code is simple as:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    <span class="code-keyword">import</span> javax.xml.ws.Endpoint;
    ...

    <span class="code-keyword">private</span> <span class="code-keyword">static</span> <span class="code-object">String</span> ADDRESS = <span class="code-quote">"http:<span class="code-comment">//localhost:9090/unittest"</span>;
</span>
    <span class="code-keyword">protected</span> void startServer() <span class="code-keyword">throws</span> Exception {
        <span class="code-comment">// We need to start a server that exposes or webservice during the unit testing
</span>        <span class="code-comment">// We use jaxws to <span class="code-keyword">do</span> <span class="code-keyword">this</span> pretty simple
</span>        ReportIncidentEndpointImpl server = <span class="code-keyword">new</span> ReportIncidentEndpointImpl();
        Endpoint.publish(ADDRESS, server);
    }
</pre>
</div></div>

<p>The Endpoint class is the <tt>javax.xml.ws.Endpoint</tt> that under the covers looks for a provider and in our case its CXF - so its CXF that does the heavy lifting of exposing out webservice on the given URL address. Since our class ReportIncidentEndpointImpl implements the interface <b>ReportIncidentEndpoint</b> that is decorated with all the jaxws annotations it got all the information it need to expose the webservice. Below is the CXF wsdl2java generated interface:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">

/*
 * 
 */

<span class="code-keyword">package</span> org.apache.camel.example.reportincident;

<span class="code-keyword">import</span> javax.jws.WebMethod;
<span class="code-keyword">import</span> javax.jws.WebParam;
<span class="code-keyword">import</span> javax.jws.WebResult;
<span class="code-keyword">import</span> javax.jws.WebService;
<span class="code-keyword">import</span> javax.jws.soap.SOAPBinding;
<span class="code-keyword">import</span> javax.jws.soap.SOAPBinding.ParameterStyle;
<span class="code-keyword">import</span> javax.xml.bind.annotation.XmlSeeAlso;

/**
 * This class was generated by Apache CXF 2.1.1
 * Wed Jul 16 12:40:31 CEST 2008
 * Generated source version: 2.1.1
 * 
 */
 
 /*
  * 
  */


@WebService(targetNamespace = <span class="code-quote">"http:<span class="code-comment">//reportincident.example.camel.apache.org"</span>, name = <span class="code-quote">"ReportIncidentEndpoint"</span>)
</span>@XmlSeeAlso({ObjectFactory.class})
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)

<span class="code-keyword">public</span> <span class="code-keyword">interface</span> ReportIncidentEndpoint {

/*
 * 
 */

    @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
    @WebResult(name = <span class="code-quote">"outputReportIncident"</span>, targetNamespace = <span class="code-quote">"http:<span class="code-comment">//reportincident.example.camel.apache.org"</span>, partName = <span class="code-quote">"parameters"</span>)
</span>    @WebMethod(operationName = <span class="code-quote">"ReportIncident"</span>, action = <span class="code-quote">"http:<span class="code-comment">//reportincident.example.camel.apache.org/ReportIncident"</span>)
</span>    <span class="code-keyword">public</span> OutputReportIncident reportIncident(
        @WebParam(partName = <span class="code-quote">"parameters"</span>, name = <span class="code-quote">"inputReportIncident"</span>, targetNamespace = <span class="code-quote">"http:<span class="code-comment">//reportincident.example.camel.apache.org"</span>)
</span>        InputReportIncident parameters
    );
}
</pre>
</div></div>

<p>Next up is to create a webservice client so we can invoke our webservice. For this we actually use the CXF framework directly as its a bit more easier to create a client using this framework than using the JAXWS style. We could have done the same for the server part, and you should do this if you need more power and access more advanced features.</p>

<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    <span class="code-keyword">import</span> org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
    ...
    
    <span class="code-keyword">protected</span> ReportIncidentEndpoint createCXFClient() {
        <span class="code-comment">// we use CXF to create a client <span class="code-keyword">for</span> us as its easier than JAXWS and works
</span>        JaxWsProxyFactoryBean factory = <span class="code-keyword">new</span> JaxWsProxyFactoryBean();
        factory.setServiceClass(ReportIncidentEndpoint.class);
        factory.setAddress(ADDRESS);
        <span class="code-keyword">return</span> (ReportIncidentEndpoint) factory.create();
    }
</pre>
</div></div>

<p>So now we are ready for creating a unit test. We have the server and the client. So we just create a plain simple unit test method as the usual junit style:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
    <span class="code-keyword">public</span> void testRendportIncident() <span class="code-keyword">throws</span> Exception {
        startServer();

        ReportIncidentEndpoint client = createCXFClient();

        InputReportIncident input = <span class="code-keyword">new</span> InputReportIncident();
        input.setIncidentId(<span class="code-quote">"123"</span>);
        input.setIncidentDate(<span class="code-quote">"2008-07-16"</span>);
        input.setGivenName(<span class="code-quote">"Claus"</span>);
        input.setFamilyName(<span class="code-quote">"Ibsen"</span>);
        input.setSummary(<span class="code-quote">"bla bla"</span>);
        input.setDetails(<span class="code-quote">"more bla bla"</span>);
        input.setEmail(<span class="code-quote">"davsclaus@apache.org"</span>);
        input.setPhone(<span class="code-quote">"+45 2962 7576"</span>);

        OutputReportIncident out = client.reportIncident(input);
        assertEquals(<span class="code-quote">"Response code is wrong"</span>, <span class="code-quote">"OK"</span>, out.getCode());
    }
</pre>
</div></div>

<p>Now we are nearly there. But if you run the unit test with <tt>mvn test</tt> then it will fail. Why!!! Well its because that CXF needs is missing some dependencies during unit testing. In fact it needs the web container, so we need to add this to our <b>pom.xml</b>.</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-xml">
    <span class="code-tag"><span class="code-comment">&lt;!-- cxf web container for unit testing --&gt;</span></span>
    <span class="code-tag">&lt;dependency&gt;</span>
        <span class="code-tag">&lt;groupId&gt;</span>org.apache.cxf<span class="code-tag">&lt;/groupId&gt;</span>
        <span class="code-tag">&lt;artifactId&gt;</span>cxf-rt-transports-http-jetty<span class="code-tag">&lt;/artifactId&gt;</span>
        <span class="code-tag">&lt;version&gt;</span>${cxf-version}<span class="code-tag">&lt;/version&gt;</span>
        <span class="code-tag">&lt;scope&gt;</span>test<span class="code-tag">&lt;/scope&gt;</span>
    <span class="code-tag">&lt;/dependency&gt;</span>
</pre>
</div></div>

<p>Well what is that, CXF also uses Jetty for unit test - well its just shows how agile, embedable and popular Jetty is.</p>

<p>So lets run our junit test with, and it reports:</p>
<div class="code panel" style="border-width: 1px;"><div class="codeContent panelContent">
<pre class="code-java">
mvn test
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO] BUILD SUCCESSFUL
</pre>
</div></div>

<p>Yep thats it for now. We have a basic project setup.</p>


<h2><a name="Tutorial-Example-ReportIncident-Part1-Endofpart1"></a>End of part 1</h2>
<p>Thanks for being patient and reading all this more or less standard Maven, Spring, JAXWS and Apache CXF stuff. Its stuff that is well covered on the net, but I wanted a full fledged tutorial on a maven project setup that is web service ready with Apache CXF. We will use this as a base for the next part where we demonstrate how Camel can be digested slowly and piece by piece just as it was back in the times when was introduced and was learning the Spring framework that we take for granted today. </p>

<h2><a name="Tutorial-Example-ReportIncident-Part1-%23Resources"></a><a href="#Tutorial-Example-ReportIncident-Part1-Resources">Resources</a></h2>
<ul>
	<li><a href="http://cwiki.apache.org/CXF20DOC/index.html" class="external-link" rel="nofollow">Apache CXF user guide</a></li>
</ul>


<h2><a name="Tutorial-Example-ReportIncident-Part1-Links"></a>Links</h2>
<ul class="alternate" type="square">
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident" title="Tutorial-Example-ReportIncident">Introduction</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part1" title="Tutorial-Example-ReportIncident-Part1">Part 1</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part2" title="Tutorial-Example-ReportIncident-Part2">Part 2</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part3" title="Tutorial-Example-ReportIncident-Part3">Part 3</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part4" title="Tutorial-Example-ReportIncident-Part4">Part 4</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part5" title="Tutorial-Example-ReportIncident-Part5">Part 5</a></li>
	<li><a href="/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part6" title="Tutorial-Example-ReportIncident-Part6">Part 6</a></li>
</ul>

    </div>
        <div id="commentsSection" class="wiki-content pageSection">
        <div style="float: right;">
            <a href="https://cwiki.apache.org/confluence/users/viewnotifications.action" class="grey">Change Notification Preferences</a>
        </div>
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part1">View Online</a>
        |
        <a href="https://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=90920&revisedVersion=28&originalVersion=27">View Changes</a>
                |
        <a href="https://cwiki.apache.org/confluence/display/CAMEL/Tutorial-Example-ReportIncident-Part1?showComments=true&amp;showCommentArea=true#addcomment">Add Comment</a>
            </div>
</div>
</div>
</div>
</div>
</body>
</html>

Mime
View raw message