Raible's Wiki

Raible Designs
Wiki Home
News
Recent Changes

AppFuse

Homepage
  - Korean
  - Chinese
  - Italian
  - Japanese

QuickStart Guide
  - Chinese
  - French
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish
  - Japanese

User Guide
  - Korean
  - Chinese

Tutorials
  - Chinese
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish

FAQ
  - Korean

Latest Downloads

Other Applications

Struts Resume
Security Example
Struts Menu

Set your name in
UserPreferences


Referenced by
AppFuseAxis
AppFuseXFireOld
AppFuseXFireOpenLasz...
Articles
XFireAegisMapping




JSPWiki v2.2.33

[RSS]


Hide Menu

AppFuseXFire


This is version 8. It is not the current version, and thus it cannot be edited.
[Back to current version]   [Restore this version]


Part I: Integrating XFire Webservices into AppFuse - A HowTo for providing Webservices from within AppFuse.

About this Tutorial

This tutorial will show you how to create a Webservice Endpoint and what you can do to automate the creation of artifacts necessary to provide Webservices to others.

Table of Contents

  • [0] Preface
  • [1] Download the prerequisite packages
  • [2] Add the packages to AppFuse's lib structure
  • [3] Modify the build script to include the packages
  • [4] Add the XFireServlet definition
  • [5] Create an xdoclet-task in build.xml to generate aegis.xml mapping files
  • [6] Expose a Manager as a webservice

