Presentation is loading. Please wait.

Presentation is loading. Please wait.

JSON Web Service – Tips & Examples

Similar presentations


Presentation on theme: "JSON Web Service – Tips & Examples"— Presentation transcript:

1 JSON Web Service – Tips & Examples
Core SDK Training: JSON Web Service – Tips & Examples Welcome to CORE SDK Training. This is the last lesson about the JSON Web Service. If you have not already done so, you should complete the JSON Web Service Introduction lesson and the SDK Commands lesson prior to starting this section. Once you have a solid understanding of how to access the code templates using the REST tool and how to interact with the key SDK commands, you can get some tips and examples on how to incorporate these code templates into your own custom applications in this lesson.

2 Course Topics Firing Triggers With the Web Service Best Practice Tips
Code Examples This lesson will tie up some final loose ends on how to work with triggers, offer best practice tips, and provide some code examples for your reference. CONFIDENTIAL

3 Executing Triggers The SDK automatically adds the EXECUTE_TRIGGERS command to all create, update, publish, and unpublish commands in the JSON template (look in the logicOptions section) If there is a trigger set on an entity type (like a sample, lot, or experiment) the SDK will fire the trigger when a command is submitted if the EXECUTE_TRIGGERS command is left in the template There will not be any special messages in the JSON response to indicate whether a trigger has been fired The update-experiment-containers command will always fire triggers even without the EXECUTE_TRIGGERS command The update-experiment-sample-data command will need to fire any triggers manually (use trigger-execute command) You can use the trigger-execute command at any time to fire any triggers manually Executing triggers from within the JSON web service is slightly different from executing triggers when actions are performed within the standard LIMS user interface. Let's take a look at some of the key Trigger concepts as they relate to the execution in the JSON web service. The triggers will need to be configured ahead of time using the standard user interface. Trigger configuration is covered in a separate lesson. First, in general, the web service offers more flexibility to control whether or not a trigger is executed. The REST Tool will automatically add the EXECUTE_TRIGGERS command to all create, update, publish, and unpublish commmands in the JSON template. This will be located in the logicOptions section. (show code example screen shot) If there is a trigger set on an entity type (like a sample, lot, or experiment) the SDK will fire the trigger when a command is submitted if the EXECUTE_TRIGGERS command is left in the template. Generally, you can remove the EXECUTE_TRIGGERS command if desired to prevent a trigger from firing. Just like the user interface, there will not be any special message in the JSON response to indicate whether a trigger has been fired or successfully executed. You will need to check the record the trigger is acting upon to verify if the trigger was executed as expected. There are a couple exceptions to the general rule that the EXECUTE_TRIGGERS command will control when triggers will be fired. One exception is the update-experiment-containers command will always fire any active triggers configured for the entity type even without the EXECUTE_TRIGGERS command listed in the logic options section. A second exception to the EXECUTE_TRIGGERS rule is the update-experiment-sample-data command will never fire directly from the request on the entity type. You will need to fire any active triggers manually using the trigger-execute command. You can use the trigger-execute command at any time to fire any triggers manually. Let's continue on to see how to fire a trigger manually using the REST tool. CONFIDENTIAL

4 Firing a Trigger Manually
Select * for Super Type, * for Entity Type, and the trigger-execute command Load the JSON Template Modify the trigger Action Types in the Request box if needed Enter the object that the trigger will be fired upon (remember the entity type needs to have a trigger configured on it in the LIMS) Submit button will execute the trigger In addition to submitting a request command to the web service, you also have the ability to just execute a trigger directly, without employing other web service commands. This may be helpful if you need to use the Update-Experiment-Sample-Data command or if you want to test that a trigger is truly working. Before we do that, let’s take a quick look at an example message trigger that should be sent when a Supplier Record is updated. Remember that the Trigger needs to be configured ahead of time. On the Suppliers trigger page, we can see the message trigger has already been added in the Existing Triggers section. If we wanted to fire the trigger during the update of a supplier record, we can enter the barcode for the supplier record we want to update, load the update template for the Supplier entity type, modify the record and submit the request. In the template, you should see the EXECUTE_TRIGGERS command in the Logic options section. When we submit the request to the database, the recipients that were configured in the message record should receive the (show screen shot). Now if we wanted to test this trigger without updating the supplier, we can also fire it manually in the REST Tool. In the list of Super Types, there is an asterisk at the bottom of the list. Select the * for the Super Type and an * for the Entity Type. This will give you a list of commands. The only command that you will ever need to use in this list is the trigger-execute option which is the command to fire a trigger manually. Finally, select the Load JSON Template button to load the request template. Modify the trigger Action Types in the request box if needed. In this case we will use the ON_UPDATE option that is there by default. Please check the trigger documentation for a list of the available action types that you can use. Enter the object that the trigger will be fired upon. For this example we will enter the Supplier barcode in the entity refs section. This trigger-execute template will not have any knowledge of the values that are currently in the record that you are firing the trigger on. Remember, the web service can only manually fire triggers for objects that have triggers previously configured. Finally, click on the Submit button to execute the trigger. You can see a success message in the response, but there will not be any direct messages in the response to tell us the trigger was fired. The recipients that were configured in the message record should receive the . CONFIDENTIAL

