Skip to Content
Author's profile photo Kevin Hu

Offline Odata Native App – Easy as a pie with Agentry

Background

Offline Odata Native App, sounds good? If users ask for it, usually it will be positioned to a Fiori/UI5 requirement. There is some posts talking about how to build an offline UI5 app with Kapsel, wrap it up and run it in Fiori Client. But from my experience, it is still not good enough, especially from a UX perspective.

So from the SAP product stack, is there an answer for a robust native offline odata app?

Yes. That is Agentry, which is an already proven offline mobile solution. What if I tell you it can also be build cross-platform? Awesome

So let us get started. If you are new to Agentry, follow this landing page to get some information.

Set up the environment

For Agentry beginners, check these prerequisites:

1. Install SAP Mobile Platform server. See this tutorial.

2. Install Agentry Editor Plugin for eclipse.

3. You can build a simple Agentry app or just easily deploy the work manager app, refer to the tutorial mentioned in step 1.


Then we need to set up our environment to use Apache Olingo Library (our odata client), but before that we need to set up Maven in our eclipse. The steps have been covered in my previous blog.


The reason we use Olingo is that it supports Odata V4 and has a good dev community. Odata4j is another option but currently it only support Odata V2 but it is very easy to set up. Also check this useful blog which describe how to connect odata from Agentry without coding. But for flexibility purpose, using 3rd-party library such as Olingo is highly recommended.


Get Started


Suppose you have everything ready. The idea of this blog is to call the Northwind sample odata service, pull out all the customer entities and make it offline with Agentry.


The major steps are listed below:

1. set up the olingo dependencies in maven. Check my previous blog on how to set up maven for Agentry java project.

2. create the steplet class and pojo class in our eclipse java project.

3. create data model “Customer” with three properties”CustomerID, CompanyName,ContactName” and the collection in Agentry Project.

4. create a fetch for the “Customers” collection and pull out the data from the odata source.

5. deploy and test.

First edit the maven pom.xml to include Olingo libraries in the Maven Project. More information is provided by Apache.


<dependency>
     <groupId>org.apache.olingo</groupId>
     <artifactId>odata-client-api</artifactId>
     <version>4.3.0</version>
</dependency>
<dependency>
     <groupId>org.apache.olingo</groupId>
      <artifactId>odata-client-core</artifactId>
      <version>4.3.0</version>
</dependency>
<dependency>
      <groupId>org.apache.olingo</groupId>
      <artifactId>odata-commons-api</artifactId>
      <version>4.3.0</version>
  </dependency>
  <dependency>
       <groupId>org.apache.olingo</groupId>
       <artifactId>odata-commons-core</artifactId>
       <version>4.3.0</version>
  </dependency>











Then we create the pojo class for the object “ZOdataCustomer”.


package com.syclo.customer.sap.component.odata.object;
import com.syclo.sap.SAPObject;
import com.syclo.sap.SAPObjectI;
import com.syclo.sap.jco.JCO.Table;
public class ZOdataCustomer extends SAPObject implements SAPObjectI {
  public String customerID;
  public String companyName;
  public String contactName;
  public String ID;
  public ZOdataCustomer() {
  }
  public void setCustomerID(String customerid) {
  this.customerID = customerid;
  }
  public String getCustomerID() {
  return this.customerID;
  }
  public void setCompanyName(String companyname) {
  this.companyName = companyname;
  }
  public String getCompanyName() {
  return this.companyName;
  }
  public void setContactName(String contactname) {
  this.contactName = contactname;
  }
  public String getContactName() {
  return this.contactName;
  }
  public void setID(String id) {
  this.ID = id;
  }
  public String getID() {
  return null;
  }
  public void setNotes(Table arg0) throws Exception {
  }
  public void setProperties(Table arg0) throws Exception {
  }
}











Then create the steplet class including the call to the odata service. We are using the sample Northwind Odata service V4. Within the steplet, it is call the odata service API, get the “Customers” entityset data and iterate it into the ZOdataCustomer objects. Jump into the Apache Olingo website for more information about the supported APIs. As this is only a tutorial, I intend to make it simple. It is always good to follow the SAP’s best practice to create the stephandler and so on.


