Skip to Content
Technical Articles

Consuming SAP Cloud for Customer Data Workbench REST API from Java Applications

SAP Data Workbench (DWB) offers REST APIs that enable customers to import bulk data into SAP Cloud for Customer. It includes the following APIs:

  • DWB Authentication API
  • DWB Template API
  • DWB Import API

Purpose

Use the SAP Cloud for Customer Data Workbench (DWB) REST API, to import bulk data into SAP Cloud for Customer.

DWB REST API Documentation

This article walks through the techniques for consuming DWB REST API in Java applications.

Accessing the Authentication API

You can access the DWB Authentication API of your tenant, with the following URL pattern:

https://<your_C4C_tenant>/sap/c4c/dwb/singleusetoken/

Add the necessary code to invoke the DWB Authentication API using the user name & password. Consider wrapping the invocation to the DWB Authentication API in a try-catch block to capture any exceptions that are thrown by the authentication attempt.

The following example is applicable for Java 8.

Import Statements:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.apache.chemistry.opencmis.commons.impl.json.JSONObject;
import org.apache.chemistry.opencmis.commons.impl.json.parser.JSONParseException;
import org.apache.chemistry.opencmis.commons.impl.json.parser.JSONParser;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.IOUtils;
import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
import org.junit.Assert;

Initializing the REST Client:

HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic(username, password);
Client client = ClientBuilder.newClient();
client.register(feature);

Request Token:

private Token requestToken() {

		Token token = null;

		try {
			String tokenResponse = client
					.target("https://" + c4cTenantURL
							+ "/sap/c4c/dwb/singleusetoken/")
					.request(MediaType.APPLICATION_JSON).get()
					.readEntity(String.class);
			if (tokenResponse == null || tokenResponse.isEmpty()
					|| tokenResponse.startsWith("<html>")) {
				Assert.fail("Request Token Failed");
			}
			JSONObject tokenResponseJSON = (JSONObject) new JSONParser()
					.parse(tokenResponse);
			if (tokenResponseJSON == null) {
				Assert.fail("Request Token Failed");
			}
			String hostName = (String) tokenResponseJSON.get("HostName");
			String tokenString = (String) tokenResponseJSON.get("Token");
			if (hostName == null || hostName.isEmpty() || tokenString == null
					|| tokenString.isEmpty()) {
				Assert.fail("Request Token Failed");
			}
			token = new Token();
			token.setHostName(hostName);
			token.setToken(tokenString);
		} catch (JSONParseException e) {
			e.printStackTrace();
			Assert.fail(e.getMessage());
		}

		return token;
	}

Assuming that the authentication API succeeds, the resulting payload contains the DWB API service endpoint URL (HostName) and Token. Note that the Token expires after 30 seconds.

Accessing the Data Workbench Template API to download Template

The Template API is used to download the template file to prepare data for submitting via DWB API.

Request URL: <HostName>/api/v1/template?token=<token>&serviceName=<service_name>&entityName=<rootEntityName>&isCustom=false&type=1&operation=1

private boolean downloadTemplate(Token token,
			TemplateRequest templateRequest) {

		try {
			String url = token.getHostName() + "/api/v1/template?token="
					+ token.getToken() + "&serviceName="
					+ templateRequest.getServiceName() + "&entityName="
					+ templateRequest.getEntityName() + "&isCustom="
					+ templateRequest.isCustom() + "&type="
					+ templateRequest.getType() + "&operation="
					+ templateRequest.getOperation();

			Response response = client.target(url).request().get();

			if (response.getStatus() == 200) {
				try (final InputStream is = (InputStream) response.getEntity()) {
					File templateFile = new File("src/main/test/data/"
							+ templateRequest.getTemplateFileName());
					Files.copy(is, templateFile.toPath(),
							StandardCopyOption.REPLACE_EXISTING);
				}
			} else {
				Assert.fail("Error: " + Integer.toString(response.getStatus())
						+ " " + response.getStatusInfo());
			}
		} catch (Exception e) {
			e.printStackTrace();
			Assert.fail(e.getMessage());
		}

		return true;
	}

Accessing the Data Workbench REST API to Import Data

