Skip to Content
Author's profile photo Krishna Kumar S

Enterprise Sales Procurement Model (ESPM) application – Version 2.0 released

Several years ago, there was a set of End to End tutorials published in SCN that showcased developing applications on SAP HANA Cloud Platform.

 

The Enterprise Sales Procurement Model (ESPM) application was a reference implementation around a webshop scenario that educates on building applications with technologies like SAPUI5, OData etc., leveraging the Java runtime on SAP HANA Cloud Platform. The application demonstrated the consumption of different platform services like Persistence Service etc.

 

Today, SAP HANA Cloud Platform offers a rich set of Capabilities and Services. Going hand in hand, ESPM application also needed to showcase the consumption of some these new set of services and capabilities.

 

We are glad to now offer a newer updated ESPM application that showcases a subset of capabilities and services offered by SAP HANA Cloud Platform:

  • SAP Jam
  • Document Service
  • Authorization Management

 

From a technology point of view, the ESPM application showcases the following technologies:

  • SAPUI5
  • OData
  • JPA for persistence
  • SAP HANA DB

 

Below is the architecture diagram of the ESPM application.

 

ESPM-Arch.jpg

 

The front end of the ESPM application is also now updated based on the newer blue crystal theme of SAPUI5. Below is a snapshot of the webshop application home page.

 

ESPM-UI.png

ESPM Source code and documentation

The source code and documentation of ESPM application is available on Github.
The hyperlink to the Github repository for ESPM is https://github.com/SAP/cloud-espm-v2

 

The above repository has multiple branches and some of those branches are for the openSAP course “Developing Java-Based Apps on SAP HANA Cloud Platform”. 

The new openSAP course Developing Java-Based Apps on SAP HANA Cloud Platform  started just a few days back on Wednesday, September 7th 2016, explains how to develop Java-based apps on SAP HANA Cloud Platform using the newly updated ESPM application. The openSAP Course guide on SCN for your reference. 

During the course of the above openSAP course, you will learn SAP HANA Cloud Platform capabilities and services with ESPM application