5 (JSON Request & Response)
Trigger Execute (JSON Request & Response) Execute Request Execute Response { "request": { "data": { "triggerActionTypes": [ "ON_EXPT_DATA_UPDATE" ], "entityRef": { "name": "", "entityId": "", "barcode": "XXY29" }, "triggerParams": {} "typeParam": "*", "sdkCmd": "trigger-execute" } { "data": {}, "success": true, "messages": [ "messageCodeString": "SDK_CONFIG_OPTION", "messageLevel": "INFO", "messageDetail": "[No logicOptions set]" }, "messageDetail": "[No responseOptions set]" "messageCodeString": "TRANSACTION_COMPLETED", "messageDetail": "[]" } ] This is an example request and response for firing a trigger manually using the REST tool. CONFIDENTIAL

6 Trigger Summary Super Type SDK Command Trigger Context SDK Behavior EXPERIMENT experiment-unpublish EXPERIMENT.ON_UNPUBLISH requires EXECUTE_TRIGGERS in logicOptions experiment-publish EXPERIMENT.ON_PUBLISH update-experiment-containers EXPERIMENT SAMPLE.ON_CREATE, EXPERIMENT.ON_EXPT_CONTAINER_UPDATE always fires regardless of logicOptions EXPERIMENT SAMPLE create EXPERIMENT SAMPLE.ON_CREATE update EXPERIMENT SAMPLE.ON_UPDATE update-experiment-sample-data EXPERIMENT.ON_EXPT_DATA_UPDATE will not fire even if included in logicOptions. requires additional sdk call to trigger-execute Any Super Type ENTITY.ON_CREATE ENTITY.ON_UPDATE For your reference, here is a Trigger Summary Table indicating the Super Type, SDK Command, Trigger Context and SDK Behavior to explain how what settings are needed to fire triggers within the web service for common use cases. Please refer to the documentation for further information. CONFIDENTIAL

7 Example Workflow Now that we have a better understanding of how to work with triggers, let’s move on to look at the best practices recommended by Core Informatics for building robust integrations on top of the API's discussed. In the previous lesson we learned about some of the key SDK commands and how they worked. In practice, the application you build will probably need to string several of these commands together in order to support your specific business process. This slide shows a common example workflow that includes sample registration and publishing results from an experiment. Here, you can see which web service templates you will need to work with to build an application that follows this workflow. The sample must be initially created and then the sample lot is created in a separate call. If you want to place that lot within a container, you will then need to create the container record and use the update-cell command to fill the container. If you are filling a multiple well container this command will need to be called for each container cell. To test your sample lots, you will need to create an experiment record. You can then use the update-experiment-containers command to associate the appropriate containers to your experiment. This will automatically create the experiment sample records on the back end. The experiment data can then be added with the update-experiment-sample-data command. Finally, the experiment can be published. Your specific business process may be slightly different, but is likely to include at least some of these elements. CONFIDENTIAL

8 Session Management General Workflow is: Log In
# POST to http/ { "request": { "data": { "lims_userName": "lims“, "lims_password": “*****", }, "typeParam": "*", "sdkCmd": "sdk-login" } General Workflow is: Log In Execute Business Logic (1 or more calls) Log Out For best performance, do NOT log in and out for every call #POST to http/ # POST to http/ { "request": { "data": {}, "typeParam": "*", "sdkCmd": "sdk-logout" } Let’s take a quick look at managing sessions. When working with any API the basic workflow for any interaction should begin with a login session, then follow with executing all business logic needed to perform the operation. This can be done in one or many calls, depending on the operation needed. Finally, the session will conclude with logging out of the session. For the best performance, it is NOT recommended to log into a new session for each call. CONFIDENTIAL

9 Cookie Management PFS will attempt to utilize cookies; however, not all languages support automatic capturing of cookies If cookies are not supported, you can add the JSessionID parameter to the URL http/ http/ _id> If you are a PFS cloud customer, you will need to add the AWSELB (load-balancing) cookie with the JSessionID Now let’s add a few notes about how to manage cookies. Sessions are tracked using cookies within the Platform For Science. The PFS will attempt to utilize these cookies, however, not all programming languages support automatic capturing of cookies and supplying them back to the server when needed. In the case where cookies are not supported, you can add the following JSessionID URL parameter to the URL as an alternate way to maintain a session. http/ http/ This value should be appended to the URL for all subsequent POSTS to the system, including the logout call. If you are a PFS cloud customer, the Amazon Web Services are implementing elastic load balancing (ELB). For this, you will additionally need to send the AWSELB cookie in addition to the JSessionID with each request. Any request received without an AWSELB cookie will be routed using ELB's standard algorithm of "approximate-least-connections." CONFIDENTIAL

10 Transaction Management
Optimistic Locking (Lite) Strategy Add a very specific timestamp attribute to the entity in question Add trigger to populate time when entity is updated Use this attribute to evaluate whether another process has updated the record Merge your new changes and update the entity Single-Threaded Updates to Shared Data If it is not possible to use the Optimistic Locking Strategy, use a single process to update entities Now let’s talk a bit about transaction management. Every call to PFS is an individual transaction. Unlike other relationship database management systems, PFS does not currently support transaction rollbacks across multiple calls. It does support rollbacks for individual creates and updates. Due to this behavior of the transactions, it is possible that your data may become inconsistent with the real world. Following are Transaction Management strategies to mitigate the scenarios that can produce inconsistent data. Optimistic Locking or Lite locking is an option that, although not currently supported, allows a developer to build an optimistic locking option within their LIMS. To do this, first, add a very specific timestamp attribute to the entity in question. Add a trigger to populate the time whenever the entity is updated. Then, use this attribute to evaluate whether another process has updated the record. Merge your new changes and update the entity. This strategy is NOT foolproof, however, thus the term 'Lite'. If it is not possible to use the Optimistic Locking option, you can use a Single-Threaded process to update entities. It is best to affect changes to individual entities via a single process. CONFIDENTIAL

11 Common API Messages Category Message Code Interpretation Resolution Authentication SDK_LOGIN_FAILED User name or password is incorrect Ensure the number of transactions per minute does not exceed maximum allowed SDK_TRANSACTION_LIMIT Attempted to create more transactions then allowed per minute.  This value is calculated by the number of API sessions allowed multiplied by 30 MAX_SESSIONS Error can occur if a login attempt by the client causes the current number of sessions to exceed the number of concurrent sessions purchased Reduce the number of active sessions Configuration ENTITY_TYPE_NOT_FOUND Entity type reference could not be resolved to an existing entity type Check the correct entity type name or id is being passed in.  Make sure the user is authorized to view that entity type. SUPER_TYPE_NOT_FOUND Super type reference could not be resolved to an existing super type Check the correct super type name is being passed in.  Make sure the user is authorized to view that super type. ATTRIBUTE_NOT_FOUND Attribute reference could not be resolved to an existing attribute The attribute name being passed in should be uppercase with non-alpha numeric characters replaced by underscore (_) Here is a table for your reference that list some common error messages that you might get as a database response(in the Message Code column), what those error messages mean (in the Interpretation column), and what you should do to fix the problem (in the Resolution column). A more comprehensive list is available in the documentation. CONFIDENTIAL

12 Common API Messages Cont.
Category Message Code Interpretation Resolution Container CELL_NOT_FOUND Cell reference could not be resolved to an existing cell A cell can be retrieved by cellId or containerReference and wellNum or by containerReference alone if it is a single well container. UNIT_INVALID Invalid unit (for amount or concentration) that is not supported by the LIMS. Modify unit to a valid unit supported by the LIMS. Convert amount or concentration values as appropriate to maintain data accuracy. Entity NAME_EXISTS Name already exists in the system Supply a unique name or leave empty so a unique name can be supplied by the LIMS. It may also be a good idea to check the existing record to make sure that the new record is not a duplicate of an existing one. ASSOCIATION_MANDATORY Error during create/update of an entity because required association was not supplied Supply value for mandatory association or modify configuration to not require association General PARAMETER_MISSING Occurs if the request being sent is missing a parameter that is required to fulfill the request Add the missing parameter.  Use the /coresdk/tools.html page (REST Tool) to inspect the template and gain information on required parameters. Here are more examples for reference. See On Line Documentation for comprehensive table CONFIDENTIAL

13 URL Encoding The REST tool automatically calls a encodeURIComponent function prior to posting. It is recommended best practice that you URL encode any string values in the JSON payload prior to building the POST. This will ensure proper data transmission and storage by making the data more HTTP friendly. For example: John’s Car = John%27s+Car The REST tool automatically calls a encodeURIComponent function prior to posting. It is recommended best practice that you URL encode any string values in the JSON payload prior to building the POST. This will ensure proper data transmission and storage by making the data more HTTP friendly. For example, John's Car would encode as the following: John%27s+Car CONFIDENTIAL

14 JSON Templates for Log In
Request Response { "request": { "data": { "lims_userName": "lims“, "lims_password": “*****", }, "typeParam": "*", "sdkCmd": "sdk-login" } { "response": { "data": { "employeeId": " ", "jsessionid": "189BD7A3F92A FE7BF " }, "success": true, "messages": [] } Now that you have some general ideas about recommended best practices, you will need to incorporate the JSON code templates you modelled into your own application code. Here are a few code examples for you to get started for your reference. The first few examples are in Java and there are some HTML examples at the end. Feel free to skip to the language that you will be working with. Let’s start by looking at an example JSON template for logging into the LIMS that would come out of the REST Tool. CONFIDENTIAL

15 Java Example – Log In String urlStr = appDir + "/sdklogin/"; URL url = new URL(urlStr); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setAllowUserInteraction(false); conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); JSONObject requestForm = new JSONObject(); JSONObject data = new JSONObject(); data.put("lims_userName", "lims"); data.put("lims_password", “******"); requestForm.put("typeParam", "*"); requestForm.put("sdkCmd", "sdk-login"); requestForm.put("data", data); JSONObject mainRequestObj = new JSONObject(); mainRequestObj.put("request", requestForm); String json = mainRequestObj.toString(); // Create the form content OutputStream out = conn.getOutputStream(); Writer writer = new OutputStreamWriter(out, "UTF-8"); writer.write("json"); writer.write("="); writer.write(URLEncoder.encode(json, "UTF-8")); writer.close(); out.close(); if (conn.getResponseCode() != 200) { throw new IOException(conn.getResponseMessage()); } // Buffer the result into a string BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder sb = new StringBuilder(); String line; while ((line = rd.readLine()) != null) { sb.append(line); rd.close(); conn.disconnect(); String JSONResponseString = sb.toString(); System.out.println("******************* LOGIN"); System.out.println(JSONResponseString); Here is how you would incorporate that login template using Java. CONFIDENTIAL

16 Pull JSessionID From Response
Java Example: Pull JSessionID From Response JSONObject serverResponseJSON = new JSONObject(JSONResponseString); JSONObject responseJSON = serverResponseJSON.getJSONObject("response"); String success = responseJSON.getString("success"); JSONObject responseDataJSON = responseJSON.getJSONObject("data"); String JSESSIONID = responseDataJSON.getString("jsessionid"); JSESSIONID = URLEncoder.encode(JSESSIONID, "UTF-8"); Here is a Java Example to Pull a JSessionID from a Response. CONFIDENTIAL

17 JSON Templates for Get Request Response cont. "associations": { "CAR_TIRE": [ { "entityTypeName": "TIRE", "entityId": , "barcode": "TRE1" } ], "CAR_ENGINE": [ "entityTypeName": "ENGINE", "entityId": , "barcode": "ENG1" }, "entityId": , "barcode": "ENG2" ] "success": true, "messages": [ "messageCodeString":TRANSACTION_COMITTED", "messageLevel": "INFO", "messageDetail": "[]" { "request": { "data": { "entityTypeName": "CAR", "barcode": "CAR1" }, "typeParam": "CAR", "sdkCmd": "get" } Response { "response": { "data": { "entityId": , "name": "CAR1", "barcode": "CAR1", "values": { "CI_CAR_COLOR": { "id": , "stringData": "Blue", "attributeId": } }, This shows an example of a JSON Template for the Get command. It is looking up a generic car entity. CONFIDENTIAL

18 Java Example – Get JSONObject requestObject = new JSONObject(); JSONObject getCall = new JSONObject(); getCall.put("sdkCmd","get"); getCall.put("typeParam","CAR"); JSONObject dataObject = new JSONObject(); dataObject.put("barcode","CAR1"); dataObject.put("entityTypeName","CAR"); // package it all up: getCall.put("data", dataObject); requestObject.put("request",getCall); String requestJSONString = requestObject.toString(); System.out.println("******************* Sending this JSON to the sdk servlet:"); System.out.println(requestJSONString); urlStr = appDir + "/sdk/;jsessionid="+JSESSIONID; url = new URL(urlStr); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setAllowUserInteraction(false); conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); // Create the form content out = conn.getOutputStream(); writer = new OutputStreamWriter(out, "UTF-8"); writer.write("json"); writer.write("="); writer.write(URLEncoder.encode(requestJSONString, "UTF-8")); writer.close(); out.close(); if (conn.getResponseCode() != 200) { throw new IOException(conn.getResponseMessage()); } // Buffer the result into a string rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); sb = new StringBuilder(); while ((line = rd.readLine()) != null) { sb.append(line); rd.close(); conn.disconnect(); JSONResponseString = sb.toString(); System.out.println(JSONResponseString); This shows how the Get template would be written in Java. CONFIDENTIAL

19 JSON Templates for Log Out
Request Response { "request": { "data": {}, "typeParam": "*", "sdkCmd": "sdk-logout" } { "response": { "data": { "key": "value" }, "success": true, "messages": [ "messageCodeString": "SDK_LOGIN", "messageLevel": "INFO", "messageDetail": "[You have logged out of your session...]" } ] This shows an example of a JSON Template for the Log Out command that would come from the REST Tool. CONFIDENTIAL

20 Java Example – Log Out // Create the Json object representing the request for a get: JSONObject logoutObject = new JSONObject(); JSONObject logoutCall = new JSONObject(); logoutCall.put("sdkCmd","sdk-logout"); logoutCall.put("typeParam","*"); JSONObject myDataObject = new JSONObject(); // package it all up: logoutCall.put("data", myDataObject); logoutObject.put("request", logoutCall); String logoutRequestJSONString = logoutObject.toString(); System.out.println("Sending this JSON to the sdk servlet:"); System.out.println(logoutRequestJSONString); urlStr = appDir + "/sdklogin/;jsessionid="+JSESSIONID; url = new URL(urlStr); conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); conn.setDoInput(true); conn.setUseCaches(false); conn.setAllowUserInteraction(false); conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); // Create the form content out = conn.getOutputStream(); writer = new OutputStreamWriter(out, "UTF-8"); writer.write("json"); writer.write("="); writer.write(URLEncoder.encode(logoutRequestJSONString, "UTF-8")); writer.close(); out.close(); if (conn.getResponseCode() != 200) { throw new IOException(conn.getResponseMessage()); } // Buffer the result into a string rd = new BufferedReader(new InputStreamReader(conn.getInputStream())); sb = new StringBuilder(); while ((line = rd.readLine()) != null) { sb.append(line); rd.close(); conn.disconnect(); JSONResponseString = sb.toString(); System.out.println("****************** LOGOUT"); System.out.println(JSONResponseString); This shows the comparable Java example of a Log Out command. CONFIDENTIAL

21 Log In and Pull JsessionID
HTML Example: Log In and Pull JsessionID <script type="text/javascript" src=" CoreSdk.setSdkAppUrl(' var response = CoreSdk.sdkLogin(userName, userPassword); var myJsessionId = CoreSdk.getJsessionId(); CoreSdk.setJsessionId(myJsessionId); Now let’s look at some HTML examples. This is an HTML example of a Log In and a Pull JsessionID. CONFIDENTIAL

22 HTML Example - Get This is an HTML example of a Get command.
var data = CoreSdk.createDataObject(); var sdkCmd = 'get'; var typeParam = 'CAR'; CoreSdk.addDataParam(data, 'barcode', 'CAR1'); CoreSdk.addDataParam(data, 'entityTypeName', 'CAR'); var myjson = CoreSdk.createJsonRequestString(sdkCmd, typeParam, data); var params = "json=" + myjson; var http = new XMLHttpRequest(); var url = CoreSdk.getSdkUrl(); http.open("POST", url, true); http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); http.onreadystatechange = function() {//Call a function when the state changes. if (http.readyState == 4 && http.status == 200) { var responseJsonObj = eval('(' + http.responseText + ')'); var response = responseJsonObj.response; } http.send(params); This is an HTML example of a Get command. CONFIDENTIAL

23 var response = CoreSdk.sdkLogout();
HTML Example – Log Out var response = CoreSdk.sdkLogout(); This is an HTML example of a Log-Out Command. CONFIDENTIAL

24 Review Firing Triggers With the Web Service Best Practice Tips
Code Examples This chapter concludes the JSON Web Service with more details on how to work with triggers, some recommended Best Practice tips and some Java and HTML code examples. If there is any information you would like to review, please go back through this lesson at this time. Thank you for investing your time in CORE SDK Training. CONFIDENTIAL


Download ppt "JSON Web Service – Tips & Examples"

Similar presentations


Ads by Google