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: 
rileyrainey
Product and Topic Expert
Product and Topic Expert

Introduction

I’ve been working on a project to bring the major elements of SAP mobility together in a single example. This example will explore the details of creating a delta-enabled OData web service, something that I mentioned in my last blog post.

At the end of the project we'll have this:

  • A web service that supports OData Delta Token processing
  • A Hybrid Kapsel application created using Web IDE that uses that service
  • Support for disconnected operation in the mobile app using the SMP SDK’s Offline capabilities
  • Support for adding and editing records in the mobile app
  • Run both the web service and mobile application atop the HANA Cloud Platform

The end result would nicely tie UI5, Web IDE, and HCP Mobile Services together into an offline-ready Hybrid mobile application.

Walking through the steps will require a bit of effort.  I plan to break it up into several articles, each covering one segment.  My goal is to have each article small enough to complete in an hour or less.

So, where to start?

Part 1 - A Delta-Token-Enabled OData Web Service

HANA Cloud Platform Trial Account – with Mobile Services

If you don’t already have a HANA Cloud Platform trial account, you can register for an account using this link.

HANA Cloud Platform Mobile Services, abbreviated HCPms, is now available as part of your HANA trial account, too.  You can review the instructions in Martin Grasshoff’s recent blog post for information on how to add HCPms to your HCP trial account.

You will need to sign up for both to complete this series of articles.

Build an OData Web Service

I’ve been working extensively in the past months with Apache Olingo, an open source OData web services framework.  I have come to like Olingo quite a lot.  I find it well organized and reliable, so I’m going to use it in this example to generate our OData web service.

The Data Model

The techniques that I’ll apply in this article can be used with almost any JDBC-compatible backing data storage.  For this project, though, I have chosen to start with a variant of SAP’s Enterprise Sales and Procurement Model (ESPM).  ESPM is a business data model widely used in examples in many current SAP programming systems.

You can find a number of articles on SCN describing different variants of ESPM.  Some use HANA as a back-end, some use other databases.  This particular variant is one that I created using the Java Persistence Architecture (JPA) to define the data model.  Olingo provides several ways to define an OData web service -- it has a particularly easy set of APIs for doing that if your starting point is JPA, so that's why I'm using that here.

The diagram below depicts the entity relationship diagram for this version of the ESPM data model.

Configure Your Java Development Environment

The complete source code to our web service is available on Github.  Here’s a few simple steps that you can follow to import, build, and run the service on your local machine.  We'll deploy it to your local machine first.  Later, we'll deploy a copy of the same service to a HANA Cloud Platform Java application server.


  1. If you have not already, install the Eclipse JEE Edition of Eclipse Kepler or Luna and the HCP Development plugins for it.  The installation guide I recently used can be found here – that document contains more information than we really care about for our purposes – limit the instructions you follow to steps 1.1 through 1.6 [NOTE: these steps install JDK, Eclipse, & Maven on your local machine; you can safely stop at completion of the step in 1.6 labelled "Check Maven User Settings"].
  2. Import the ESPM Olingo git repository as a Maven project

    (2.a) Start Eclipse
    (2.b) Import the project from Github -
    Click "File>Import", Select "Maven>Check out Maven projects from SCM", Click "Next"


    (2.c) Import (continued) -
    Select "git" as the SCM system of choice; enter "https://github.com/SAP/sap_mobile_platform_espm_olingo_services.git" as the SCM URL; click "Finish";  The import will take a moment.  At the end of the import, your Project Explorer should contain an ESPM_V1 project:



  3. Build the ESPM web services application
    -- Right-click on the ESPM_V1 project in the Project Explorer window, select "Run As>Maven Build...". You should see a dialog that looks like this one below.  Enter "clean install" in the Goals field.  Press "Run".



    Under normal conditions the Eclipse Console window will indicate the build succeeded with a message similar to this:




  4. Download a copy of the Tomcat 7 server binary distribution .ZIP file -- I used 7.0.57, but almost any Tomcat 7 version will do.
  5. Create a new Tomcat server instance in your Eclipse workspace by following these instructionsfrom the Eclipse documentation set.
  6. Run the project on your newly created Tomcat server -  Right-click on the ESPM_V1 project and select "Run As...>Run on Server".  You will see something like the dialog show below.  Select the "tomcat 7.0 server at localhost" and click "Finish".



  7. Verify the application runs correctly by visiting this link in your web browser: http://localhost:8080/ESPM_V1/api/Products