Hope you will find the ESPM version 2.0 useful. Do post in your comments and feedback. Happy coding! 

 

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Oliver Pitz
      Oliver Pitz

      Hello Krishna,

      a quick question concerning the xml binding of the odata: when I try to consume the odata service in a standardlist via the items aggreation the browser console shows this error:

       

      Log-dbg.js:456 2021-02-02 13:47:42.310324 HTTP request failed (500 Internal Server Error): {"error":{"code":null,"message":{"lang":"en","value":"Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.4.v20160829-44060b6): org.eclipse.persistence.exceptions.DatabaseException\nInternal Exception: java.sql.SQLException: Borrow prepareStatement from pool failed\nError Code: 0\nCall: SELECT * FROM (SELECT * FROM (SELECT EL_TEMP.*, ROWNUMBER() OVER() AS EL_ROWNM FROM (SELECT PRODUCT_ID AS a1, CATEGORY AS a2, CATEGORY_NAME AS a3, CURRENCY_CODE AS a4, DIMENSION_DEPTH AS a5, DIMENSION_HEIGHT AS a6, DIMENSION_UNIT AS a7, DIMENSION_WIDTH AS a8, LONG_DESCRIPTION AS a9, NAME AS a10, PICTURE_URL AS a11, PRICE AS a12, QUANTITY_UNIT AS a13, SHORT_DESCRIPTION AS a14, SUPPLIER_ID AS a15, WEIGHT AS a16, WEIGHT_UNIT AS a17, SUPPLIER_SUPPLIER_ID AS a18 FROM ESPM_PRODUCT ORDER BY PRODUCT_ID) AS EL_TEMP) AS EL_TEMP2 WHERE EL_ROWNM <= ?) AS EL_TEMP3 WHERE EL_ROWNM > ?\n\tbind => [2 parameters bound]\nQuery: ReadAllQuery(referenceClass=Product sql=\"SELECT * FROM (SELECT * FROM (SELECT EL_TEMP.*, ROWNUMBER() OVER() AS EL_ROWNM FROM (SELECT PRODUCT_ID AS a1, CATEGORY AS a2, CATEGORY_NAME AS a3, CURRENCY_CODE AS a4, DIMENSION_DEPTH AS a5, DIMENSION_HEIGHT AS a6, DIMENSION_UNIT AS a7, DIMENSION_WIDTH AS a8, LONG_DESCRIPTION AS a9, NAME AS a10, PICTURE_URL AS a11, PRICE AS a12, QUANTITY_UNIT AS a13, SHORT_DESCRIPTION AS a14, SUPPLIER_ID AS a15, WEIGHT AS a16, WEIGHT_UNIT AS a17, SUPPLIER_SUPPLIER_ID AS a18 FROM ESPM_PRODUCT ORDER BY PRODUCT_ID) AS EL_TEMP) AS EL_TEMP2 WHERE EL_ROWNM <= ?) AS EL_TEMP3 WHERE EL_ROWNM > ?\")"}}} - sap.ui.model.odata.v2.ODataModel
      f @ Log-dbg.js:456
      L.error @ Log-dbg.js:232
      J._handleError @ ODataModel-dbg.js:4389
      J._processError @ ODataModel-dbg.js:4085
      X @ ODataModel-dbg.js:3275
      Y @ ODataModel-dbg.js:3347
      W @ ODataModel-dbg.js:3051
      (anonymous) @ ODataModel-dbg.js:6618
      eval @ datajs.js?eval:17
      p9 @ datajs.js?eval:17
      XMLHttpRequest.send (async)
      request @ datajs.js?eval:17
      E2 @ datajs.js?eval:17
      o.request @ datajs.js?eval:17
      J._request @ ODataModel-dbg.js:6624
      _ @ ODataModel-dbg.js:3135
      (anonymous) @ ODataModel-dbg.js:3094
      Promise.then (async)
      Z @ ODataModel-dbg.js:3089
      J._submitRequest @ ODataModel-dbg.js:3155
      J._submitBatchRequest @ ODataModel-dbg.js:3389
      (anonymous) @ ODataModel-dbg.js:3808
      e @ each-dbg.js:61
      J._processRequestQueue @ ODataModel-dbg.js:3758
      (anonymous) @ ODataModel-dbg.js:3864
      Promise.then (async)
      (anonymous) @ ODataModel-dbg.js:3863
      Promise.then (async)
      J._processRequestQueueAsync @ ODataModel-dbg.js:3862
      (anonymous) @ ODataModel-dbg.js:4618
      Promise.then (async)
      J._processRequest @ ODataModel-dbg.js:4610
      J.read @ ODataModel-dbg.js:5307
      n._getLength @ ODataListBinding-dbg.js:808
      n.getContexts @ ODataListBinding-dbg.js:169
      o.refreshAggregation @ ManagedObject-dbg.js:4116
      t.refreshItems @ ListBase-dbg.js:594
      A.refresh @ ManagedObjectMetadata-dbg.js:392
      r @ ManagedObject-dbg.js:3833
      b.fireEvent @ EventProvider-dbg.js:247
      n._fireRefresh @ ODataListBinding-dbg.js:896
      n.initialize @ ODataListBinding-dbg.js:978
      o._bindAggregation @ ManagedObject-dbg.js:3876
      t._bindAggregation @ ListBase-dbg.js:700
      o.updateBindings @ ManagedObject-dbg.js:4271
      o._propagateProperties @ ManagedObject-dbg.js:4740
      o.propagateProperties @ ManagedObject-dbg.js:4721
      o._propagateProperties @ ManagedObject-dbg.js:4743
      o.propagateProperties @ ManagedObject-dbg.js:4721
      o._propagateProperties @ ManagedObject-dbg.js:4743
      o.propagateProperties @ ManagedObject-dbg.js:4715
      o.setParent @ ManagedObject-dbg.js:2624
      o.addAggregation @ ManagedObject-dbg.js:2160
      (anonymous) @ XMLTemplateProcessor-dbg.js:684
      Promise.then (async)
      (anonymous) @ XMLTemplateProcessor-dbg.js:657
      (anonymous) @ SyncPromise-dbg.js:309
      c @ SyncPromise-dbg.js:60
      S @ SyncPromise-dbg.js:225
      S.then @ SyncPromise-dbg.js:308
      Z @ XMLTemplateProcessor-dbg.js:654
      $ @ XMLTemplateProcessor-dbg.js:725
      x @ XMLTemplateProcessor-dbg.js:553
      t.parseTemplatePromise @ XMLTemplateProcessor-dbg.js:321
      m.onControllerConnected @ XMLView-dbg.js:655
      F @ View-dbg.js:492
      r @ Component-dbg.js:203
      s.runAsOwner @ Component-dbg.js:613
      P @ View-dbg.js:476
      (anonymous) @ View-dbg.js:504
      Promise.then (async)
      g._initCompositeSupport @ View-dbg.js:503
      (anonymous) @ ManagedObject-dbg.js:528
      constructor @ ManagedObject-dbg.js:552
      constructor @ Element-dbg.js:200
      constructor @ Control-dbg.js:181
      f @ Metadata-dbg.js:453
      f @ Metadata-dbg.js:453
      w @ View-dbg.js:1153
      v @ View-dbg.js:1117
      c.createContent @ UIComponent-dbg.js:584
      (anonymous) @ UIComponent-dbg.js:329
      o.runWithPreprocessors @ ManagedObject-dbg.js:1015
      (anonymous) @ UIComponent-dbg.js:328
      r @ Component-dbg.js:203
      s.runAsOwner @ Component-dbg.js:613
      c.init @ UIComponent-dbg.js:327
      init @ Component.js:21
      (anonymous) @ ManagedObject-dbg.js:533
      constructor @ ManagedObject-dbg.js:552
      constructor @ Component-dbg.js:304
      constructor @ UIComponent-dbg.js:86
      f @ Metadata-dbg.js:453
      l1 @ Component-dbg.js:2634
      D @ Component-dbg.js:2219
      (anonymous) @ Component-dbg.js:2274
      r @ Component-dbg.js:203
      (anonymous) @ Component-dbg.js:2273
      Promise.then (async)
      z @ Component-dbg.js:2272
      s.create @ Component-dbg.js:2079
      i @ Component-dbg.js:1224
      s._createComponent @ Component-dbg.js:1235
      e._createComponent @ ComponentContainer-dbg.js:354
      e.onBeforeRendering @ ComponentContainer-dbg.js:373
      d._handleEvent @ Element-dbg.js:336
      $ @ RenderManager-dbg.js:783
      R.renderControl @ RenderManager-dbg.js:904
      R.render @ RenderManager-dbg.js:1286
      U.rerender @ UIArea-dbg.js:650
      Y.renderPendingUIUpdates @ Core-dbg.js:2813
      setTimeout (async)
      Y.addInvalidatedUIArea @ Core-dbg.js:2751
      U.addInvalidatedControl @ UIArea-dbg.js:541
      U.invalidate @ UIArea-dbg.js:520
      o.setParent @ ManagedObject-dbg.js:2635
      o.addAggregation @ ManagedObject-dbg.js:2160
      U.addContent @ UIArea-dbg.js:378
      (anonymous) @ Interface-dbg.js:57
      c.placeAt @ Control-dbg.js:669
      e.run @ ComponentSupport-dbg.js:125
      (anonymous) @ ComponentSupport-dbg.js:224
      (anonymous) @ ui5loader-dbg.js:1829
      Promise.then (async)
      requireAll @ ui5loader-dbg.js:1747
      executeModuleDefinition @ ui5loader-dbg.js:1803
      (anonymous) @ ui5loader-dbg.js:1221
      ModuleDefinitionQueue.process @ ui5loader-dbg.js:1219
      execModule @ ui5loader-dbg.js:1671
      requireModule @ ui5loader-dbg.js:1463
      requireAll @ ui5loader-dbg.js:1737
      r @ ui5loader-dbg.js:1993
      setTimeout (async)
      Y._executeOnInit @ Core-dbg.js:1287
      Y._executeInitialization @ Core-dbg.js:1398
      Y.init @ Core-dbg.js:1226
      (anonymous) @ Core-dbg.js:477
      m @ Core-dbg.js:170
      X.finishTask @ Core-dbg.js:164
      (anonymous) @ Core-dbg.js:500
      (anonymous) @ Core-dbg.js:892
      Promise.then (async)
      Y._boot @ Core-dbg.js:891
      (anonymous) @ Core-dbg.js:499
      m @ Core-dbg.js:170
      X.finishTask @ Core-dbg.js:164
      (anonymous) @ Core-dbg.js:574
      Promise.then (async)
      constructor @ Core-dbg.js:573
      (anonymous) @ Core-dbg.js:4227
      (anonymous) @ ui5loader-dbg.js:1829
      requireAll @ ui5loader-dbg.js:1752
      executeModuleDefinition @ ui5loader-dbg.js:1803
      ui5Define @ ui5loader-dbg.js:1935
      execModule @ ui5loader-dbg.js:1625
      requireModule @ ui5loader-dbg.js:1463
      requireSync @ ui5loader-dbg.js:2062
      (anonymous) @ jquery-mobile-custom-dbg.js:2163

       

      An direct access via odatamodel.read function works without any issues and I can bind it then via a local json model. but of course, a direct binding how we use it with abap gateway services would be easier. Do I miss something here? Or is it not possible at all with java odata services?

       

      Here my example how I try it directly in the xml:

       

      <List id="listSapDemo" headerText="Products" items="{path : '/Products'}">
      <StandardListItem title="{Name}"/>
      </List>

      Kind regards,

      Oliver