XFireHome M5M6-SNAPSHOTDevelopersDeveloper Space |
Example of Exposing a POJO Service that uses XMLBeans as parameters and return value using XFireXFire 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 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 XMLBeansSample 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 filesApplicationContext.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 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. |