René van Mil

Building a RESTful API With an SAP CE Backend

The SAP NetWeaver Composition Environment (SAP CE) is a Java EE 5 application server. Among a lot of other things, the environment provides several frameworks which allow you to develop webapplications with Java. Most commonly SAP CE servers are used to host Web Dynpro Java applications (from within an SAP Portal) which connect to an SAP ECC backend and local database using the CAF framework.

SAP launched this product around 2007 during the SOA hype, which means currently a lot of customers are still using the SAP CE application server for their custom webapplications built on top of their SAP (and other) systems. Unfortunately the frameworks provided by SAP CE heavily rely on SOAP, WSDL, UDDI, XML, etc. which currently is widely regarded as a failure and deprecated technology stack.

Because of this (and recent personal experience) I decided to write this post, explaining how you can use SAP CE to build a RESTful API, so you can use the server as a backend for modern webapplications (obviously not built with Web Dynpro ;)), or mobile apps.

Overview

The following technology will be used in this blog post:

  • CAF framework; used to connect to an SAP ECC backend through SAP RFC
  • Java EE Web Module: used to expose the CAF service as a RESTful web service
  • Jersey: used to quickly develop RESTful web services
  • User Management Engine (UME): used for user authentication
  • ABAP BAPI: a SAP delivered BAPI which we will expose as a RESTful web service
  • Netweaver Developer Studio: to develop everything

Step 1 - Create the DC’s

Create the required DC’s:

  • CAF DC caf/restdemo
  • External Library DC java/jersey
  • Web Module DC caf/restdemo/web

After creating the DC’s, configure their permissions and dependencies:

  • Add the Web Module DC to the permissions of the CAF ejbmodule DC

  • Add the Web Module DC to the dependencies of the CAF ear DC

  • Configure the dependencies of the Web Module DC

Step 2 - Setup Jersey

  • Download the latest Jersey 1.x (the 2.x version requires at least Java 7 which is not supported by SAP CE) ZIP bundle (do not use the JAR bundle).
  • Open the Java EE perspective in the Developer Studio and open the External Library DC. Select the libraries folder and import all Jersey JAR files.

  • Return to the Development Infrastructure perspective and add all the JAR files to both public parts of the External Library DC

Step 3 - Create the CAF Application Service

  • Open the CAF perspective and import the BAPI_CURRENCY_GETLIST RFC. You will have to provide an RFC destination name; if one already exists for your SAP ECC system use that one, otherwise specify a new name (demo in this example) and create the destination in the SAP CE Administration (nwa).

  • Select the created BAPI_CURRENCY_GETLIST service and generate the default mappings in a new Application Service named BAPI_CURRENCY_GETLIST

  • Save and generate the CAF application
  • Build and deploy the CAF application
  • Open the SAP CE Service Browser and test the application service you just deployed. If everything works correctly, you should see a list of currencies appear after executing the service.

Step 4 - Create the RESTful API

  • Open the Java EE perspective and open the Web Module DC.
  • Select and edit the web.xml file inside the WebContent\WEB-INF folder. Copy and paste the xml below, and make sure to adjust the display-name tag and com.sap.demo. parts to correspond to the project you created (it’s probably easiest if you kept all this identical to the provided screenshots).
web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?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>LocalDevelopment~caf~restdemo~web~demo.sap.com</display-name>
    <servlet>
        <servlet-name>Demo 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.caf.restdemo.modeled;com.sap.demo.caf.restdemo.web</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>Demo REST Service</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>
  • Create the com.sap.demo.caf.restdemo.web package in the source folder.
  • Inside this package, create the CurrencyResource class
  • Locate the JNDI name of the CAF Application Service we created in step 3. You can find the JNDI name in the SAP CE Administration (nwa).

  • Implement the CurrencyResource class. Copy and paste the code below, and make sure to use the proper JNDI name.
CurrencyResource.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.sap.demo.caf.restdemo.web;

import javax.naming.InitialContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.sap.caf.demo_sap_com.caf_restdemo.external.encsapdejci.ee.intern.TblCURRENCY_LIST_BAPI1090_2;
import com.sap.demo.caf.restdemo.modeled.BAPI_CURRENCY_GETLIST_Output;
import com.sap.demo.caf.restdemo.modeled.appsrv.bapi_currency_getlist.BAPI_CURRENCY_GETLISTServiceLocal;
import com.sap.security.api.IUser;
import com.sap.security.api.UMFactory;

@Path("/currency")
public class CurrencyResource {
    BAPI_CURRENCY_GETLISTServiceLocal currencyService;
    final String JNDI_NAME = "demo.sap.com/caf~restdemo~ear/LOCAL/com.sap.demo.caf.restdemo.modeled.appsrv.bapi_currency_getlist.BAPI_CURRENCY_GETLIST/com.sap.demo.caf.restdemo.modeled.appsrv.bapi_currency_getlist.BAPI_CURRENCY_GETLISTServiceLocal";

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Response listCurrencies(@Context HttpServletRequest request,
                                   @Context HttpServletResponse response) {
        try {
            // Authenticate
            IUser user = UMFactory.getAuthenticator().getLoggedInUser(request, response);
            if (null == user) {
                return Response.status(Response.Status.UNAUTHORIZED).build();
            }
            // Handle request
            InitialContext jndiContext = new InitialContext();
            currencyService = (BAPI_CURRENCY_GETLISTServiceLocal)jndiContext.lookup(JNDI_NAME);
            BAPI_CURRENCY_GETLIST_Output output = currencyService.bapiCURRENCYGETLIST(new TblCURRENCY_LIST_BAPI1090_2());
            return Response.ok(output.getCURRENCY_LIST().getItem()).build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
  • Return to the Development Infrastructure perspective
  • Build the Web Module DC
  • Build and deploy the CAF DC

Step 5 - Call the RESTful web service

The web service we created should now be reachable at the following URL:

http://mysapceserver.local:51000/demo.sap.com~caf~restdemo~web/rest/currency?j_username=johndoe&j_password=abcd1234

Make sure to adjust the hostname, port number, username and password according to your environment. If you used a different software component or DC name, you must change the path as well. Opening this URL in your browser should return output similar to this (the list should be a lot longer, I have shortened it for this blog post):

Example Output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[
    {
        "CURRENCY": "ADP",
        "CURRENCY_ISO": "ADP",
        "ALT_CURR": "020",
        "VALID_TO": 253402210800000,
        "LONG_TEXT": "Andorrese peseta"
    },
    {
        "CURRENCY": "AED",
        "CURRENCY_ISO": "AED",
        "ALT_CURR": "784",
        "VALID_TO": 253402210800000,
        "LONG_TEXT": "Verenigde Arabische Emiraten (dirham)"
    },
    {
        "CURRENCY": "AFA",
        "CURRENCY_ISO": "AFA",
        "ALT_CURR": "004",
        "VALID_TO": 253402210800000,
        "LONG_TEXT": "Afghani (oud)"
    },
    {
        "CURRENCY": "AFN",
        "CURRENCY_ISO": "AFN",
        "ALT_CURR": "971",
        "VALID_TO": 253402210800000,
        "LONG_TEXT": "Afghani"
    }
]

Comments

Real Time Web Analytics