Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

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

  1. Expose your Manager as a Web Service
    1. SOAP
    2. REST
  2. Securing your Web Service
Info
titleSource 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:

No Format
svn checkout http://appfuse-demos.googlecode.com/svn/trunk/tutorial-service

Expose your Manager as a Web Service
Anchor
managerws

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
Anchor
soap

To expose your PersonManager (and its implementation) as a SOAP service, add a @WebService annotation to the interface.

Code Block
languagejava
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
languagejava
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
languagexml
<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
Anchor
rest

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
languagejava
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
languagejava
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
languagexml
<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
Anchor
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.