If the application was deployed correctly, you will see an XML representation of about 110 products.  The web service is programmed to install a collection of test data for Products, Stock, Suppliers, and Customers.  Each time the application is restarted, it will drop and reinitialize those tables in the database (you can change the behavior to preserve the state of the database between invocations by changing the eclipselink.ddl-generation property in src/main/resources/WEB-INF/persistence.xml from "drop-and-create-tables" to "create-tables").

If you scroll to the bottom of the Products response, you will see something like this:

As you can see, there is an UpdatedTimestamp field associated with each record.  Because our code supplied a delta token generator, there is a "delta" link URL at the bottom of the response.

OData Delta Tokens

The OData protocol is essentially a superset of a standard RESTful web service.  One of the really cool extensions to REST supplied by OData is Delta Token handling. Using Delta tokens affords more efficient communications between each client and the source web service (OASIS design document reference).

SAP’s Mobile Platform products – both cloud and on-premise versions – will leverage a delta token enabled web service to optimize data synchronization.  I recently wrote an article describing the mechanics of this process -- it might be worth your time to review it (link).  The point here is that we want the most scalable web service possible, so we’ll take the extra steps required to enable delta token processing for most of this service’s OData entity collections.

Apache Olingo provides a couple of framework-based options for adding delta token support to JPA-based projects.  I used the first of the two options documented in the Olingo on-line documentation.  To reconfigure the project to use that approach, I first added an “updated timestamp” column to each table where I wanted to add delta token support.  I then added or modified the JPA @PrePersist and @PreUpdate methods to automatically update this updatedTimestamp field with the current server time for both of these operations.  Finally, I created the ESPMJPADeltaListener class based on ODataJPATombstoneEntityListener, as described in the Olingo documentation.

Adding the "updated timestamp" column follows a common pattern of leveraging server timestamps to track what changes between requests.  In the implementation of the ESPMJPADeltaListener class, I set up the delta token generator to return a server timestamp.  This timestamp will be returned as part of the request contents.


