Skip to content
This repository was archived by the owner on Mar 28, 2019. It is now read-only.

Adding Custom REST Calls

Steven Davelaar edited this page Mar 4, 2016 · 2 revisions

AMPA provides standard support for calling CRUD REST Resources. You can also add custom REST calls that do not directly map to one of the standard CRUD resources. You can do this in two ways:

  • Declaratively by defining a Custom resource
  • Programmatically by calling a REST resource in Java code

###Defining a Custom Resource The Specifying CRUD Resource Details wizard page allows you to add custom resources. When you do this, AMPA will generate an additional method with the same name as your custom resource into your entity CRUD service class with the following signature:

public void doSomething(Department department) {
  invokeCustomMethod(department, "doSomething");
}

The advantage of this approach is that it is fast and easy, and if you are offline or the REST call fails with some server error, the custom resource action will be registered as a pending data sync action and AMPA will make the call later on when you are online again. In other words, it is handled in the same ways as standard CRUD transactions that you make in offline mode.

The disadvantage is that it limits you in how you supply query and path parameters, and how you provide the request payload (this can only be the serialized data object). The value of query and path parameters can be defined declaratively using the options described in section Specifying CRUD Resource Details. If you need complete flexibility in how you construct your URI path with query and path parameters, it is better to go for the programmatic approach and code your REST call in Java.

###Calling a REST Resource in Java You can invoke any REST resource using the invokeRestService method on the remote persistence manager, which is either the RestJSONPersistenceManager, or if you connect to Oracle Mobile Cloud Service, the MCSPersistenceManager.

You could also use the standard MAF RestServiceAdapter, however using the invokeRestService method has some advantages:

  • It requires less coding, just one line of code to make the REST call
  • It will handle all responses with HTML status code in 200-299 range successfully, no exception is thrown for status codes 201-299 as is the case with the RestServiceAdapter.
  • If you have enabled web service logging, you can easily view the REST call details
  • If connecting to MCS, you do not need to specify the Oracle-Mobile-Backend-Id and (anonymous) Authorization header parameters.

The signature of the invokeRestService method is as follows:

public String invokeRestService(String connectionName, String requestType, String requestUri,String payload,
                                Map<String,String> headerParamMap, int retryLimit, boolean secured)

Note that the last argument secured, is no longer used, it is only there for backward compatibility.

You will typically add a method to your entity CRUD service class in which you invoke the invokeRestService method. You can then easily make the REST call from the UI by dragging and dropping the method onto your AMX page. Here is a sample method that makes such a REST call:

public void invokeSomeRestResource(String pathParamValue,String queryParamValue) {
  if (isOnline()) {
      RestJSONPersistenceManager rpm = new RestJSONPersistenceManager();      
      String uri = "/someResourcePath/"+pathParamValue+"?someQueryParam="+queryParamValue;
      String result = rpm.invokeRestService("MyRESTConn", "GET", uri, null, null, 0, false);
    // do something with the result
  }    
}

If you want to execute the REST call in the background, the code looks as follows:

public void invokeSomeRestResource(String pathParamValue,String queryParamValue) {
  TaskExecutor.getInstance().execute(true, () -> {
    if (isOnline())
    {
      RestJSONPersistenceManager rpm = new RestJSONPersistenceManager();      
      String uri = "/someResourcePath/"+pathParamValue+"?someQueryParam="+queryParamValue;
      String result = rpm.invokeRestService("MyRESTConn", "GET", uri, null, null, 0, false);
      // do something with the result
    }    
  });
}

Note that we are using a Java 7 lambda expression to pass in a Runnable to the TaskExecutor.

If the response should be converted to a list of entities and stored in SQLite database, just like the standard Find All resource, you can use the handleReadResponse method on the remote persistence manager do all this for you. This is the signature of this method:

public <E extends Entity> List<E> handleReadResponse(String jsonResponse, Class entityClass, 
                                                     String collectionElementName, String rowElementName,          
                                                     List<BindParamInfo> parentBindParamInfos, boolean deleteAllRows)

The collectionElementName and rowElementName arguments map to the Payload List Element Name and Payload Row Element Name that we specify for standard GET resources. See section Specifying CRUD Resource Details for an explanation on how to set the values of these arguments based on the structure of the response payload. There is one gotcha here, if the response returns an array as top-level object, you need to specify root as the value for collectionElementName.

You can leave the parentBindParamInfos argument null, and the deleteAllRows argument is obsolete, it is only there for backwards compatibility. If you want to delete all local rows prior to processing the response payload, then you need to add the code to do so yourself (see section Accessing the SQLite Database).

Here is how the above example can be extended to process the response payload into a list of entities:

public void invokeSomeRestResource(String pathParamValue,String queryParamValue) {
  if (isOnline()) {
      RestJSONPersistenceManager rpm = new RestJSONPersistenceManager();      
      String uri = "/someResourcePath/"+pathParamValue+"?someQueryParam="+queryParamValue;
      String result = rpm.invokeRestService("MyRESTConn", "GET", uri, null, null, 0, false);
      List<Employee> emps = rpm.handleReadResponse(result, Employee.class, "root", null, null, false);
      setEntityList(emps);
  }    
}

Clone this wiki locally