You can access the DWB API to Import Data, with the following URL pattern:

<HostName> + “/api/v1/import?token=” + <Token>

Add the necessary code to invoke the DWB API to Import Data using the HostName & Token. Consider wrapping the invocation to the DWB REST API in a try-catch block to capture any exceptions that are thrown by the data import attempt.

private String importData(Token token, Task task) {

		String taskName = null;

		try {
			File dataFile = new File(task.getDataFile());
			byte[] fileContent = IOUtils.toByteArray(new FileInputStream(
					dataFile));
			String data = new String(Base64.encodeBase64(fileContent, true),
					"UTF-8");
			String body = "<task>" + "<customService>"
					+ task.getCustomService() + "</customService>"
					+ "<dataFile>" + data + "</dataFile>"
					+ "<rootEntitySetName>" + task.getEntitySetName()
					+ "</rootEntitySetName>" + "<ignoreBlankValues>"
					+ task.isIgnoreBlankValues() + "</ignoreBlankValues>"
					+ "<initialLoad>" + task.isMigrationMode()
					+ "</initialLoad>" + "<operation>" + task.getOperation()
					+ "</operation>" + "<projectName>" + task.getProjectName()
					+ "</projectName>" + "<sequence>" + task.getSequence()
					+ "</sequence>" + "<serviceName>" + task.getServiceName()
					+ "</serviceName>" + "<simulation>" + task.isSimulation()
					+ "</simulation>" + "<taskType>" + task.getTaskType()
					+ "</taskType>" + "<errorThreshold>" + task.getThreshold()
					+ "</errorThreshold>" + "<lastTask>" + task.isLastTask()
					+ "</lastTask>" + "</task>";

			String url = token.getHostName() + "/api/v1/import?token="
					+ token.getToken();

			Response dwbAPIResponse = client
					.target(url)
					.request(MediaType.APPLICATION_JSON)
					.post(Entity.entity(body, MediaType.APPLICATION_XML),
							Response.class);

			if (dwbAPIResponse.getStatus() == 200) {
				JSONObject dwbAPIResponseJSON = null;
				dwbAPIResponseJSON = (JSONObject) new JSONParser()
						.parse(dwbAPIResponse.readEntity(String.class));
				taskName = (String) dwbAPIResponseJSON.get("taskName");
			} else {
				Assert.fail("Error: "
						+ Integer.toString(dwbAPIResponse.getStatus()) + " "
						+ dwbAPIResponse.getStatusInfo());
			}
		} catch (JSONParseException e) {
			e.printStackTrace();
			Assert.fail(e.getMessage());
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			Assert.fail(e.getMessage());
		} catch (IOException e) {
			e.printStackTrace();
			Assert.fail(e.getMessage());
		}

		return taskName;
	}

Sample POST Request XML Body:

Multiple DWB import tasks can be created for a single project, by invoking the DWB REST API in a loop.

		Project dwbProject = prepareData();
		for (Task task : dwbProject.getTasks()) {
			Token token = this.requestToken();
			Assert.assertNotNull(token);
			String taskName = this.importData(token, task);
			Assert.assertNotNull(taskName);
		}

For reference, Class Project, Task, Token & TemplateRequest:

public class Project {

	private String name;
	private List<Task> tasks = new ArrayList<Task>();

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public List<Task> getTasks() {
		return tasks;
	}

	public void addTask(Task task) {
		this.tasks.add(task);
	}

}
public class Task {

	private String serviceName;
	private boolean customService;
	private String dataFile;
	private String entitySetName;
	private boolean ignoreBlankValues;
	private boolean migrationMode;
	private int operation;
	private int sequence;
	private boolean simulation;
	private int taskType;
	private int threshold;
	private boolean lastTask;
	private String projectName;

	public String getProjectName() {
		return projectName;
	}

	public void setProjectName(String projectName) {
		this.projectName = projectName;
	}

	public String getServiceName() {
		return serviceName;
	}

	public void setServiceName(String serviceName) {
		this.serviceName = serviceName;
	}

	public boolean getCustomService() {
		return customService;
	}