public class ESPMJPADeltaListener extends ODataJPATombstoneEntityListener {
static final String DATEFORMAT = "yyyy-MM-dd HH:mm:ss";
/*
  * Generate a web-service-specific delta token to be passed back to the
  * client with a response.  In this case, we simply generate an ISO-8601-style
  * string reflecting the current UTC date/time.
  * @see org.apache.olingo.odata2.jpa.processor.api.ODataJPATombstoneEntityListener#generateDeltaToken(java.util.List, javax.persistence.Query)
  */
@Override
  public String generateDeltaToken(List<Object> deltas, Query query) {
  final SimpleDateFormat sdf = new SimpleDateFormat(DATEFORMAT);
      sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
      final String utcTime = sdf.format(new Date());
      return utcTime;
  }





The getQuery() method is a bit more complex, but the core functionality is found below.  Basically, if the client supplies a delta token as part of the GET request, the function with modify the SQL data fetched to be limited to rows that changed after the timestamp supplied in the delta token.  The client will not have a delta token to supply on the initial request -- and some applications may not want to leverage delta tokens at all.  In both of those cases the code responds to the missing delta token by returning a complete set of data results.

 


String deltaToken = ODataJPATombstoneContext.getDeltaToken();
  Query query = null;
  if (deltaToken != null) {
       String statement = jpqlStatement.toString(); 
       String[] statementParts = statement.split(JPQLStatement.KEYWORD.WHERE); 
       String deltaCondition = jpqlContext.getJPAEntityAlias() + ".updatedTimestamp >= {ts '" + deltaToken + "'}"; 
       if (statementParts.length > 1) 
       {   
            statement = statementParts[0] + JPQLStatement.DELIMITER.SPACE + JPQLStatement.KEYWORD.WHERE +                JPQLStatement.DELIMITER.SPACE + deltaCondition + JPQLStatement.DELIMITER.SPACE + JPQLStatement.Operator.AND +                statementParts[1]; 
       } 
       else {   
            statement = statementParts[0] + JPQLStatement.DELIMITER.SPACE + JPQLStatement.KEYWORD.WHERE + JPQLStatement.DELIMITER.SPACE + deltaCondition; 
       }
       query = em.createQuery(statement);
  }
  else  {
       query = em.createQuery(jpqlStatement.toString());
  }
  return query;





You can see delta tokens in action by copying the entire contents of the delta token's "href" attribute from step 7 and pasting that into your browser URL box. You will see a different response this time -- one that does not include any records, since nothing has been changed since the original request was issued.

Deploy the Web Service to your HCP Trial Account

For simplicity’s sake, I chose to store my ESPM data in an embedded Java-based SQL engine, Hypersonic. You could do the same thing in HANA, but the extra steps involved to do that would not really be relevant to our example.  To wrap up this exercise, we'll deploy the ESPM web service onto a HANA Cloud Platform app server using your trial account.

Your HANA Trial includes the capability to deploy one small sized Java application at no charge (this is a 'micro' instance in AWS terms).  Unless you have been working with Java in HCP, your probably have not taken advantage of this resource yet.  If it happens that you have, you will need to stop any Java applications you are running to deploy our ESPM application.

  1. Deploy the application using Eclipse -- A deployment to the HANA Cloud Platform Java server is performed in much the same way that your deployed to your local Tomcat instance.  Start by right-clicking on the ESPM_V1 project and select "Run>Run on Server...".




    Select "Manually Create a new Server" and choose the Server Type as "SAP>SAP HANA Cloud Platform".

    Enter "hanatrial.ondemand.com" as the Landscape host.

    Click "Next".



    Enter "espm" as the Application name (for some reason, HCP insists that this name be all lower case with no symbol characters).

    For Account Name, enter your SAP S/C/I/D-Number followed by "trial" (no spaces or other punctuation).

    For User Name, enter your SAP S/C/I/D-Number.

    Enter your password.

    I found that I had to uncheck "Save Password" to get this to work correctly on OS X.  You may start with it "checked" if you like and then uncheck it if the operation fails (the only consequence I experienced was having to re-enter my password a few extra times).

    Click 'Finish'.

    The deployment will take several minutes to complete.  You can move on to Step 2 to monitor the status of the deployment and to prepare to test the deployed service.

  2. Check the deployment in the HANA Cloud Platform Cockpit -- In your browser, open the HANA Cloud Platform Cockpit.

    Click "Java Applications" on the left hand bar.

    You will see something like the screen below, although most of the Actions (start, Stop, Switch, and Update) will be disabled (greyed-out) until the deployment completes.  You can refresh the page to monitor the deployment status.

    Once all the Action buttons are enabled. We're ready to move on to Step 3.

    Click on "espm" in the Name column to continue.



  3. Test the ESPM web service -- The details page on the "espm" application will include a link to the "Application URL" (below)



    Click the Application URL link.  You will see a details form looking something like this:



    Append "api/Products" to the URL and press "Go" or Enter. 

    The end result should be the same response you saw with your local Tomcat service.

Summary

This ends the first section of our four part project.  If all went according to plan, you have successfully deployed your Olingo-based web service into the HANA Cloud Platform.  You also now have your machine configured to expand your exploration of Java applications that are deployable to the HCP landscape.

In the next article in this series, we'll explore how to use HCP's Web IDE and other elements of the SAP Mobile Platform to build a Hybrid mobile application that accesses this service.

9 Comments