How to call M3 API from JavaScript

Here is a solution to call M3 API from JavaScript, for example to call MMS200MI.GetItmBasic from an HTML page, using the solution described in a previous post on how to call M3 API with REST & JSON. This solution is interesting for easily integrating M3 into third-party web applications.

In this example, I will call the API program MMS200MI and the transaction GetItmBasic to get the details of a specified Item. This API accepts three input fields: Company (CONO), Item number (ITNO), and Language (LNCD).

First, let’s set the variables (replace the values with those that suit your environment):

var userid = 'm3userid';
var password = 'm3password';
var CONO = 100;
var ITNO = 'AN21R8';
var LNCD = 'GB';

Then, let’s construct the URL to make the REST call, and make sure to URI-encode the parameter values:

var url = '/m3api-rest/execute/MMS200MI/GetItmBasic?';
url += '&CONO=' + encodeURIComponent(CONO);
url += '&ITNO=' + encodeURIComponent(ITNO);
url += '&LNCD=' + encodeURIComponent(LNCD);

There are many solutions in JavaScript to make REST calls. I will use the built-in XMLHttpRequest object of modern browsers, but you can choose to use another library of your choice such as jQuery Ajax, Dojo.xhr, etc.

However, all modern browsers implement a same origin policy that restricts cross-domain requests to prevent malicious attacks on a page. Thus, our HTTP Request must be made on the same domain as the REST Service endpoint. For example, if our REST Service endpoint is located at http://hostname:33005/m3api-rest/ then your HTML page must be served with the same origin, i.e. same host and same port number. For example, I placed my HTML page in the mne/script/ folder of my Smart Office server to ensure the same origin policy. There are several workarounds to make cross-domain requests, for example JSONP makes the HTTP Request using a dynamic <script> tag; I haven’t tested such workarounds.

Then, let’s make the HTTP Request assuming your HTML page respects the same origin policy:

var xhr = new XMLHttpRequest();
xhr.open('GET', url, false, userid, password);
xhr.setRequestHeader('Accept', 'application/json');
xhr.send();

Remember, if your HTML page is not in the same domain as the REST service endpoint the browser will throw a JavaScript exception about cross-domain requests.

Then, let’s check if we received a response or not:

if (xhr.status == 200) {
   // success
} else {
   // error
}

The status codes returned could be 200 OK, 401 Unauthorized (incorrect userid/password), 500 Internal Error (invalid data rejected by M3), or something else.

If it’s 200 OK let’s parse the resulting JSON and show the result, otherwise let’s show the error message:

if (xhr.status == 200) {
   // success
   var jsonTxt = xhr.responseText;
   var response = eval('(' + jsonTxt + ')');
   var metadata = response.Metadata.Field;
   var fields = response.MIRecord.NameValue;
   for (var i in fields) {
      console.log(metadata[i]['@description'] + ' (' + fields[i].Name + ', ' + metadata[i]['@type'] + metadata[i]['@length'] + ') = ' + fields[i].Value);
   }
} else {
   // error
   console.log(xhr.responseText);
}

I use eval to parse the JSON but you can use another parser like Doug’s JSON, jQuery.parseJSON, dojo/json, or another parser of your choice.

Also, I use console.log to output the results to the JavaScript console of Google Chrome. Feel free to use any other technique of your choice.

Here is the full source code:

MITest-JS// <![CDATA[
   // set the input fields
   var userid = 'm3userid';
   var password = 'm3password';
   var CONO = 100;
   var ITNO = 'AN21R8';
   var LNCD = 'GB';
   // construct the URL
   var url = '/m3api-rest/execute/MMS200MI/GetItmBasic?';
   url += '&CONO=' + encodeURIComponent(CONO);
   url += '&ITNO=' + encodeURIComponent(ITNO);
   url += '&LNCD=' + encodeURIComponent(LNCD);
   // execute the request
   var xhr = new XMLHttpRequest();
   xhr.open('GET', url, false, userid, password);
   xhr.setRequestHeader('Accept', 'application/json');
   xhr.send();
   // handle the response
   if (xhr.status == 200) {
      // success
      var jsonTxt = xhr.responseText;
      var response = eval('(' + jsonTxt + ')');
      var metadata = response.Metadata.Field;
      var fields = response.MIRecord.NameValue;
      for (var i in fields) {
         console.log(metadata[i]['@description'] + ' (' + fields[i].Name + ', ' + metadata[i]['@type'] + metadata[i]['@length'] + ') = ' + fields[i].Value);
      }
   } else {
      // error
      console.log(xhr.responseText);
   }
// ]]>

Here is a screenshot of the result in Internet Explorer, Google Chrome, Firefox, and Safari of an HTML page with a form that I made:

That’s it!

UPDATE 2012-09-12:

You can access a field value directly by its field name with the following code:

var record = {};
response.MIRecord[i].NameValue.map(function(o){ record[o.Name] = o.Value; }); // transform each record to an associative array accessible by a key
record['ITNO']
record['ITDS']
record['STAT']
record['RESP']

Related articles

Published by

thibaudatwork

ex- M3 Technical Consultant

12 thoughts on “How to call M3 API from JavaScript”

Leave a comment