	public void setCustomService(boolean customService) {
		this.customService = customService;
	}

	public String getDataFile() {
		return dataFile;
	}

	public void setDataFile(String dataFile) {
		this.dataFile = dataFile;
	}

	public String getEntitySetName() {
		return entitySetName;
	}

	public void setEntitySetName(String entitySetName) {
		this.entitySetName = entitySetName;
	}

	public boolean isIgnoreBlankValues() {
		return ignoreBlankValues;
	}

	public void setIgnoreBlankValues(boolean ignoreBlankValues) {
		this.ignoreBlankValues = ignoreBlankValues;
	}

	public boolean isMigrationMode() {
		return migrationMode;
	}

	public void setMigrationMode(boolean migrationMode) {
		this.migrationMode = migrationMode;
	}

	public int getOperation() {
		return operation;
	}

	public void setOperation(int operation) {
		this.operation = operation;
	}

	public int getSequence() {
		return sequence;
	}

	public void setSequence(int sequence) {
		this.sequence = sequence;
	}

	public boolean isSimulation() {
		return simulation;
	}

	public void setSimulation(boolean simulation) {
		this.simulation = simulation;
	}

	public int getTaskType() {
		return taskType;
	}

	public void setTaskType(int taskType) {
		this.taskType = taskType;
	}

	public int getThreshold() {
		return threshold;
	}

	public void setThreshold(int threshold) {
		this.threshold = threshold;
	}

	public boolean isLastTask() {
		return lastTask;
	}

	public void setLastTask(boolean lastTask) {
		this.lastTask = lastTask;
	}

}
public class Token {

	private String token;
	private String hostName;

	public String getToken() {
		return token;
	}

	public void setToken(String token) {
		this.token = token;
	}

	public String getHostName() {
		return hostName;
	}

	public void setHostName(String hostName) {
		this.hostName = hostName;
	}

}
public class TemplateRequest {

	private String serviceName;
	private String entityName;
	private boolean isCustom;
	private int type;
	private int operation;
	private String templateFileName;

	public String getTemplateFileName() {
		return templateFileName;
	}

	public void setTemplateFileName(String templateFileName) {
		this.templateFileName = templateFileName;
	}

	public String getServiceName() {
		return serviceName;
	}

	public void setServiceName(String serviceName) {
		this.serviceName = serviceName;
	}

	public String getEntityName() {
		return entityName;
	}

	public void setEntityName(String entityName) {
		this.entityName = entityName;
	}

	public boolean isCustom() {
		return isCustom;
	}

	public void setCustom(boolean isCustom) {
		this.isCustom = isCustom;
	}

	public int getType() {
		return type;
	}

	public void setType(int type) {
		this.type = type;
	}

	public int getOperation() {
		return operation;
	}

	public void setOperation(int operation) {
		this.operation = operation;
	}

}

Assuming that the DWB REST API succeeds, the resulting payload contains the DWB Task Name for the submitted data file.

Monitoring Data Workbench Project/Tasks submitted using the DWB REST API

Logon to SAP Cloud for Customer front-end and navigate to Data Workbench Monitor work center view to monitor the submitted tasks for a project:

The submitted DWB task can also be monitored using the following OData endpoint:

https://<Your_C4C_Tenant>/sap/c4c/odata/v1/dwbmonitor/ScenarioCollection?$filter=ScenarioName%20eq%20%27<Task_Name>%27

Note: Your C4C Tenant username and password is required to Sign In to this endpoint.

Tips & Tricks

  1. The DWB API REST calls should be made sequentially for a project.
  2. A new token should be fetched for each call to the DWB REST API; Token expires after 30 seconds.
  3. The last task of the project must be indicated  by <lastTask>true</lastTask>, as the last call to the DWB REST API for that project.
  4. Submitted tasks for a project are processed in DWB only when the last task is submitted using the DWB REST API.

Summary

  • Use the DWB Authentication API to fetch token, and the DWB Import API endpoint
  • Use the DWB Template API to download the template for an object, and prepare data using the template
  • Using DWB Import API, create mass data into SAP Cloud for Customer
1 Comment
You must be Logged on to comment or reply to a post.