Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
ch_loos
Advisor
Advisor

Modern client-side web frameworks and libraries like SAPUI5 are using REST services to load data from a server. If you want to consume existing business logic from these new web applications, you first need to make them REST-enabled.

For standard SAP applications, you can use SAP NetWeaver Gateway. But what about your own composite services built e.g. using the Composite Application Framework (CAF)?

In this blog, we will use the Apache Jersey library to expose a CAF Business Object as a RESTful web service.

Deploying Jersey

For a description on how to package and deploy the Jersey libraries to the SAP NetWeaver Application Server, please refer to this excellent blog by werner.steyn.

It is recommended to wrap the External Library into its own Enterprise Application, and have it packaged in a separate Software Component so that it can be reused from multiple applications.

Don’t forget to remove the access restrictions to the DCs and its public parts, in order to make it available to other applications.

Creating a web module DC

The Jersey servlet needs a web.xml to be configured and deployed. Create a new web module DC in the software component which holds your CAF project.

Add a DC dependency from the CAF EAR DC to the new web DC so that it is included with the CAF application.

Enabling access to the CAF project

Since you want to reuse the existing CAF service, you need to be able to reference it from your new web module DC.

In the component properties of the CAF EAR DC, switch to the “Public Parts” tab, select the “client” public part and add permission for your web DC. Repeat this for all other public parts.

Next, switch to the “Permissions” tab and again add permission for the web DC.

Setting DC dependencies

Now, switch to the component properties of your web DC and add the following DC dependencies:

  • caf/core/ear
  • caf/runtime/ear
  • jersey/ear (from the Software Component which contains the Jersey libraries)
  • tc/bl/exception/lib

You can test if everything works by building the CAF application. If the build is failing, check the build log for error messages.

Implementing the resource class

Now it’s time to actually implement the REST service. All you need is a plain Java class with some annotations. The JNDI name to look up the CAF EJB can be retrieved via the JNDI Browser in NWA.

The GET method simply all employees stored in the respective CAF table. Since Jersey supports POJOs, we can return the Employee object as-is and don’t need to create any wrapper objects.

package com.sap.demo.cafrest.employee;
import java.util.List;
import javax.naming.InitialContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import com.sap.demo.employee.modeled.Employee;
import com.sap.demo.employee.modeled.bonode.employee.employee.EmployeeServiceLocal;
@Path("/employees")
public class EmployeeResource {
      EmployeeServiceLocal employeeService;
      final String JNDI_NAME = "demo.sap.com/employee~ear/LOCAL/com.sap.demo.employee.modeled.bonode.employee.employee.Employee/com.sap.demo.employee.modeled.bonode.employee.employee.EmployeeServiceLocal";
      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public List<Employee> getAllEmployees() {
            try {
                  InitialContext jndiContext = new javax.naming.InitialContext();
                  employeeService = (EmployeeServiceLocal) jndiContext.lookup(JNDI_NAME);
                  List<Employee> result = employeeService.findAll();
                  return result;
            } catch (Exception e) {
                  throw new RuntimeException(e);
            }
      }
}

In the code sample above, we only implement the method to get all objects. You can easily implement all CRUD and finder methods in a similar way using the respective annotations for GET, PUT, POST and DELETE. Check the Jersey documentation for more details.

This example uses a CAF business object service, but the same approach also works for application services.

Configuring the Jersey servlet

Finally, we need to configure the servlet container for Jersey. Open the web.xml of your web DC and add the following lines:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
      id="WebApp_ID" version="2.5">
      <display-name>CAF REST demo</display-name>
      <servlet>
            <servlet-name>Jersey REST Service</servlet-name>
            <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
            <init-param>
                  <param-name>com.sun.jersey.config.property.packages</param-name>
                  <param-value>org.codehaus.jackson.jaxrs;com.sap.demo.employee.modeled;com.sap.demo.cafrest.employee</param-value>
            </init-param>
            <init-param>
                  <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
                  <param-value>true</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
            <servlet-name>Jersey REST Service</servlet-name>
            <url-pattern>/rest/*</url-pattern>
      </servlet-mapping>
</web-app>

Via the parameter com.sun.jersey.api.json.POJOMappingFeature, we tell Jersey to use POJO mapping instead of JAXB annotations.

In the value for com.sun.jersey.config.property.packages, you need to add all Java packages containing the POJOs used in your CAF services. Otherwise the POJO to JSON mapping will not work.

Testing the service

Deploy the whole CAF application to the server. After deployment, you should be able to call the service from your browser:

If you get an error message, check the dev traces in the NWA Log Viewer.

Summary

Exposing a CAF service via REST requires only a few lines of code. The trickiest part is to make sure you have set all the right permissions and dependencies between the various DCs.

5 Comments