RESTFul Web Services

Well-designed distributed applications typically contain several service layers. At the lowest level, local services are built using object-oriented principles and collocated in the same VM. At the next level, services are distributed but are deployed on the same middleware infrastructure and managed in common. Finally, an application may expose a limited number of services that must be accessible to external clients, for example, systems not deployed on the same middleware infrastructure.

When using Fabric3, it is generally recommended to use messaging middleware to connect distributed SCA components (the second level mentioned above). However, when creating endpoints for services that must be accessible to external clients in a vey loosely coupled manner, RESTful web services are the recommended approach. While Fabric3 also supports "traditional" WS-* web services with binding.ws, RESTful web services tend to be significantly simpler, flexible and more interoperable in practice than WS-*.   

RESTful web services are created in Fabric3 using JAX-RS and bound to an endpoint using binding.rs. The following section details how this is done.

The Starter Applications and Feature Applications contain a number of examples of how to use JAX-RS 2.0 with Fabric3.

Using JAX-RS to Create Restful Web Services

The JAX-RS binding provides support for exposing SCA services as RESTful resources using JAX-RS 2.0. The binding supports both JAXB and JSON (via the Jackson JSON parser). 

Exposing an SCA service as a RESTFul endpoint is straightforward – simply use JAX-RS annotations and configure the service with <binding.rs> in a composite. As a convenience, JAX-RS annotations can be used directly on a component implementation class without the need for a service interface:

@EndpointUri("messages")
@Path("/")
@Component
@Consumes({MediaType.APPLICATION_JSON})
@Produces({MediaType.APPLICATION_JSON})
@Scope("COMPOSITE")
public class MessageService {

   @PUT
   @Path("message")
   public Response create(Message message) {
      // ...
   }

   @GET
   @Path("message/{id}")
   public Message retrieve(@PathParam("id") Long id) {
      // ...
   }

   @DELETE
   @Path("message/{id}")
   public Response delete(@PathParam("id") Long id) {
      // ...
   }
}

The EndpointUri annotation is used to specify the endpoint path to the base container address for a particular transport/protocol. In this case, the transport is HTTP, so the full endpoint address will be <server><port>/messages

The above component can alternatively be configured in a composite as follows:

<composite xmlns:f3="urn:fabric3.org" ...>

   <component name="MessageService">
      <implementation.java class="org.fabric3.tests.rs.MessageService"/>
      <service name="MessageService">
         <f3:binding.rs uri="/messages"/>
      </service>
   </component>
</composite>

The binding configuration will expose the MessageService resource at <server><port>/messages.

To consume and produce both XML and JSON, the JAX-RS Consumes and Produces annotations are used:

@Path("/")
@Consumes({MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
@Produces(MediaType.APPLICATION_XML,MediaType.APPLICATION_JSON})
@Scope("COMPOSITE")
public class MessageService {
   //....
}

Further examples are provided in the Fabric3 Samples.

Using JAX-RS Providers

Fabric3 supports JAX-RS filter providers. The runtime will recognize JAX-RS Provider annotations and create a component from the class. This allows filters to be injected with other services as demonstrated below: 

@Provider
@RequireAdmin
@Priority(Priorities.AUTHENTICATION)
@Scope("COMPOSITE")
public class AdminAuthenticationFilter implements ContainerRequestFilter {
    @Reference
    protected AuthenticationService authenticationService;

    public void filter(ContainerRequestContext requestContext) throws IOException {
        // ...
    }
}

Provider components should generally be COMPOSITE scope (i.e. multi-threaded).

Exposing Spring Beans as RESTful Resources

Spring beans can also be exposed as RESTful resources using JAX-RS annotations on a bean implementation and the binding.rs element. In this case, the MessageService implementation remains exactly the same as in the above example. The Spring application context is configured as follows:

<beans xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200912"...>
   <sca:service name="MessageService" target="MessageService"/>
   <bean id="MessageService" class="org.fabric3.samples.hibernate.MessageService"/>
</beans>

The MessageService is configured in the composite as follows:

<composite ...>
   <component name="MessageService">
      <implementation.spring location="..."/>
      <service name="MessageService">*
         <f3:binding.rs uri="/messages"/>*
      </service>*
   </component>
</composite>

Further examples are provided in the Fabric3 Spring Samples.

Securing Resources

The JAX-RS binding supports HTTP Basic Authentication using the 'clientAuthentication' intent. To enable authentication on a service, add the following to the binding:

<composite ...>
   <component name="MessageService">
      <implementation.spring location="..."/>
      <service name="MessageService">
         <f3:binding.rs uri="/messages" requires="clientAuthentication"/>
      </service>*
   </component>
</composite>

Enabling JAX-RS

JAX-RS support is enabled by installing the rs profile in any of the Fabric3 runtimes.