com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links' is unknown.

Developing JAX-RS Applications

JAX-RS is an annotation-driven Java API that can be used for exposing Java beans as HTTP based services. For example, RESTful web applications are developed using JAX-RS annotations to define the resources exposed by the service. Web applications developed using JAX-RS annotations consist of the following qualities:

  • Use of HTTP/S transport protocols for message transfer.
  • The content that is transported by a JAX-RS web service can be in any format, e.g., XML, JSON, TEXT etc.
  • Security can be enabled for a JAX-RS web application either at the HTTP Header level, or by using TLS protocol.

Use WSO2 Developer Studio to easily develop your JAX-WS/JAX-RS Application. It will generate the needed Web application structure and you only have to concentrate on annotations and the business logic.

See the following topics for information on JAX-RS applications in WSO2 AS:

Working with JAX-RS annotations

JAX-RS annotations are defined in JSR 311. They are also a way of mapping Java with HTTP requests. For example, @GET, @PUT, @POST, @DELETE and @HEAD are JAX-RS annotations that directly map to HTTP requests by the same name. See the official Java documentation, for details about JAX-RS annotations and RESTful web services.

Shown below is an example of a simple web application that uses the following JAX-RS annotations: @Path, @GET, @Consumes and @Produces.

@Path("/hello")
public class HelloWorldService {  
@GET    
	@Consumes("text/plain")    
	@Produces("text/xml")
	@Path("/{user}") public String hello(@PathParam("user") String user) {   }
}

In this example, the @GET annotation is used to specify how the web application should respond to HTTP GET requests coming from a client. The @Consumes annotation determines the media type that the web service can accept from the client and the @Produces annotation determines the media type that the web service can return to the client in response to the request.

Configuring JAX-RS applications for AS

The following sections explain some of the configuration options that are available for JAX-RS applications:


Securing JAX-RS applications

When you define JAX-RS applications, you can enable authentication and authorization for your application based on the users and roles that are defined in the AS user store. This is done by using the @RolesAllowed annotation in your web service to map user roles that are already defined in the user store.

