Give it a REST:  Utilizing the 3PL Central REST API to Optimize Your WMS

Date: May 23, 2018


My name is Shane Smith and I am the Director of Implementation and Support. I have been with 3PL Central for a couple exciting and high-growth years. Prior, I worked mostly in the enterprise business to business (B2B) space with many years focused primarily in security and middleware. Before moving to the dark side (management), I had various software engineer and architect roles. With 3PL Central’s REST API coming to life and the opportunity to “eat our own dogfood” to solve some internal challenges by dusting off the coding keyboard, the answer was “heck yeah”.

I’m not into holy wars, and my preferred coding language is Java and since a lot of what I am going to share is from my nights and weekends, the weekend clause applies - I get to use what I want to use.

So, Java it is. This blog is about utilizing the 3PL Central REST API via Java. If you want to program in something else, feel free to port anything you would like ;)

For our own 3PL Central’s internal uses, we often need to move large amounts of varying and dependent warehouse data from one source to another. The scope, so far, has included customers, items, and inventory data. We’ll start with this objective, at the beginning, and share some examples of how you can build and re-use some Java code for your own purposes.

For starters, and to set the stage, here is what I used for various stages of development. My personal endorsement is that all these work and my weekend clause applies to all:

  • System Environment/IDE
    • I use Java 1.8, Eclipse Oxygen, and program on Macintosh
  • JSON Test Clients / Tools / Libraries
    • When needing to validate and/or format JSON, I used the free online web version of JSON Formatter, located here
    • I use CocoaRestClient (available here
      • Fiddler is another popular option, is also available on Macintosh, and is available here
    • I experimented with a couple JSON libraries, and ultimately settled on using the package: org.json.simple (json-simple) for most of the JSON
      • There are many implementations (weekend clause)
      • Simple-json’s home page is located here
      • Simple-json’s external .jar is located here for download
      • Mkyong.com has a tremendous amount of samples of using this library that are exceedingly easy to follow and leverage. I highly recommend his site. Check him out here
  • 3PL Central’s REL and Web API documentation is located here
    • Not your typical does not apply disclaimer: consider this documentation beta from a developer’s standpoint. Also, note that these pages, as is the REST platform in general, are continuously changing (because they really are)

There are a number of REST API calls you are likely going to want to reuse. Because the scope of my project was in flux, I chose to create a static utility class to simplify and speed up development. I could always choose to come back and refactor the code if it made sense. Sound familiar?

For me, I like easy. So, first thing is writing a couple utility methods that I can refer to easily is a always a good place to start.

Step 1: In accordance with 3PL Central’s documentation, one is provided with a ClientId and a ClientSecret string to use in order to get a temporary access token to make further API calls with. These strings must be concatenated with a colon (“:”), and then encoded. We’ve come a long way since Java 1.1 and this is pretty easy. Here is a simple method, from my utility class, that returns the Base 64 UTF-8 encoded authorization string that is used to return a current access token for REST access to 3PL Central:

import java.util.Base64;

public static String getAuthorizationString(String inClientId, String inSecretKey) {
    String encodeMe = inClientId + ":" + inSecretKey;
    String encoded = Base64.getEncoder().withoutPadding().encodeToString(encodeMe.getBytes());

return encoded;
}

Step 2: We need to build the JSON payload (the information and details we are sending) in order to get a proper access token. We’ll absolutely get into utilizing the proper JSON library and doing this “right”, but for the sake of getting an example up and going quick, let’s go full on cheat-mode and go quick and dirty so we can get something working quick - it’s a super simple and static payload at this point afterall. Here’s a simple static method that builds the JSON goodness for us that is based on our 3PL GUI ID.

This method does the trick:

public static String getAccessTokenJSON(String inThreePLGuiId, String inUserLogin) {
    String returner = "";
    returner = "{\n" +
                 "\"grant_type\": \"client_credentials\",\n" +
                 "\"tpl\": \"" + inThreePLGuiId + "\",\n" +
                 "\"user_login_id\": \""+ inUserLogin"+\"\n" + "}";
    return returner;
}

IMPORTANT NOTE: Make sure to reference http://api.3plcentral.com/rels/auth for understanding and making the appropriate changes to the payload as it fits your specific needs – along with understanding the possible errors!

Step 3: Now, we are at the point where we can get our temporary access token that we use to make other REST API calls with. Here is an example of another utility method that is used to get a temporary access token using our authorization, URL (http://secure-wms.com/AuthServer/api/Token

), and our REST payload from Step 2:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.StringReader;

import java.net.HttpURLConnection;
import java.net.URL;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

public static String getAccessToken(String inUrl, String inAuthorizationToken,
                                                          String inThreePLGuiId, String inUserLogin) {

String replyMessage = "";
String returner = "";
try {

// CREATE THE URL CONNECTION
URL getAccessTokenUrl = new URL(inUrl);
HttpURLConnection conn = (HttpURLConnection) getAccessTokenUrl.openConnection();

// ESTABLISH THE URL CONNECTION AND PROPERTIES.
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Host", "secure-wms.com");
conn.setRequestProperty("Content-Type", "application/json; charset=utf-8");
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("User-Agent", "Fiddler");
conn.setRequestProperty("Authorization", "Basic " + inAuthorizationToken);
conn.setRequestProperty("Accept-Encoding", "gzip,deflate,sdch");
conn.setRequestProperty("Accept-Language", "en-US,en;q=0.8");
conn.setRequestProperty("Content-Length", "113");

// WRITE THE REQUEST TO THE HTTP CONNECTION
OutputStream os = conn.getOutputStream();
os.write(getAccessTokenJSON(inThreePLGuiId,inUserLogin).getBytes());
os.flush();

// READ THE REPLY STRING FROM THE SERVER
BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));

String output;
while((output = br.readLine()) != null) {
replyMessage += output + "\n";
}

// ***NOTE*** WE SHOULD CHECK FOR A SUCCESSFUL RETURN HERE AND ONLY
// CONDITIONALLY CONTINUE!!!

// CLOSE DOWN THE HTTP CONNECTION
conn.disconnect();

// USE THE JSONPARSER TO CREATE THE JSON OBJECTS TO
// RETRIEVE THE ACCESS CODE FROM
JSONParser parser = new JSONParser();
Object obj = parser.parse(new StringReader(replyMessage));

// GET THE ACCESS_TOKEN AND GET READY FOR RETURN
JSONObject jsonObject = (JSONObject) obj;
returner = (String) jsonObject.get("access_token");    

}
catch(Exception e) {
        e.printStackTrace();
}

