Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
Former Member
Using the incredibly useful post by Jannis Rondorf as a starting point, I wanted to write this blog post to show how IdM could access a REST API / WebService (HTTP & HTTPS) only using JAVA & JavaScript (without any custom JAVA classes or VDS); the following script should be pretty self-explanatory for the most part, but comments should hopefully make things a little clearer; please feel free to comment if you have any further doubts / questions and I will do my best to answer them:
// Main function:pushDataToAPI

function pushDataToAPI(Par) {
importClass(Packages.java.net.HttpURLConnection);
importClass(Packages.java.net.URL);
importClass(Packages.java.io.DataOutputStream);
importClass(Packages.java.io.ByteArrayOutputStream);

var targetAPI = Par.get("TARGET_SYSTEM");
var APIintent = "";

var systemA_URL = "http://systemAHostNAME:1234/api/user";

var systemD_CreateURL = "http://systemDHostName:1234/system_API/systemapi.svc/rest/createUser";
var systemD_UpdateURL = "http://systemDHostName:1234/system_API/systemapi.svc/rest/updateUser";
var systemD_Username = "systemDAPIUser";
var systemD_Password = "systemD@APIUser1234";
var systemD_Encoding = uToBase64(systemD_Username + ":" + systemD_Password); //encode the system D user credentials into Base64
var systemA_Username = "systemARestAPIUser";
var systemA_Password = "systemA@RestAPIUser1234";
var systemA_Encoding = uToBase64(systemA_Username + ":" + systemA_Password); //encode the system A user credentials into Base64

var logFileText = "";

var urlString = "";


//determine target URL based on passed in TARGET_SYSTEM parameter
//with System D, there are two separate URLs for User CREATION and User UPDATING
if (targetAPI == "systemA")
urlString = systemA_URL;
else if (targetAPI == "systemD") {
APIintent = Par.get("API_intent");
if (APIintent == "Create") {
uWarning("In System D section now, going to hit CREATE API: ");
urlString = systemD_CreateURL;
} else if (APIintent == "Update") {
uWarning("In System D section now, going to hit UPDATE API: ");
urlString = systemD_UpdateURL;
}
}

uWarning("FOR THIS API system: " + targetAPI);
uWarning("determined URL: ");
uWarning(urlString);


//get the necessary attributes from the entry being processed currently

var currentEntry = uGetEntryID();
var allAttrs = uIS_GetEntry(currentEntry);
var entFName = allAttrs.get("MX_FIRSTNAME");
var entLName = allAttrs.get("MX_LASTNAME");
var entUsername = allAttrs.get("MSKEYVALUE");
var entServiceType = allAttrs.get("MX_FS_PERSONNEL_AREA");
var entPayrollNo = allAttrs.get("MX_FS_PERSONNEL_NUMBER");
var entEmail = allAttrs.get("MX_MAIL_PRIMARY");
var entPhone = allAttrs.get("MX_PHONE_PRIMARY");
var entMobile = allAttrs.get("MX_MOBILE_PRIMARY");
var entDepartment = allAttrs.get("MX_DEPARTMENT");
var entPrivCode = allAttrs.get("MX_FS_JOB_ID");
var entEmpStatus = allAttrs.get("MX_FS_EMPLOYMENT_STATUS_ID");
var entAdocode = allAttrs.get("MX_FS_ORGANIZATIONAL_UNIT_ID");
var entOrgID = allAttrs.get("MX_DEPARTMENT");
var entAccountingCode = allAttrs.get("MX_ACCOUNTING_NUMBER");


//set up the message data based on the specific system; system A in this case accepts XML data via its API, while system D accepts JSON data.
var systemA_ObjData = '<UserDataFeed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="SystemA.API.Integration">\n<FirstName>' + entFName + '</FirstName>\n<LastName>' + entLName + '</LastName>\n<EmploymentTypeID>' + entServiceType + '</EmploymentTypeID>\n<StaffNumber>' + entPayrollNo + '</StaffNumber>\n<Adocode>' + entAdocode + '</Adocode>\n<UnitID>' + entOrgID + '</UnitID>\n<Workemail>' + entEmail + '</Workemail>\n<MilitaryTelephone>' + entPhone + '</MilitaryTelephone>\n<MobileTelephone>' + entMobile + '</MobileTelephone>\n<Username>' + entEmail + '</Username>\n<UserStatusID>' + entEmpStatus + '</UserStatusID>\n<UserType>' + entPrivCode + '</UserType>\n<Position>' + entDepartment + '</Position>\n<Employer>IDMEmployer</Employer>\n<BudgetCode>' + entAccountingCode + '</BudgetCode>\n</UserDataFeed>';

var systemD_ObjData = '{"emailAddress" : "' + entEmail + '","firstName" : "' + entFName + '","lastName" : "' + entLName + '","customerIdentifier" : "' + entAdocode + '","roleIdentifier" : "' + entPrivCode + '"}';


var objWithVars = '';

//determine data to be sent to target system
if (targetAPI == "systemA")
objWithVars = systemA_ObjData;
else if (targetAPI == "systemD")
objWithVars = systemD_ObjData;

uWarning("determined obj data: ");
uWarning(objWithVars);

//convert data to be sent into ByteArray
var bytesObj = new ByteArrayOutputStream();
bytesObj.reset();
for (var i = 0; i < objWithVars.length; ++i) {
bytesObj.write(objWithVars.charCodeAt(i));
}

var url = new URL(urlString); //create new URL based on selected target system

var writeConn;

writeConn = url.openConnection(); //open an HTTP connection using the selected URL

writeConn.setDoOutput(true); //set output flag for HTTP connection to be true
writeConn.setDoInput(true); //set input flag for HTTP connection to be true

var verb = "POST";

//based on selected target system, select the HTTP VERB; in this case it is either PUT if System D has to be updated, or POST for any other scenario
if (targetAPI == "systemD" && APIintent == "Update") {
verb = "PUT";
writeConn.setRequestMethod(verb);
} else if (targetAPI == "systemA" || (targetAPI == "systemD" && APIintent == "Create")) {
verb = "POST";
writeConn.setRequestMethod(verb);
}

//set up the authorization header for based on the selected target system; this section can be skipped if using an REST / WebService endpoint,
//that does not require authentication
if (targetAPI == "systemD") {
writeConn.setRequestProperty("Authorization", "Basic " + systemD_Encoding);
} else if (targetAPI == "systemA") {
writeConn.setRequestProperty("Authorization", "Basic " + systemA_Encoding);
}

//set up the content-type header based on the selected target system
if (targetAPI == "systemD") {
writeConn.setRequestProperty("Content-Type", "application/json");
} else {
writeConn.setRequestProperty("Content-Type", "application/xml");
}

uWarning("set request method and content type! Going to push data to API now!");

//initiate a connection to the selected target system and then write the composed data to that system
//response messages are then logged once the
try {
writeConn.connect();
var dataOS = new DataOutputStream(writeConn.getOutputStream());
dataOS.write(bytesObj.toByteArray(), 0, bytesObj.size());
dataOS.flush();
dataOS.close();
} catch (idmerr) {
uWarning("Encountered error while trying to push data to API: ");
uWarning(idmerr);
uWarning(idmerr.message);
uSkip(1);
}

var responseCode = writeConn.getResponseCode();
var responseMsg = writeConn.getResponseMessage();

uWarning("Response MSG for the " + verb + ": " + responseMsg);
uWarning("Response CODE for the " + verb + ": " + responseCode);
uWarning("Header FIELD 0 for the " + verb + ": " + writeConn.getHeaderField(0));


//if a response code other than 200 or 201 is encountered, that means an error has occurred and this will then be written to an external log file
//if logging to a file is not required this section can be removed.
if (writeConn.getResponseCode() !== 200 && writeConn.getResponseCode() !== 201) {
logFileText += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r\n";
logFileText += "For SYSTEM " + targetAPI + "\r\n";
logFileText += "hitting API URL: " + urlString + "\r\n";
logFileText += "with this payload:\n " + objWithVars + "\r\n";
logFileText += "*************************************\r\n";
logFileText += "THIS IS THE Header FIELD 0:\n " + writeConn.getHeaderField(0) + "\r\n";
logFileText += "THIS IS THE RESULT CODE:\n " + writeConn.getResponseCode() + "\r\n";
logFileText += "THIS IS THE RESULT MESSAGE:\n " + writeConn.getResponseMessage() + "\r\n";
logFileText += "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\r\n";
uToFile("C:\\IDM_ErrorFile.txt", logFileText, true);
}

//finally disconnect the HTTP connection after the data has been pushed to the REST API / WebService
writeConn.disconnect();

}

NOTE: HTTP & HTTPS connections can both be accessed using the HTTPUrlConnection JAVA Class; in the case of an HTTPS API, you will need to import the SSL certificate of the secured target API web server, into the JAVA Keystore (following the IDM documentation:Exporting and Installing the SSL Certificate - SAP Identity Management Installation and Update Guide...); if the SSL certificate is not imported you will encounter an SSL handshake error, when trying to access the secured HTTPS REST API / WebService.

Using similar logic / concepts you can retrieve data from a REST API / WebService instead of pushing data to it (as demonstrated in the above example).

I hope this helps give you a better understanding of how you can access a REST API directly from SAP IDM, simply using JAVA / JavaScript, as well as the different use cases this can be applied to.
2 Comments
Labels in this area