The following steps demonstrate how a JAX-RS application is secured by filtering the users that can access the service:

  1. For authentication, you should first enable the basic-auth security constraint in the web.xml file of your web application. In AS, web applications are authenticated against the Carbon user stores. The Working with Users, Roles and Permissions section explains how user stores are set up and configured. By default, WSO2 Carbon products come with a default JDBC-based user store, and do not use tomcat-users.xml (which comes by default with Apache Tomcat). This allows the web application to be authenticated against user stores such as LDAP, ActiveDirectory etc. So, when you set BASIC auth as a security-constraint via web.xml, the users will be authenticated against the users and roles set in a Carbon user store. See the following example:

    <security-constraint>  
     <web-resource-collection>      
    	<web-resource-name>CXF Jax-RS security</web-resource-name>            
    	<url-pattern>/services/*</url-pattern>  
     </web-resource-collection>  
     <auth-constraint>      
        <role-name>admin</role-name>      
        <role-name>newrole</role-name>  
     </auth-constraint>
    </security-constraint>
  2. You must add a cxf interceptor in the cxf-servlet.xml file. The roles you set using the @RolesAllowed annotation is authorized by CXF using the request interceptor, org.apache.cxf.interceptor.security.SecureAnnotationsInterceptor. CXF receives the underlying container’s SecurityContext for this task. Since we have set the Carbon user store as the default user realm, CXF will use that. See the following example:

    <!-- The SecureAnnotationsInterceptor honors the @RolesAllowed, @PermitAll and @DenyAll annotations -->  
    
    <bean id="authorizationInterceptor"        class="org.apache.cxf.interceptor.security.SecureAnnotationsInterceptor">     
    <property name="securedObject" ref="serviceBean"/>  
    </bean>
    <jaxrs:server id="customerService" address="/customers">
    
    <!-- set the interceptor for the jaxrs:server for in-bound messages to authorize the user -->
          
    <jaxrs:inInterceptors>          
        <ref bean="authorizationInterceptor"/>      
        </jaxrs:inInterceptors>
      
    <jaxrs:serviceBeans>          
        <ref bean="serviceBean"/>      
    </jaxrs:serviceBeans>
  3. Then, you can go ahead and add the relevant annotation to the needed resource methods in your JAX-RS resource class. See the following examples:

    • @RolesAllowed annotation: The required roles for authentication and authorization should be specified for the application. In the example given below, only the users with the “admin” role will be able to access the resource method, "getCustomer".

      @GET 
        @RolesAllowed("admin")  
        @Produces("application/xml")  
        @Path("/customers/{id}/")  
      public Customer getCustomer(@PathParam("id") String id) 
      {         System.out.println("----invoking getCustomer, Customer id is: " + id);long idNumber = Long.parseLong(id);Customer c = customers.get(idNumber); return c;}
    • @DenyAll annotation: Block all users in the user store from accessing the service.

      @DenyAll
          @Path("/orders/{orderId}/")
          public Order getOrder(@PathParam("orderId") String orderId) {
              System.out.println("----invoking getOrder, Order id is: " + orderId);
              long idNumber = Long.parseLong(orderId);
              Order c = orders.get(idNumber);
              return c;
          }
    • @PermitAll annotation: Allows all users in the user store to access the service.

      @PermitAll
          @Path("/orders/{orderId}/")
          public Order getOrder(@PathParam("orderId") String orderId) {
              System.out.println("----invoking getOrder, Order id is: " + orderId);
              long idNumber = Long.parseLong(orderId);
              Order c = orders.get(idNumber);
              return c;
          }
  4. The annotations such as @RolesAllowed comes from the jsr250-api Common Annotations library. This is not shipped with WSO2 AS by default. So, you need to either include this library in your web application, or directly copy it to the AS. Since this is for a CXF JAX-RS application, you may copy this library to <AS_HOME>/lib/runtimes/cxf/ folder. The Maven dependency information for jsr250-api library is as follows:

    <dependency>
     <groupId>javax.annotation</groupId>
     <artifactId>jsr250-api</artifactId>
     <version>1.0</version>
    </dependency>

Shown below is a sample security configuration (web.xml file and cxf-servlet.xml file) for a JAX-RS service.

 Sample web.xml file:
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>JAX-WS/JAX-RS Webapp</display-name>
    <servlet>
        <servlet-name>JAXServlet</servlet-name>
        <display-name>JAX-WS/JAX-RS Servlet</display-name>
        <description>JAX-WS/JAX-RS Endpoint</description>
        <servlet-class>
            org.apache.cxf.transport.servlet.CXFServlet
        </servlet-class>
        <init-param>
            <param-name>service-list-stylesheet</param-name>
            <param-value>servicelist.css</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>JAXServlet</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>60</session-timeout>
    </session-config>
<security-constraint>
    <web-resource-collection>
        <web-resource-name>CXF Jax-RS security</web-resource-name>
        <url-pattern>/services/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>admin</role-name>
        <role-name>newrole</role-name>
    </auth-constraint>
</security-constraint>
<login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>default</realm-name>
</login-config> 
</web-app>
 Sample cxf-servlet.xml file:
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxrs="http://cxf.apache.org/jaxrs"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
         http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
    <bean id="serviceBean" class="demo.jaxrs.server.CustomerService"/>
    <!-- The SecureAnnotationsInterceptor honors the @RolesAllowed, @PermitAll and @DenyAll annotations -->
    <bean id="authorizationInterceptor"
          class="org.apache.cxf.interceptor.security.SecureAnnotationsInterceptor">
        <property name="securedObject" ref="serviceBean"/>
    </bean>
    <jaxrs:server id="customerService" address="/customers">
        <!-- set the interceptor for the jaxrs:server for in-bound messages to authorize the user -->
        <jaxrs:inInterceptors>
            <ref bean="authorizationInterceptor"/>
        </jaxrs:inInterceptors>
        <jaxrs:serviceBeans>
            <ref bean="serviceBean"/>
        </jaxrs:serviceBeans>
    </jaxrs:server>
</beans>

Other configuration options

  • If you want to enable SaaS mode or CORS for your web applications see Configuring Applications for AS
  • If you want to use more advanced configurations for your web application, such as enabling Single Sign On (SSO), enabling fine grained authorization using XACML, see the topics listed under Working with Applications.

Building JAX-RS applications for AS

JAX-WS and JAX-RS applications can be bundled in a CXF application. Given below is the general folder structure of a CXF application. However, this can change depending on your application.

Please see the instructions on class loading for web applications, which explains how you can add the webapp-classloading.xml file to your web app. This XML is a custom file implemented by WSO2 to give flexibility in classloading. You must have this file in order to deploy JAX-WS and JAX-RS applications, because the CXF runtime is not visible to the webapps by default.

HellowService.war
    WEB-INF/
        web.xml
        cxf-servlet.xml
        wsdl
        lib/
        classes/
    META-INF/
        webapp-classloading.xml
com.atlassian.confluence.content.render.xhtml.migration.exceptions.UnknownMacroMigrationException: The macro 'next_previous_links2' is unknown.