About this Tutorial
This tutorial exposes your Manager classes (or any other classes) as a web service with CXF, a proven Open-Source Services Framework. It assumes you completed the Services tutorial and wrote a custom PersonManager class and PersonManagerImpl implementation.
Table of Contents
- Expose your Manager as a Web Service
- SOAP
- REST
- Securing your Web Service
| Info |
|---|
|
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: | No Format |
|---|
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 are a couple of services that are already exposed in your AppFuse application. For the SOAP-based UserService, you can see the WSDL by running mvn jetty:run and navigating to http://localhost:8080/services/UserService?wsdl. You can view the REST equivalent (a WADL file) at http://localhost:8080/services/api?_wadl&_type=xml. All web services can be viewed at http://localhost:8080/services/.
Exposing a SOAP Service
To expose your PersonManager (and its implementation) as a SOAP service, add a @WebService annotation to the interface.
| Code Block |
|---|
|
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. You'll also need to add a public, no-args constructor to satisfy JAX-WS.
| Code Block |
|---|
|
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;
@Service("personManager")
@WebService(serviceName = "PersonService", endpointInterface = "org.appfuse.tutorial.service.PersonManager")
public class PersonManagerImpl extends GenericManagerImpl<Person, Long> implements PersonManager {
PersonDao personDao;
public PersonManagerImpl() {};
public PersonManagerImpl(PersonDao personDao) {
super(personDao);
this.personDao = personDao;
}
public List<Person> findByLastName(String lastName) {
return personDao.findByLastName(lastName);
}
}
|
Open your src/main/webapp/WEB-INF/cxf-servlet.xml file and add the following declaration to tell CXF about your web service endpoint:
| Code Block |
|---|
|
<jaxws:endpoint id="personService" implementor="#personManager" address="/PersonService"/>
|
After making these changes, you should be able to run mvn jetty:run and view the WSDL for your PersonManager at http://localhost:8080/services/PersonService?wsdl.
To continue creating your web application, please see the web tutorials.
Exposing a REST Service
To expose your PersonManager (and its implementation) as a REST service, add a @PATH annotation to the interface and annotations to the method to indicate its path and supported methods. NOTE: This example includes the aforementioned @WebService annotation because it's perfectly acceptable to use both in the same files.
| Code Block |
|---|
|
package org.appfuse.tutorial.service;
import org.appfuse.service.GenericManager;
import org.appfuse.tutorial.model.Person;
import javax.jws.WebService;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import java.util.List;
@WebService
@Path("/")
public interface PersonManager extends GenericManager<Person, Long> {
@Path("/person/{lastname}")
@GET
List<Person> findByLastName(@PathParam("lastname") String lastName);
@Path("/people")
@GET
List<Person> getPeople();
}
|
With JAX-RS, you don't need any additional annotations on your implementation. However, you'll still need to add the implementation of the getPeople() method and to tell CXF about it.
Add the the getPeople() method's implementation to your PersonManagerImpl.
| Code Block |
|---|
|
public List<Person> getPeople() {
return personDao.getAll();
}
|
Next, open your src/main/webapp/WEB-INF/cxf-servlet.xml file and add the following XML in the <jaxrs:serviceBeans> section:
| Code Block |
|---|
|
<ref bean="personManager"/>
|
After making these changes, you should be able to run mvn jetty:run and view all the people in your database at http://localhost:8080/services/api/people.
| Note |
|---|
If you have trouble getting this to work, please subscribe to the mailing list and send us the issue you're experiencing. |
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. For more information, see Enunciate's tutorial on Securing Web Services
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.