// SINCE I WAS NAUGHTY AND DIDN’T CHECK THE RESPONSE, I OPTIMISTICALLY, RETURN
// THE ACCESS TOKEN AS A STRING
return returner;
}

Sample usage of this code may looking like this:

String authorization = getAuthorizationString(“MyClientId”, “MySecretKey”);
String accessToken = getAccessToken(“http://secure-wms.com/AuthServer/api/Token”, // TOKEN URL
                                                                authorization,                                                     // AUTH STRING
                                                               “{aba0000a-000a-00a0-a000-00000000abc0}”, // TPL GUID
                                                               “1”);                                                                    // USER ID

System.out.println(“Access token = “ + accessToken);

 So, this little bit of code is mighty powerful. We have created a method that encodes the authorization for us. Also, we have a single method that returns an access token to use later on in our application.

For my code, I made a lot of these variables customizable in a “preferences” dialog and stored them in a property file so they would be automatically passed for me. I STRONGLY SUGGEST also storing the access token for reuse somewhere to help both on the application’s performance and to lessen the number of API calls.

An access token is good for an indeterminate amount of time, but rule of thumb is about an hour. There are three ways of handling this in the code:

  1. Fetch a new access token when a REST call fails for authorization credentials
  2. Fetch a new access token after a determinate amount of time from the last fetch
  3. Fetch a new access token after a preset number of usages

For me, again, quick and dirty, I’m heavily utilizing the API to move a large amount of data, so from a rapid development standpoint, I used the least desirable and easiest, number 3. Getting a new token after 500-1000 calls worked out to be a small percentage and easily fit in the time boundaries for me.

It has to be said, that the unlisted option above, fetching a token for every single call is completely out of the question. This would be a perfect way to double your program’s execution time (or worse) and also unnecessarily load the host server with useless and unnecessary requests. This is “things that shouldn’t have to be said”, but coding something in this manner is equivalent to crawling a server and a good way to get your client access flagged, throttled, or even worse, banned. Don’t create and become a problem, don’t do it. #wordsofwisdom

Next, we will start building on these three methods, get in and using the JSON library, and start scratching the tip of the iceberg of all what one can do (an awful lot) with our REST API.

Obvious enhancements to work on and get familiar with are changing the payload from String to JSONObject in getAccessTokenJSON and refactoring it’s usage in the code. Reference Mkyong.com and the link listed above for great and straightforward examples of doing this and make sure you conform to JSON listed at 3PL Central here.

Another enhancement, is our getAccessToken method itself should check the connection’s response and handle a failed response accordingly by using the connection’s getResponse() method. Feel free to take a stab tidying up that code as well.


Shane Smith

Written by Shane Smith

Director of Implementation & Support Shane brings 20+ years of Customer Success and Software Engineering experience to 3PL Central from enterprise B2B Security, GovCon and Middleware industries. Before shifting his career to focus on customer’s success, Shane held numerous software developer and architect roles and was also an ICBM targeting and weather satellite programmer in the United States Air Force at Offutt AFB in Omaha, Nebraska.