XFire

Home
Bug/Issue Reporting
Download
FAQ
Get Involved
License
News
Stack Comparison
Support
User's Guide
XFire Team

M5

Javadocs
Reports

M6-SNAPSHOT

Javadocs
Reports

Developers

Developer Space
CVS
Building
Architecture
Interesting Projects
Release Process

Example of Exposing a POJO Service that uses XMLBeans as parameters and return value using XFire

XFire is capable of exposing Document-Style services that use XMLBeans.

For example, let's suppose you have XMLBeans that you generated from a Schema:

PriceCheckRequestDocument - corresponding to an instance of PriceCheckRequest from a PreOrderManagement Schema (e.g. preorderschema.xsd) and
PriceCheckResponseDocument - corresponding to an instance of a PriceCheckResponse from the same schema.

This is quite typical in business-to-business sharing where companies may use different systems, but would like to standardize on common messaging – similar to the way EDI was used.

You might have created a service as follows:

PriceCheckService.java
public interface PriceCheckService
{
    /**
     * @param request - xmlBean corresponding to a PriceCheckRequestDocument
     * @return and xmlBean corresponding to a PriceCheckResponseDocument
     */
    PriceCheckResponseDocument checkPrice(PriceCheckRequestDocument request);
}

PriceCheckRequestDocument is an XML bean that was generated from a schema using the XMLBeans 2.0's XMLBean Task from ANT. A sample Target is show below. The sample assumes that you have ant properties setup for: {generated-source} - location your build directory, {generated-source}/xmlbeans - location where your xmlbeans generated source will be deposited, {xbeans.jar}- location and filename of where the xmlbeans jar file will be generated, and xsd is where your original schema files reside.

directory structure
/build.xml
/build
      /lib                       -- built libraries go here
          /myschema.jar          -- you'd set xbeans.jar to /build/lib/myschema.jar or equivalent
/xsd
    /<your schema files here>
/generated-source                -- location where generated source files will be placed
                 /xmlbeans       -- generated XML Beans source goes here
/lib                             -- xml beans stuff goes here
    /xmlbeans
             /...
    /xfire
          /...
    /spring
           /...
    /test
         /...
build.classpath
<!-- Build Classpath -->
	<path id="build.classpath">
		<pathelement location="${build}" />
		<fileset dir="${lib}">
			<include name="ant/*.jar" />
			<include name="*.jar" />
			<include name="xfire/*.jar" />
			<include name="spring/*.jar" />
			<include name="test/*.jar" />
		</fileset>
	</path>
Example Ant Target for generating XMLBeans
Sample ANT Target
<!-- Generate XMLBeans from Schema  (use verbose="true" to debug), refresh after build -->
	<target name="generate-xmlbean">
		<delete failonerror="false">
			<fileset dir="${generated-source}/xmlbeans">
				<include name="**/*.*" />
			</fileset>
		</delete>
		<xmlbean classgendir="${generated-source}/xmlbeans" verbose="false" destfile="${xbeans.jar}"
                      fork="true" javasource="1.4" srconly="no" classpathref="build.classpath" 
                       failonerror="true">
			<fileset dir="xsd" includes="**.*" />
		</xmlbean>
	</target>

After running this task, you should have an file called myschema.jar that contains a bunch of class files and binary schema files in it.

Now it's time to expose the service using XFire. I use Spring to handle configuration of everything. My PriceCheckService is exposed inside Spring. Since the Transaction Boundary is at the Service layer, I create a proxy using the TransactionProxyFactory.

Spring ApplicationContext files
ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
		"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <!-- Web Service -->
    <bean id="myPriceCheckService"
        name="com.paraware.webservice.PriceCheckService" class="com.paraware.webservice.PriceCheckServiceImpl">
        <property name="businessService">
            <ref bean="myBusinessService"/>
        </property>
    </bean>
</beans>
serviceContext.xml
<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
		"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean id="myBusinessService"
        name="com.paraware.service.BusinessService"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="transactionManager">
            <ref local="myTransactionManager"/>
        </property>
        <property name="target">
            <ref local="myBusinessServiceTarget"/>
        </property>
        <property name="transactionAttributes">
            <props>
                <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
            </props>
        </property>
    </bean>
    <bean id="myBusinessServiceTarget"
        class="com.paraware.service.BusinessServiceImpl"
        singleton="true" autowire="no">
        <property name="authenticationDao">
            <ref bean="myAuthenticationDao"/>
        </property>
        <property name="inventoryDao">
            <ref bean="myInventoryDao"/>
        </property>
    </bean>
    <bean id="myTransactionManager"
        name="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource">
            <ref bean="myDataSource"/>
        </property>
    </bean>
