About this Tutorial
This tutorial exposes your Manager classes (or any other classes) as a web service with XFire. It assumes you completed the Services tutorial and wrote a custom PersonManager class and PersonManagerImpl implementation.
| Upgrading to CXF We are aware that Apache CXF is the next generation of XFire. However, we've also optimized the XFire footprint to be as small as possible. Part of this optimization was removing JAXB 2 support and using XMLBeans instead. The XFire Migrating Guide says that XMLBeans will be supported in CXF 2.1. We plan on upgrading at that time. Of course, if you get a hankering to upgrade AppFuse before then - please do. We love contributions. |
Table of Contents
| Source Code The code for this tutorial is located in the "tutorial-service" module of the appfuse-demos project on Google Code. Use the following command to check it out from Subversion: svn checkout http://appfuse-demos.googlecode.com/svn/trunk/tutorial-service |
Expose your Manager as a Web Service
Thanks to annotations, it's very easy to expose your existing classes as web services. In fact, there's a UserService that's already exposed in your AppFuse application at http://localhost:8080/services/UserService. To see the WSDL, go to http://localhost:8080/services/UserService?wsdl. All web services can be viewed at http://localhost:8080/services.
| If the /services page is empty, make sure there is no default-lazy-init="true" at the top of your xfire-servlet.xml. If you don't have an xfire-servlet.xml in your project, copy it from target/yourapp-version/WEB-INF to your src/main/webapp/WEB-INF directory. |
To expose your PersonManager (and its implementation) as a web service, add a @WebService annotation to the interface.
package org.appfuse.tutorial.service; import org.appfuse.service.GenericManager; import org.appfuse.tutorial.model.Person; import javax.jws.WebService; import java.util.List; @WebService public interface PersonManager extends GenericManager<Person, Long> { public List<Person> findByLastName(String lastName); }
Then add the same annotation to your PersonManagerImpl, specifying the service name and endpointInterface:
package org.appfuse.tutorial.service.impl; import org.appfuse.tutorial.dao.PersonDao; import org.appfuse.tutorial.model.Person; import org.appfuse.tutorial.service.PersonManager; import org.appfuse.service.impl.GenericManagerImpl; import javax.jws.WebService; import java.util.List; @WebService(serviceName = "PersonService", endpointInterface = "org.appfuse.tutorial.service.PersonManager") public class PersonManagerImpl extends GenericManagerImpl<Person, Long> implements PersonManager { PersonDao personDao; public PersonManagerImpl(PersonDao personDao) { super(personDao); this.personDao = personDao; } public List<Person> findByLastName(String lastName) { return personDao.findByLastName(lastName); } }
After making these changes, you should be able to run mvn jetty:run-war and view the WSDL for your PersonManager at http://localhost:8080/services/PersonService?wsdl.
| If the above URL doesn't result in an XML document being displayed in your browser, it's likely because you didn't register PersonManagerImpl in your Spring context file (applicationContext.xml). AppFuse uses the setup described in XFire's documentation. |
To continue creating your web application, please see the web tutorials.
Security
Web Services in AppFuse are unsecure by default. To secure them, the easiest thing to do is add /services/**=ROLE_NAME to your WEB-INF/security.xml file. You may have to copy target/yourapp-version/WEB-INF/security.xml to your src/main/webapp/WEB-INF directory.
Limit exposed methods
When you add the annotations to your service classes, by default all public methods are exposed as web services. This might not be ideal. If you would like to limit the methods that are exposed, then do the following.
i. Remove the @WebService from the service interface class (i.e PersonManager)
ii. Remove the endpoint attribute in the service implementation class (i.e PersonManagerImpl) so that it now look like this
@WebService(serviceName = "PersonService")
iii. Add @WebMethod(exclude=true) for each public method in the implemented class (i.e PersonManagerImpl) that you would not like exposed as a web service. This includes methods defined in parent classes as well (i.e GenericManagerImpl)
iv. Add @WebMethod on each public method that you would like to expose as a webservice.
To authenticate on the client side, see Using Acegi With XFire For Web Service Authentication & Authorization.