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

Developing JAX-RS Services

JAX-RS is an annotation-driven Java API that can be used for exposing Java beans as HTTP based services. For example, RESTful web services are developed using JAX-RS annotations to define the resources exposed by the service.  Web services 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 service either at the HTTP Header level, or by using TLS protocol.

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

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 more details about JAX-RS annotations.

Shown below is an example of a simple web service 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 service 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.

Securing JAX-RS services

When you define JAX-RS services, you can enable authentication and authorization for your service 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 the @RollesAllowed annotation is used in a sample web 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. 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 the 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>

    To authorize the users based on the @RolesAllowed annotation, you must add a cxf interceptor in the cxf-servlet.xml file. The roles you set in @RolesAllowed 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>
  2. Then, you can go ahead and add the @RolesAllowed annotation to the needed resource methods in your JAX-RS resource class. The required roles for authentication and authorization should be specified for the service as shown below.

    @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;}

    In the above example, only the users with the “admin” role will be able to access the resource method, "getCustomer". The role will be checked against the Carbon user-stores defined in AS. See the User Management section for information on how user stores are set up and configured.

  3. 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 service, 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>

Enabling CORS for JAX-RS

If required, you can enable CORS (cross origin resource sharing) for JAX-RS applications by adding the CORS filter to the web.xml file as shown in the following example. 

<filter>
    <filter-name>CorsFilter</filter-name>
    <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
    <init-param>
        <param-name>cors.allowed.origins</param-name>
        <param-value>*</param-value>
    </init-param>
    <init-param>
        <param-name>cors.allowed.methods</param-name>
        <param-value>GET,POST,HEAD,OPTIONS,PUT,DELETE,PATCH</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>CorsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

The parameters used in this example are as follows:  

  • The cors.allowed.origins parameter is used to specify the web domains that should be allowed to share resources with the JAX-RS application. The domain names should be specified as parameter values. If the parameter value is set to '*' as shown above, or if this parameter is not used at all, resource sharing will be allowed for all origins (all web domains). 
  • The cors.allowed.methods parameter is used to specify the type of requests for which CORS should be enabled. You can list the allowed methods as parameter values.

Developing RESTful service using JAX-RS

See how you can easily develop a RESTful web application using JAX-RS annotations in WSO2 Developer Studio. Once the web service is created, you can deploy it in WSO2 Application Server using the management console. Also, see the official Java documentation, for details about JAX-RS annotations and RESTful web services.

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