Preface [#0]

You may wonder, why I bother to write a howto for XFire, given that there is already one for Axis, the far more widely used Webservice framework. But you may wonder as well, why the codehaus people bother writing XFire at all, years after Axis was published in the first place. The reason for the latter, in my personal opinion, is that Axis 1 has some shortfalls. Namely dealing with Collections and it is not so easy to plug in another XML binding framework. Why should you not be comfortable with the built in XML binding? Because it is not as powerful as for example XmlBeans. You have to limit your application to a subset of what's possible with webservices. Another, in some cases important benefit is performance (in terms of speed), that is because the next generation webservice frameworks (like Axis 2 and XFire) are based an StAX, the Streaming Api for Xml. Apache is aware of this limitations of Axis 1 and has taken Axis 2 on board as a replacement build from scratch for Axis 1. Axis 2 is (as well as XFire) in pre 1.0 state, XFire is, however, just a few days away from it's 1.0 as of Feb 2006. My motivation to use XFire instead of Axis 2 is, that I started using it, was successful in short time, and just stuck with it, becoming a committer of the project.

There's work in progress to automate the process of plugging in XFire into AppFuse (via an extras package), you'll find the first shot version attached to this page as zip.

All that's described on this page is performed by an ant-task in this package. Expand it in the extras folder of your project, go into the folder xfire-webservice with a shell and do an

   ant install
there. It will install the necessary files and do the changes described below.

Download the prerequistie packages [#1]

Currently I recommend the nightly snapshot of XFire. This may change with the release of 1.0, but the latest milestone 1.0M6a has got some problems that have been fixed in CVS. It is available from the Codehaus XFire site. You'll find source and binary distribution in one file here xfire-all-1.0-SNAPSHOT.zip. When you open the zip, you'll find a lot of xfire-xxx.jars. This is because XFire has various options for XML binding, configuration and container-integration. In this howto we'll focus on Aegis for binding and Spring integration, so all you need of the xfire-jars are:
  • xfire-core-1.0-SNAPSHOT.jar
  • xfire-aegis-1.0-SNAPSHOT.jar
  • xfire-spring-1.0-SNAPSHOT.jar

plus some of the third-party libs you'll find in the libs/runtime dir of the zip. Later, we'll use some of the libs from libs/test as well, because I'll show you how you can setup testcases in the webservice field really easy.

Add the packages to AppFuse's lib structure [#2]

  1. Create the following folder structure in your project directory:
lib/
   xfire-1.0-SNAPSHOT/
      lib/runtime
      lib/test

Copy the following files into the xfire-1.0-SNAPSHOT/lib/runtime folder:

from the root of the zip

  • xfire-core-1.0-SNAPSHOT.jar
  • xfire-aegis-1.0-SNAPSHOT.jar
  • xfire-spring-1.0-SNAPSHOT.jar

from the lib/runtime folder

  • jaxen-1.1-beta-8.jar
  • jdom-1.0.jar
  • stax-1.1.2-dev.jar
  • stax-api-1.0.jar
  • stax-util-snapshot-20040917.jar

additionally, you need wsdl4j-1.5.2.jar which is available here

  • wsdl4j-1.5.2.jar

some other required libs under libs/runtime you already have in other lib directories of appfuse. Currently, there are no version conflicts with the 1.8 version of appfuse. If there are some with the new 1.9 version, I'll see to sort them out and amend this howto.

Copy the following files from the libs/test dir to xfire-1.0-SNAPSHOT/lib/test

  • easymock-1.1.jar
  • httpunit-1.5.1.jar
  • xmlunit-1.0.jar

Now add the following to lib.properties

#
# XFire - http://xfire.codehaus.org
#
xfire.version=1.0-SNAPHOST
xfire.dir=${lib.dir}/xfire-${xfire.version}/lib/runtime
xfire.test.dir=${lib.dir}/xfire-${xfire.version}/lib/test

Modify the build script to include these packages [#3]

Now that AppFuse is aware of the new libraries, we need to include them in the build process.

We must modify the package-web target, to add the following to the lib directives for the war task:

   ...
   <lib dir="${xfire.dir}" includes="*.jar"/>
</war>

Additinally we need to put the xfire libs into the compile-service classpath in properties.xml(just below <path id="service.compile.classpath">):

	<fileset dir="${xfire.dir}" includes="*.jar"/>
and the corresponding test classpath
	<fileset dir="${xfire.test.dir}" includes="*.jar"/>

Add the XFireServlet definition [#4]

Actually there are two servlets, you could choose. One is the Spring integration of XFire servlet, the other the XFire integration of Spring servlet. You see, the both projects love each other :-) We'll go with the Spring way, known as XFireConfigurableServlet. One of the major differences is, that the XFire way creates the Spring appContext in the servlet, something that we don't need, as we already have a Spring enabled web application. If you want to create a webservice-only application, you can use the org.codehaus.xfire.transport.http.XFireConfigurableServlet instead, so that you don't need to use Springs startup-servlet or listener to load the appContext (if you don't know, what I'm talking about, you probably don't need it :-)

Now it depends on the appfuse version you have. In versions below 1.9, the servlet-configuration is done under metadata/web in the servlets.xml and servlet-mapping.xml files. From 1.9 on, there is a web.xml file under web/WEB_INF. However, I assume, that you as a web developer know your web.xml. Open web/WEB-INF/web.xml and add the following:

  <!-- XFire servlet definition and mapping -->
  <servlet>
    <servlet-name>XFireServlet</servlet-name>
    <servlet-class>
      org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>XFireServlet</servlet-name>
    <url-pattern>/servlet/XFireServlet/*</url-pattern>
  </servlet-mapping>

  <servlet-mapping>
    <servlet-name>XFireServlet</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>

Additionally it makes sense to add mime-mappings in the web.xml file:

    <!-- currently the W3C havent settled on a media type for WSDL;
         http://www.w3.org/TR/2003/WD-wsdl12-20030303/#ietf-draft
         for now we go with the basic 'it's XML' response -->
    <mime-mapping>
       <extension>wsdl</extension>
       <mime-type>text/xml</mime-type>
    </mime-mapping>
    <mime-mapping>
       <extension>xsd</extension>
       <mime-type>text/xml</mime-type>
    </mime-mapping>

The DispatcherServlet expects your Spring service definition in a file named XFire-servlet.xml under WEB-INF. The first definition (SimpleUrlHandlerMapping) tells the DispatcherServlet, that it should pass a request to "services/UserService" to the bean named "userWebservice". The second is the declaration of this web service. We delegate the requests directly to the bean "userManager" using the interface UserManager. userManager itself is declared in your applicationContext-service.xml. You see how smooth xfire integrates with Spring again. No boilerplate code between the servlet and the POJO Manager bean. Only a bit of xml wiring them together.

You may have noticed the import. That file contains definitions for beans integrated with Spring from xfire. There you can find the spring bean declarations of "xfire", "xfire.serviceFactory" and some more. The doc on the xfire site gives the advice to put that in the global application-context declaration in your web.xml, but I thought it is more clear just to expose this to the context that deals with the xfire webservices rather than the root application context.

Create a new file und web/WEB-INF named "XFire-servlet.xml" and paste the following into it:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
    "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
	<import resource="classpath:org/codehaus/xfire/spring/xfire.xml"/>
	
	<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="urlMap">
			<map>
				<entry key="/UserService">
					<ref bean="userWebservice" />
				</entry>
			</map>
		</property>
	</bean>

	<!-- Declare a parent bean with all properties common to both services -->
	<bean id="userWebservice" class="org.codehaus.xfire.spring.remoting.XFireExporter">
		<property name="serviceFactory">
			<ref bean="xfire.serviceFactory" />
		</property>
		<property name="xfire">
			<ref bean="xfire" />
		</property>
		<property name="serviceBean">
			<ref bean="userManager" />
		</property>
		<property name="serviceInterface">
			<value>org.appfuse.service.UserManager</value>
		</property>
	</bean>
</beans>

In principle you'd be done here. You could deploy the application and call the webservice. But because the UserManager has got a method "List getUsers()", we need to tell xfire, what components to expect to get back when calling this method.

Create an xdoclet-task in build.xml to generate the aegis.xml mapping files [#5]

XFire doesn't need a .wsdd file like axis, because all services are configured via Spring and optional additional files. In this howto, we use aegis-mapping, which works on xml descriptors to provide information XFire can't obtain through introspection from the class files. Another method is to annotate the classes with java 5 annotations (covered by xfire-java5) or with commons-annotations (xfire-annotations). It's beyond the scope of this howto to explain all possibilities, so we stick with aegis.

Normally you'd create the xxx.aegis.xml mapping files by hand, but as we are used to xdoclet tags in AppFuse, I wrote a template doing that for us. The xxx.aegis.xml files go into the package structure like property files, so if you want to provide a mapping for org.appfuse.model.User, you just put it there under org.appfuse.model.User.aegis.xml.

What you can do with the mappings is described here. There's a schema for the xml here.

Create a file named aegis-mapping.xdt in metadata/templates:

<?xml version="1.0" encoding="utf-8"?>
<mappings<XDtClass:ifHasClassTag tagName="aegis.mapping" paramName="xmlns"> 
	xmlns:<XDtClass:className/>="<XDtClass:classTagValue tagName="aegis.mapping" paramName="xmlns"/>"</XDtClass:ifHasClassTag>>
	<mapping
		<XDtClass:ifHasClassTag tagName="aegis.mapping" paramName="name"> name="
			<XDtClass:ifHasClassTag tagName="aegis.mapping" paramName="xmlns"><XDtClass:className/>:</XDtClass:ifHasClassTag>
				<XDtClass:classTagValue tagName="aegis.mapping" paramName="name"/>"
			</XDtClass:ifHasClassTag>
			<XDtClass:ifHasClassTag tagName="aegis.mapping" paramName="uri"> 
				uri="<XDtClass:classTagValue tagName="aegis.mapping" paramName="uri"/>"
			</XDtClass:ifHasClassTag>>
	<XDtMethod:forAllMethods>
		<XDtMethod:ifHasMethodTag tagName="aegis.property"><property
			<XDtMethod:ifHasMethodTag tagName="aegis.property" paramName="name"> 
				name="<XDtMethod:methodTagValue tagName="aegis.property" paramName="name"/>"
			</XDtMethod:ifHasMethodTag>
			<XDtMethod:ifDoesntHaveMethodTag tagName="aegis.property" paramName="name"> 
				name="<XDtMethod:propertyName/>"
			</XDtMethod:ifDoesntHaveMethodTag>
			<XDtMethod:ifHasMethodTag tagName="aegis.property" paramName="type"> 
				type="<XDtMethod:methodTagValue tagName="aegis.property" paramName="type"/>"
			</XDtMethod:ifHasMethodTag>
			<XDtMethod:ifHasMethodTag tagName="aegis.property" paramName="mappedName"> 
				mappedName="<XDtMethod:methodTagValue tagName="aegis.property" paramName="mappedName"/>"
			</XDtMethod:ifHasMethodTag>
			<XDtMethod:ifHasMethodTag tagName="aegis.property" paramName="nillable"> 
				nillable="<XDtMethod:methodTagValue tagName="aegis.property" paramName="nillable"/>"
			</XDtMethod:ifHasMethodTag>
			<XDtMethod:ifHasMethodTag tagName="aegis.property" paramName="ignore"> 
				ignore="<XDtMethod:methodTagValue tagName="aegis.property" paramName="ignore"/>"
			</XDtMethod:ifHasMethodTag>
			<XDtMethod:ifHasMethodTag tagName="aegis.property" paramName="componentType"> 
				componentType="<XDtMethod:methodTagValue tagName="aegis.property" paramName="componentType"/>"
			</XDtMethod:ifHasMethodTag>
			<XDtMethod:ifHasMethodTag tagName="aegis.property" paramName="style"> 
				style="<XDtMethod:methodTagValue tagName="aegis.property" paramName="style"/>"
			</XDtMethod:ifHasMethodTag>/>
		</XDtMethod:ifHasMethodTag>
		<XDtMethod:ifHasMethodTag tagName="aegis.method"><method
			<XDtMethod:ifHasMethodTag tagName="aegis.method" paramName="name"> 
				name="<XDtMethod:methodTagValue tagName="aegis.method" paramName="name"/>"
			</XDtMethod:ifHasMethodTag>
			<XDtMethod:ifDoesntHaveMethodTag tagName="aegis.method" paramName="name"> 
				name="<XDtMethod:methodName/>"
			</XDtMethod:ifDoesntHaveMethodTag>>
			<XDtMethod:ifHasMethodTag tagName="aegis.method-return-type"><return-type
				<XDtMethod:ifHasMethodTag tagName="aegis.method-return-type" paramName="keyType"> 
					keyType="<XDtMethod:methodTagValue tagName="aegis.method-return-type" paramName="keyType"/>"
				</XDtMethod:ifHasMethodTag>
				<XDtMethod:ifHasMethodTag tagName="aegis.method-return-type" paramName="componentType"> 
					componentType="<XDtMethod:methodTagValue tagName="aegis.method-return-type" paramName="componentType"/>"
				</XDtMethod:ifHasMethodTag>
				<XDtMethod:ifHasMethodTag tagName="aegis.method-return-type" paramName="mappedName"> 
					mappedName="<XDtMethod:methodTagValue tagName="aegis.method-return-type" paramName="mappedName"/>"
				</XDtMethod:ifHasMethodTag>
				<XDtMethod:ifHasMethodTag tagName="aegis.method-return-type" paramName="typeName"> 
					typeName="<XDtMethod:methodTagValue tagName="aegis.method-return-type" paramName="typeName"/>"
				</XDtMethod:ifHasMethodTag>
				<XDtMethod:ifHasMethodTag tagName="aegis.method-return-type" paramName="type"> 
					type="<XDtMethod:methodTagValue tagName="aegis.method-return-type" paramName="type"/>"
				</XDtMethod:ifHasMethodTag>/>
			</XDtMethod:ifHasMethodTag>
			<XDtMethod:ifHasMethodTag tagName="aegis.method-parameter">
				<XDtMethod:forAllMethodTags tagName="aegis.method-parameter"><parameter
					<XDtMethod:ifHasMethodTag tagName="aegis.method-parameter" paramName="index"> 
						index="<XDtMethod:methodTagValue tagName="aegis.method-parameter" paramName="index"/>"
					</XDtMethod:ifHasMethodTag>
					<XDtMethod:ifHasMethodTag tagName="aegis.method-parameter" paramName="keyType"> 
						keyType="<XDtMethod:methodTagValue tagName="aegis.method-parameter" paramName="keyType"/>"
					</XDtMethod:ifHasMethodTag>
					<XDtMethod:ifHasMethodTag tagName="aegis.method-parameter" paramName="componentType"> 
						componentType="<XDtMethod:methodTagValue tagName="aegis.method-parameter" paramName="componentType"/>"
					</XDtMethod:ifHasMethodTag>
					<XDtMethod:ifHasMethodTag tagName="aegis.method-parameter" paramName="mappedName"> 
						mappedName="<XDtMethod:methodTagValue tagName="aegis.method-parameter" paramName="mappedName"/>"
					</XDtMethod:ifHasMethodTag>
					<XDtMethod:ifHasMethodTag tagName="aegis.method-parameter" paramName="typeName"> 
						typeName="<XDtMethod:methodTagValue tagName="aegis.method-parameter" paramName="typeName"/>"
					</XDtMethod:ifHasMethodTag>
					<XDtMethod:ifHasMethodTag tagName="aegis.method-parameter" paramName="type"> 
						type="<XDtMethod:methodTagValue tagName="aegis.method-parameter" paramName="type"/>"
					</XDtMethod:ifHasMethodTag>/>
				</XDtMethod:forAllMethodTags>
			</XDtMethod:ifHasMethodTag>
		</method>
		</XDtMethod:ifHasMethodTag>
	</XDtMethod:forAllMethods>
	</mapping>
</mappings>
(I reformatted the file to make it more readable, but it doesn't generate nice looking xml in that form. I recommend using this version)

Tags recognized are:

Class-Level:
   @aegis.mapping
         xmlns=""
         name=""
         uri=""

Method-Level:
   @aegis.property
         name=""
         type=""
         mappedName=""
         nillable=""
         ignore=""
         componentType=""
         style=""

   @aegis.method
         name=""

   @aegis.method-return-type
         keyType=""
         componentType=""
         mappedName=""
         typeName=""
         type=""

		@aegis.method-parameter
					index=""
					keyType=""
					componentType=""
					mappedName=""
					typeName=""
					type=""

First create the bit that resolves the getUsers() List component type:

[...}
 * @aegis.mapping
 */
public interface UserManager {
[...]
     * @aegis.method-return-type componentType="org.appfuse.model.User" 
     */
    public List getUsers(User user);
[...]

The same issue comes up in the User type itself and in the Role type.

For User.java this looks like

[...]
 *
 * @struts.form include-all="true" extends="BaseForm"
 * @hibernate.class table="app_user"
 * @aegis.mapping
 */
public class User extends BaseObject implements Serializable, UserDetails {
    private static final long serialVersionUID = 3832626162173359411L;
[...]
    /**
     * @struts.validator type="required"
     * @hibernate.id length="20" generator-class="assigned" unsaved-value="version"
     * @aegis.property name="Username"
     */
    public String getUsername() {
        return username;
    }
[...]
    /**
     * Returns the full name.
     * @aegis.property ignore="true"
     */
    public String getFullName() {
        return firstName + ' ' + lastName;
    }
[...]
     * @aegis.property componentType="org.appfuse.model.Role"
     */
    public Set getRoles() {
        return roles;
    }

and for Role we have the same Collection resolving plus we need to get rid of the circular reference to User. This is because xfire is about document/literal style webservices. What that is compared to jax-rpc is best explained here. document/literal doesn't have references in the xml that it understands. So if we would keep that circular reference, we would get a StackOverflowException.

[...]
 * @hibernate.class table="role"
 * @aegis.mapping
 */
public class Role extends BaseObject implements Serializable, GrantedAuthority {
[...]
     * @aegis.property ignore="true"                                   
     */
    public Set getUsers() {
        return users;
    }
[...]

Depending on your specific usage of the webservice you design, you can ignore further properties, but I leave that to you in this example.

Open build.xml and add the following target definition (I personally put it directly before the compile-web target):

	  <target name="gen-aegis-mapping" depends="prepare"
	       description="Generates Aegis Mapping XML descriptors from POJOs">
	       <taskdef name="xdoclet" classname="xdoclet.DocletTask"
	           classpathref="xdoclet.classpath"/>

	       <xdoclet excludedtags="@version,@author"
	           addedtags="@xdoclet-generated at ${TODAY}"
	           force="${xdoclet.force}"
	           destdir="${build.dir}/service/classes"
	           mergedir="metadata/webservice">
	           <fileset dir="src/service" includes="**/*.java"/>

	           <template templateFile="metadata/templates/aegis-mapping.xdt"
	                     acceptAbstractClasses="false"
	                     prefixWithPackageStructure="true"
	                     destinationFile="{0}.aegis.xml"
	                     havingClassTag="aegis.mapping"/>
	       </xdoclet>
	  	
	       <xdoclet excludedtags="@version,@author"
	           addedtags="@xdoclet-generated at ${TODAY}"
	           force="${xdoclet.force}"
	           destdir="${build.dir}/dao/classes"
	           mergedir="metadata/webservice">
	           <fileset dir="src/dao" includes="**/*.java"/>

	           <template templateFile="metadata/templates/aegis-mapping.xdt"
	                     acceptAbstractClasses="false"
	                     prefixWithPackageStructure="true"
	                     destinationFile="{0}.aegis.xml"
	                     havingClassTag="aegis.mapping"/>
	       </xdoclet>
	   </target>

Expose a Manager as a webservice [#6]

Now you've got everything together that's necessary to see it running. Do an ant gen-aegis-mapping deploy and open the url "services/UserService?wsdl" of your application in your browser. You should see a xfire generated wsdl webservice definition:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions 
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:ns1="http://model.appfuse.org" 
    xmlns:ns3="http://dao.appfuse.org" 
    xmlns:soap11="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:soap12="http://www.w3.org/2003/05/soap-envelope" 
    xmlns:soapenc11="http://schemas.xmlsoap.org/soap/encoding/"
    xmlns:soapenc12="http://www.w3.org/2003/05/soap-encoding" 
    xmlns:tns="http://service.appfuse.org" 
    xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    targetNamespace="http://service.appfuse.org">
  <wsdl:types xmlns:ns2="http://acegisecurity.org">
    <xsd:schema targetNamespace="http://model.appfuse.org" elementFormDefault="qualified" attributeFormDefault="qualified">
      <xsd:complexType name="User">
        <xsd:sequence>
          <xsd:element name="accountExpired" type="xsd:boolean" minOccurs="0" />
          <xsd:element name="accountLocked" type="xsd:boolean" minOccurs="0" />
          <xsd:element name="accountNonExpired" type="xsd:boolean" minOccurs="0" />
          <xsd:element name="accountNonLocked" type="xsd:boolean" minOccurs="0" />

          <xsd:element name="address" type="ns1:Address" minOccurs="0" nillable="true" />
          <xsd:element name="authorities" type="ns2:ArrayOfGrantedAuthority" minOccurs="0" nillable="true" />
          <xsd:element name="confirmPassword" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="credentialsExpired" type="xsd:boolean" minOccurs="0" />
          <xsd:element name="credentialsNonExpired" type="xsd:boolean" minOccurs="0" />
          <xsd:element name="email" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="enabled" type="xsd:boolean" minOccurs="0" />
          <xsd:element name="firstName" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="lastName" type="xsd:string" minOccurs="0" nillable="true" />

          <xsd:element name="password" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="passwordHint" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="phoneNumber" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="roles" type="ns1:ArrayOfRole" minOccurs="0" nillable="true" />
          <xsd:element name="username" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="version" type="xsd:int" minOccurs="0" nillable="true" />
          <xsd:element name="website" type="xsd:string" minOccurs="0" nillable="true" />
        </xsd:sequence>
      </xsd:complexType>

      <xsd:complexType name="ArrayOfRole">
        <xsd:sequence>
          <xsd:element name="Role" type="ns1:Role" nillable="true" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="Role">
        <xsd:sequence>
          <xsd:element name="authority" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="description" type="xsd:string" minOccurs="0" nillable="true" />

          <xsd:element name="name" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="version" type="xsd:int" minOccurs="0" nillable="true" />
        </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="Address">
        <xsd:sequence>
          <xsd:element name="address" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="city" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="country" type="xsd:string" minOccurs="0" nillable="true" />

          <xsd:element name="postalCode" type="xsd:string" minOccurs="0" nillable="true" />
          <xsd:element name="province" type="xsd:string" minOccurs="0" nillable="true" />
        </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="ArrayOfUser">
        <xsd:sequence>
          <xsd:element name="User" type="ns1:User" nillable="true" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
      </xsd:complexType>

    </xsd:schema>
    <xsd:schema targetNamespace="http://acegisecurity.org" elementFormDefault="qualified" attributeFormDefault="qualified">
      <xsd:complexType name="ArrayOfGrantedAuthority">
        <xsd:sequence>
          <xsd:element name="GrantedAuthority" type="ns2:GrantedAuthority" nillable="true" minOccurs="0" maxOccurs="unbounded" />
        </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="GrantedAuthority">
        <xsd:sequence>

          <xsd:element name="authority" type="xsd:string" minOccurs="0" nillable="true" />
        </xsd:sequence>
      </xsd:complexType>
    </xsd:schema>
    <xsd:schema targetNamespace="http://service.appfuse.org" elementFormDefault="qualified" attributeFormDefault="qualified">
      <xsd:element name="getUsers">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="in0" type="ns1:User" nillable="true" minOccurs="1" maxOccurs="1" />

          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="getUsersResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="out" type="ns1:ArrayOfUser" nillable="true" minOccurs="1" maxOccurs="1" />
          </xsd:sequence>
        </xsd:complexType>

      </xsd:element>
      <xsd:element name="setUserDAO">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="in0" type="ns3:UserDAO" nillable="true" minOccurs="1" maxOccurs="1" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="setUserDAOResponse">

        <xsd:complexType />
      </xsd:element>
      <xsd:element name="getUser">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="in0" type="xsd:string" nillable="true" minOccurs="1" maxOccurs="1" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>

      <xsd:element name="getUserResponse">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="out" type="ns1:User" nillable="true" minOccurs="1" maxOccurs="1" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="saveUser">
        <xsd:complexType>

          <xsd:sequence>
            <xsd:element name="in0" type="ns1:User" nillable="true" minOccurs="1" maxOccurs="1" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="saveUserResponse">
        <xsd:complexType />
      </xsd:element>
      <xsd:complexType name="UserExistsException" />

      <xsd:element name="UserExistsException" type="tns:UserExistsException" />
      <xsd:element name="removeUser">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="in0" type="xsd:string" nillable="true" minOccurs="1" maxOccurs="1" />
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
      <xsd:element name="removeUserResponse">

        <xsd:complexType />
      </xsd:element>
    </xsd:schema>
    <xsd:schema targetNamespace="http://dao.appfuse.org" elementFormDefault="qualified" attributeFormDefault="qualified">
      <xsd:complexType name="UserDAO" />
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="getUserResponse">
    <wsdl:part element="tns:getUserResponse" name="parameters" />

  </wsdl:message>
  <wsdl:message name="getUsersRequest">
    <wsdl:part element="tns:getUsers" name="parameters" />
  </wsdl:message>
  <wsdl:message name="removeUserResponse">
    <wsdl:part element="tns:removeUserResponse" name="parameters" />
  </wsdl:message>
  <wsdl:message name="setUserDAOResponse">
    <wsdl:part element="tns:setUserDAOResponse" name="parameters" />

  </wsdl:message>
  <wsdl:message name="removeUserRequest">
    <wsdl:part element="tns:removeUser" name="parameters" />
  </wsdl:message>
  <wsdl:message name="saveUserRequest">
    <wsdl:part element="tns:saveUser" name="parameters" />
  </wsdl:message>
  <wsdl:message name="setUserDAORequest">
    <wsdl:part element="tns:setUserDAO" name="parameters" />

  </wsdl:message>
  <wsdl:message name="UserExistsException">
    <wsdl:part element="tns:UserExistsException" name="UserExistsException" />
  </wsdl:message>
  <wsdl:message name="getUsersResponse">
    <wsdl:part element="tns:getUsersResponse" name="parameters" />
  </wsdl:message>
  <wsdl:message name="saveUserResponse">
    <wsdl:part element="tns:saveUserResponse" name="parameters" />

  </wsdl:message>
  <wsdl:message name="getUserRequest">
    <wsdl:part element="tns:getUser" name="parameters" />
  </wsdl:message>
  <wsdl:portType name="UserManagerPortType">
    <wsdl:operation name="getUsers">
      <wsdl:input message="tns:getUsersRequest" name="getUsersRequest" />
      <wsdl:output message="tns:getUsersResponse" name="getUsersResponse" />
    </wsdl:operation>

    <wsdl:operation name="setUserDAO">
      <wsdl:input message="tns:setUserDAORequest" name="setUserDAORequest" />
      <wsdl:output message="tns:setUserDAOResponse" name="setUserDAOResponse" />
    </wsdl:operation>
    <wsdl:operation name="getUser">
      <wsdl:input message="tns:getUserRequest" name="getUserRequest" />
      <wsdl:output message="tns:getUserResponse" name="getUserResponse" />
    </wsdl:operation>
    <wsdl:operation name="saveUser">

      <wsdl:input message="tns:saveUserRequest" name="saveUserRequest" />
      <wsdl:output message="tns:saveUserResponse" name="saveUserResponse" />
      <wsdl:fault message="tns:UserExistsException" name="UserExistsException" />
    </wsdl:operation>
    <wsdl:operation name="removeUser">
      <wsdl:input message="tns:removeUserRequest" name="removeUserRequest" />
      <wsdl:output message="tns:removeUserResponse" name="removeUserResponse" />
    </wsdl:operation>
  </wsdl:portType>

  <wsdl:binding name="UserManagerHttpBinding" type="tns:UserManagerPortType">
    <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="getUsers">
      <wsdlsoap:operation soapAction="" />
      <wsdl:input name="getUsersRequest">
        <wsdlsoap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="getUsersResponse">
        <wsdlsoap:body use="literal" />

      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="setUserDAO">
      <wsdlsoap:operation soapAction="" />
      <wsdl:input name="setUserDAORequest">
        <wsdlsoap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="setUserDAOResponse">
        <wsdlsoap:body use="literal" />

      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="getUser">
      <wsdlsoap:operation soapAction="" />
      <wsdl:input name="getUserRequest">
        <wsdlsoap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="getUserResponse">
        <wsdlsoap:body use="literal" />

      </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="saveUser">
      <wsdlsoap:operation soapAction="" />
      <wsdl:input name="saveUserRequest">
        <wsdlsoap:body use="literal" />
      </wsdl:input>
      <wsdl:output name="saveUserResponse">
        <wsdlsoap:body use="literal" />

      </wsdl:output>
      <wsdl:fault name="UserExistsException">
        <wsdlsoap:fault name="UserExistsException" use="literal" />
      </wsdl:fault>
    </wsdl:operation>
    <wsdl:operation name="removeUser">
      <wsdlsoap:operation soapAction="" />
      <wsdl:input name="removeUserRequest">
        <wsdlsoap:body use="literal" />

      </wsdl:input>
      <wsdl:output name="removeUserResponse">
        <wsdlsoap:body use="literal" />
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="UserManager">
    <wsdl:port binding="tns:UserManagerHttpBinding" name="UserManagerHttpPort">
      <wsdlsoap:address location="http://localhost:8080/appfuse-xfire/services/UserService" />

    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

The next part of this howto deals with unit-testing of your webservices. You can do that on various levels of the xfire-stack.
The third part is about client-generation and will follow (hopefully) soon.
So stay tuned!



Go to top   More info...   Attach file...
This particular version was published on 06-Nov-2006 13:52:53 MST by MikaGoeckel.