cancel
Showing results for 
Search instead for 
Did you mean: 

Function implementation SAP Cloud Application Programming Model

Dear, I'm implementing a Function on SAP Cloud Application Programming Model using Java (https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/94c7f17ecc0b4508b3f4c5ed85bd7760.html), in the documentation it says that we can set the response like bellow:

"Provides the methods for creating a response for a successful or failed function call:

  • In the event of a successful function call, you can return data as one of the following using the setSuccess method:
    • List of Map containing complex types
    • List of EntityData containing entities
    • List of Object containing primitive types
  • In the event of a failed function call, you can return an instance of ErrorResponse, containing the error message and status code, using the setError method."

For simplicity I'm creating two instances os EntityData and setting it to response object like bellow:

Service definition:

using br.com.strategiatec from '../db/data-model';
service SalesmanService {
  entity Salesman as projection on strategiatec.Salesman;
  function findSalesmanByLocation() returns Salesman;
}

My implementation:

@Function(Name = "findSalesmanByLocation", serviceName = "SalesmanService")
public OperationResponse findSalesmanByLocation(OperationRequest functionRequest, ExtensionHelper extensionHelper) {
try {
List<EntityData> result = new ArrayList<EntityData>();
Map<String, Object> obj1 = new HashMap<String, Object>();
obj1.put("ID", 12);
obj1.put("name", "Test Name 1");
obj1.put("latitude", -19.859451);
obj1.put("longitude", -43.9456877);
Map<String, Object> obj2 = new HashMap<String, Object>();
obj2.put("ID", 35);
obj2.put("name", "Test Name 2");
obj2.put("latitude", -19.859451);
obj2.put("longitude", -43.9456877);
List<String> keys = new ArrayList<String>();
keys.add("ID");
result.add(EntityData.createFromMap(obj1, keys, "Salesman"));
result.add(EntityData.createFromMap(obj2, keys, "Salesman"));
OperationResponse response = OperationResponse.setSuccess().setEntityData(result).response();
return response;
} catch (Exception e) {
return OperationResponse
.setError(ErrorResponse.getBuilder().setMessage("Erro on function calll").response());
}
}

When I call the service, I'm getting just the first record:

https://xx-xx-srv.cfapps.eu10.hana.ondemand.com/odata/v2/SalesmanService/findSalesmanByLocation

<?xml version='1.0' encoding='utf-8'?>
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xml:base="https://xx-xx-srv.cfapps.eu10.hana.ondemand.com:443/odata/v2/SalesmanService/">
    <id>https://xx-xx-srv.cfapps.eu10.hana.ondemand.com:443/odata/v2/SalesmanService/Salesman(12)</id>
    <title type="text">Salesman</title>
    <updated>2019-01-27T08:23:22.467Z</updated>
    <category term="SalesmanService.Salesman" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
    <link href="Salesman(12)" rel="edit" title="Salesman"/>
    <content type="application/xml">
        <m:properties>
            <d:ID>12</d:ID>
            <d:name>Test Name 1</d:name>
            <d:latitude>-19.859451</d:latitude>
            <d:longitude>-43.9456877</d:longitude>
        </m:properties>
    </content>
</entry>

I have tried using Primitive types instead an Entity just to test but it returns just one entry too.

There is a missing point?

Best regards

Accepted Solutions (1)

Accepted Solutions (1)

Dear, I've opened a ticket o support.sap.com and the solution is just put an "array of" just before return type on service definition, like that:

function findSalesmanByLocation() returns array of Salesman;

Best regards

Answers (1)

Answers (1)

Ivan-Mirisola
Product and Topic Expert
Product and Topic Expert

Hi Isaías,

Thanks for sharing the answer. I was trying to figure out what the issue was.

To add to your solution, one thing that would make your code more "elegant" is to make use of the Entity Data builder class, like so:

@Function(Name="findSalesmanByLocation", serviceName = "SalesmanService")
public OperationResponse findSalesmanByLocation(OperationRequest functionRequest, ExtensionHelper extensionHelper) {
	List<EntityData> result = getEntityList();
	return OperationResponse.setSuccess().setEntityData(result).response();
}

private List<EntityData> getEntityList(){
	List<EntityData> anEntityList = new ArrayList<EntityData>();
		anEntityList.add(createEntity(12, "Dummy Name 1", -19.859451, -43.9456877, "Salesman"));
		anEntityList.add(createEntity(35, "Dummy Name 2", -19.859451, -43.9456877, "Salesman"));
		anEntityList.add(createEntity(49, "Dummy Name 3", -19.859451, -43.9456877, "Salesman"));

	return anEntityList;
}	
	
private EntityData createEntity(Integer entityId, String name, String entityType){
	EntityData anEntity = EntityData.getBuilder()
			.addKeyElement("ID", entityId)
			.addElement("name", name)
			.addElement("latitude", name)
			.addElement("longitude", name)
			.buildEntityData(entityType);
	return anEntity;
}

You code will be more easier to read and you also get the key element defined differently then the elements for each entity data.

Best regards,
Ivan

Hi Ivan, thanks by suggestion.