package com.syclo.customer.sap.component.odata.steplet;
import java.net.URI;
import java.util.ArrayList;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.domain.ClientEntity;
import org.apache.olingo.client.api.domain.ClientEntitySet;
import org.apache.olingo.client.api.domain.ClientEntitySetIterator;
import org.apache.olingo.client.api.ODataClient;
import org.apache.olingo.client.core.ODataClientFactory;
import com.syclo.agentry.AgentryException;
import com.syclo.customer.sap.component.odata.object.ZOdataCustomer;
import com.syclo.sap.SAPObject;
import com.syclo.sap.SAPObjectFactory;
import com.syclo.sap.Steplet;
import com.syclo.sap.User;
public class GetOdataCustomerSteplet extends Steplet {
  protected com.syclo.sap.FetchSession _stepletFetchSession = null;
  public GetOdataCustomerSteplet(com.syclo.agentry.FetchSession session)
  throws AgentryException {
  super(session);
  this._stepletFetchSession = ((com.syclo.sap.FetchSession) session);
  this._stepletFetchSession.setSteplet(this);
  }
  @Override
  public boolean execute() throws AgentryException {
  try {
  ZOdataCustomer customer = null;
  ArrayList<SAPObject> recs = new ArrayList<SAPObject>();
  ODataClient client = ODataClientFactory.getClient();
  String serviceRoot = "http://services.odata.org/V4/Northwind/Northwind.svc";
  URI customersUri = client.newURIBuilder(serviceRoot)
  .appendEntitySetSegment("Customers").build();
  ODataRetrieveResponse<ClientEntitySetIterator<ClientEntitySet, ClientEntity>> response = client
  .getRetrieveRequestFactory()
  .getEntitySetIteratorRequest(customersUri).execute();
  ClientEntitySetIterator<ClientEntitySet, ClientEntity> iterator = response
  .getBody();
  while (iterator.hasNext()) {
  ClientEntity oCustomer = iterator.next();
  customer = new ZOdataCustomer();
  customer.setCustomerID(oCustomer.getProperty("CustomerID")
  .getValue().toString());
  customer.setCompanyName(oCustomer.getProperty("CompanyName")
  .getValue().toString());
  customer.setContactName(oCustomer.getProperty("ContactName")
  .getValue().toString());
  recs.add(customer);
  }
  int sz = recs.size();
  if (sz > 0) {
s._returnData = createSAPObjectArray(
  SAPObjectFactory.create(
  "com.syclo.customer.sap.component.odata.object.ZOdataCustomer",
  new Class[] { User.class }, null), recs);
  }
  return true;
  } catch (Throwable e) {
  throwExceptionToClient(e);
  }
  return false;
  }
}









Export the java source to jar file. In here I will use the maven shade plugin so that I can get a single jar file with all the dependencies and deploy it to SMP server. Again refer to my previous bloghttp://scn.sap.com/community/developer-center/mobility-platform/blog/2016/09/27/how-to-set-up-maven-with-agentry-java-project on how to set it up in maven. Once we got the jar file from the target folder, copy it to the java folder of your Agentry app and update the classpath in JavaBE.ini file. Restart SMP server.

Then in Agentry Project, create a new object “ZOdataCustomer” with the following properties. customerID is the key.

Capture.PNG

Create a collection in MainObject named “ZOdataCustomers”.

Capture2.PNG

Create a Step named “ZGetOdataCustomerSteplet”, pointing to the steplet java class we just created.

Capture3.PNG

Finally create the fetch “ZOdataCustomersFetch”, pointing to the collections “ZOdataCustomers” using the step “ZGetOdataCustomerSteplet”.

Capture4.PNG

Capture5.PNG

OK. Now publish the Agentry project to SMP and we are done. Run the test from the test environment and you can see the odata has been made offline!

Capture6.PNG

Next Step

I will try to read with “$expand” option in the “Customers” entityset in the sample service. This will make the all the orders for the customers offline. Also I will do some CRUD operations. I will also try to consume to a SAP Gateway exposed Odata service. These will be covered in my next post.

Feel free to leave your comments. Happy coding!

Assigned Tags

      2 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Michael Appleby
      Michael Appleby

      Hi Kevin,

      Probably due to the 1DX updates to redirects as well as the latest blog migration, several of your links have been reported as broken.  Please fix the links and resubmit.  I would also recommend that you keep an eye on it in the next few weeks as the 1DX SCN changes come fast and furious.

      Cheers, Mike (Moderator)

      SAP Technology RIG

      Author's profile photo Marçal Oliveras
      Marçal Oliveras

      Hi Michael, sorry for the Off-Topic but I’m really confused with the new SCN…

      • All the links to previous blogs are not valid anymore? Will SAP implement an automatic redirection to the new URL that doesn’t even keep the same ID?
      • Is it not possible to follow the Agentry blogs, documents and questions as I did before via RSS? And via e-mail notifications? As I see I can only follow the already created ones, but I want to get notified once something new is published.
      • I go to http://go.sap.com/community/topic/agentry.html thinking that this is the entry point to the Agentry community, but the list of blogs and questions is empty… For instance this blog is not showing there. Why?