</beans>
daoContext.xml
<?xml version="1.0" encoding="UTF-8"?>
	<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
		"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
   <bean id="myDataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean" singleton="true">
        <property name="jndiName">
            <value>jdbc/PriceCheckDataSource</value>
        </property>
        <property name="resourceRef">
            <value>true</value>
        </property>
    </bean> 
    <bean id="myAuthenticationDao"
        name="com.paraware.dao.jdbc.AuthenticationDaoImpl"
        singleton="true" autowire="no"
        class="com.paraware.dao.jdbc.AuthenticationDaoImpl">
        <property name="dataSource">
            <ref bean="myDataSource"/>
        </property>
    </bean>
    <bean id="myInventoryDao"
        name="com.paraware.dao.jdbc.InventoryDaoImpl"
        singleton="true" autowire="no"
        class="com.paraware.dao.jdbc.InventoryDaoImpl">
        <property name="dataSource">
            <ref bean="myDataSource"/>
        </property>
    </bean>      
</beans>

Next, it's time to configure the xfire-servlet.xml file. This file is used by Spring to let the DispatchServlet know which controllers to work with. Spring will look for this file based on the name of the DispatcherServlet in the web.xml file. (i.e. xfire-servlet.xml)

xfire-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <bean
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="urlMap">
            <map>
                <!-- this is where this service will be exposed i.e. http://localhost/context/SoapCustomerService -->
                <entry key="/SoapCustomerService">
                    <ref bean="SoapCustomerService"/>
                </entry>
            </map>
        </property>
    </bean>
    <bean id="xfire.xmlbeansServiceFactory"
        class="org.codehaus.xfire.xmlbeans.XMLBeansServiceFactory"
        singleton="true">
        <property name="transportManager">
            <ref bean="xfire.transportManager"/>
        </property>
        <!-- make sure you specify this binding provider if you use setter injection, otherwise you'll get the aegis provider -->
        <property name="bindingProvider">
            <ref bean="xfire.xmlbeansBindingProvider"/>
        </property>
    </bean>
    <bean id="xfire.xmlbeansBindingProvider"
        class="org.codehaus.xfire.xmlbeans.XMLBeansBindingProvider"
        singleton="true"/>
    <!-- Declare a parent bean with all properties common to both services -->
    <bean id="SoapCustomerService"
        class="org.codehaus.xfire.spring.XFireExporter">
        <property name="serviceFactory">
            <ref bean="xfire.xmlbeansServiceFactory"/>
        </property>
        <property name="xfire">
            <ref bean="xfire"/>
        </property>
        <property name="style">
            <!-- this needs to be specified to have document style properly handled -->
            <value>document</value>
        </property>
        <property name="service">
            <!-- notice this is the service interface that was exposed in applicationContext.xml -->
            <ref bean="myPriceCheckService"/>
        </property>
        <property name="serviceInterface">
            <!-- notice this is the fully qualified service interface that was exposed in applicationContext.xml -->
            <value>com.paraware.webservice.PriceCheckService</value>
        </property>
    </bean>
    <bean id="wsdlConfigurer"
        class="com.paraware.xfire.XMLBeansWSDLBuilderConfigurer"
        init-method="init">
        <property name="transportManager">
            <ref bean="xfire.transportManager"/>
        </property>
        <property name="service">
            <value>SoapCustomerService</value>
        </property>
        <property name="serviceRegistry">
            <ref bean="xfire.serviceRegistry"/>
        </property>
        <property name="schemaLocations">
            <list>
                <!-- this is the schema used to create your xml beans.  multiple schemas can be listed -->
                <value>/WEB-INF/pre-order.xsd</value>
            </list>
        </property>
    </bean>
</beans>

Next, it's time to create the web.xml file. I'm using the ContextLoaderServlet but you can easily (and I would encourage this) use the ContextLoaderListener. I used the ContextLoaderServlet because I was working with a container that didn't support the ContextLoaderListener.

Things to Note
#I have several configuration files. My applicationContext.xml file includes configuration of my PriceCheckService. This service actually makes use of another service called business service that I use elsewhere and define in serviceContext.xml.
#serviceContext.xml includes configuration of the business service and transactionalProxy
#daoContext.xml includes the dao configurations and the datasource (this is set to use the resource configured in web-xml which will be configured by the container.
#finally classpath:org/codehaus/xfire/spring/xfire.xml is specified to ensure that XFire spring beans are loaded in the context
#a resource reference is specified and indicates that a resource will need to be configured by the container.

web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml
            /WEB-INF/serviceContext.xml
            /WEB-INF/daoContext.xml
            <!-- The XFire Spring Beans Configuration -->
            classpath:org/codehaus/xfire/spring/xfire.xml</param-value>
    </context-param>
    <servlet>
        <servlet-name>context</servlet-name>
        <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet>
        <servlet-name>xfire</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>xfire</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
    <resource-ref id="ResourceRef_1">
        <description> DataSource configured in container </description>
        <res-ref-name> jdbc/PriceCheckDataSource </res-ref-name>
        <res-type> javax.sql.DataSource </res-type>
        <res-auth> CONTAINER </res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>    
</web-app>

That's it. You should be able to fire up your app using this URL: http://localhost/context/SoapCustomerService?wsdl and see the WSDL that is generated for your service. Then you can send a PriceCheckRequestDocument into the service and get a PriceCheckResponseDocument back out.