# Package com.mathworks.mps.client.rest

RESTful API and Protocol Buffer Support

See: Description

- Class Summary
  Class | Description
  --- | ---
  HTTPErrorInfo | This class parses the error response body for the GET Result of Request request when the state of the request is ERROR_STATE.
  MATLABParams | This class creates the payload for the initial HTTP POST request.
  MATLABRequest | This class represents the HTTP response to the GET State Information request.
  MATLABRequestHandle | This class represents the MATLAB function execution request created with the initial POST Asynchronous Request.
  MATLABRequests | This class represents the collection of requests owned by a certain client.
  MATLABResult<T> | This class represents the outcome of the execution of a MATLAB function deployed on MATLAB Production Server.

- Enum Summary
  Enum | Description
  --- | ---
  MATLABRequestState | The state of an asynchronous MATLAB execution request.

## Package com.mathworks.mps.client.rest Description

# RESTful API and Protocol Buffer Support

The MATLAB® Production Server™ Java™ client API offers two workflows for client-server communication.
One workflow that uses the MWHttpClient hides the implementation details of request creation, data serialization and deserialization in both asynchronous and synchronous requests sent to the server. For more information, see overview. The other workflow provides you the flexibility to use your own HTTP client for client-server communication. This workflow relies on the MATLAB Production Server RESTful API. Starting in R2020a, the RESTful API supports protocol buffers (protobuf) for data serialization in the Java client API. Protocol buffers are a language-neutral and platform-neutral method of serializing structured data. To use protocol buffers, set the HTTP Content-Type header to `application/x-google-protobuf`. The Java client API internally creates protocol buffer messages based on a proto format and returns the corresponding byte array. Use this byte array in the HTTP request body. The Java client API provides methods and classes to deserialize the protocol buffer responses.

The examples that follow explain how to make asynchronous and synchronous requests to the server and the support for MATLAB structures (structs) in the second workflow. You use the `java.net` package for making HTTP requests to evaluate a MATLAB function `mymagic` deployed on a MATLAB Production Server instance running on `localhost:9910`. To use the Java client API, you must include `mps_client.jar` in the `CLASSPATH`. Find `mps_client.jar` in `$MPS_INSTALL/client/java`, where `$MPS_INSTALL` is the location in which MATLAB Production Server is installed.

Sample code for the examples is available in `$MPS_INSTALL/client/java/examples/MagicSquare`.

## Asynchronous RESTful Requests using Protocol Buffers

1. Make an asynchronous request to the server

2. Get the state information of the request

3. View the collection of requests owned by a particular client

4. Retrieve the results of a request

### 1. Make an asynchronous request to the server

Use the POST Asynchronous Request RESTful API to make the initial request to the server.

- 1.1 Set the request headers.

  Set the HTTP request `mode` to `async`. Set the HTTP Content-Type header to `application/x-google-protobuf`, as the API returns a byte array of protocol buffer messages. Set the `client` to a user defined client identifier value.

  The function `mymagic` in the deployed archive `mymagic` takes a single `int32` input and returns a magic square as a 2-D `double` array.

                String clientId = "123";
                String mpsBaseUrl = "http://localhost:9910";
                URL url;
                url = new URL(mpsBaseUrl + "/mymagic/mymagic?mode=async&client="+clientId);
                final static protected String CONTENT_TYPE = "application/x-google-protobuf";
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setDoOutput(true);
                urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE);

- 1.2 Create an HTTP request body containing the protocol buffer message and send the request to the server.

  Use the newInstance(arg1, arg2, arg3) method defined in the MATLABParams class to build the message. Since the `mymagic` function returns a single 2-D array, set `arg1` to `1` and `arg2` to `double[][].class`. Specify an integer value for `arg3`, which is the input to the `mymagic` function.

                MATLABParams mlMakeBody = MATLABParams.newInstance(1, double[][].class, 2);
                OutputStream output = urlConnection.getOutputStream();
                output.write(mlMakeBody.getRequestBody());
                output.flush();

- 1.3 Receive and interpret the server response.

  On successful execution of the HTTP requests, the server responds with a protocol buffer message. Parse the protocol buffer message using methods from the MATLABRequestHandle class to get details like the state of the request, the request URL, and the last modified sequence value of the request.

                MATLABRequestHandle mlInitialResponse = MATLABRequestHandle.newInstance(urlConnection.getInputStream());
                System.out.println("First Request has been Sent. Initial response is below");
                System.out.println("State: "+ mlInitialResponse.getState() + " " + "Request URL: "+mlInitialResponse.getRequestURL() + " Last modified sequence: " + mlInitialResponse.getLastModifiedSeq());

### 2. Get the state information of the request.

Use the GET State Information RESTful API to get the state of the request. In the request URL, set the query parameter `format` to `protobuf` so that the server to return the output in protocol buffer format. Parse the response to get the state of the request and the current `lastModifiedSeq` value at the server. Use the methods defined in the MATLABRequest class to parse the response.

                url = new URL(mpsBaseUrl + mlInitialResponse.getRequestURL() + "/info?" + "format=protobuf");
                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE);
                urlConnection.setRequestMethod("GET");
                urlConnection.connect();

                MATLABRequest requestInfoTmp = MATLABRequest.newInstance(urlConnection.getInputStream());
                System.out.println(requestInfoTmp.getState() + " " + requestInfoTmp.getLastModifiedSeq());

### 3. View the collection of requests owned by a particular client.

Use the GET Collection of Requests RESTful API to view the collection of requests sent by a particular client represented by `clientId.` In the request URL, set the query parameter `format` to `protobuf` so that the server returns the output in protocol buffer format. Use the MATLABRequests class `newInstance` method to parse the response body of a successful request. `MATLABRequests` class has a `getMATLABRequests` method that returns a `Map` of `requestURL` and `MATLABRequest` object.

                url = new URL(mpsBaseUrl + mlInitialResponse.getInstanceId() + "requests" + "?since="
                    + mlInitialResponse.getLastModifiedSeq() + "&format=protobuf&" + "clients=" + clientId);
                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE);
                urlConnection.setRequestMethod("GET");
                urlConnection.connect();

                MATLABRequests updates = MATLABRequests.newInstance(urlConnection.getInputStream());

                Map<String, MATLABRequest> urlUpdates = updates.getMATLABRequests();
                System.out.println("State of the Requests with the client: " + clientId);
                for (String requestURL : urlUpdates.keySet()) {
                    System.out.println(requestURL + ":" + urlUpdates.get(requestURL).getState());
                }

### 4. Retrieve the results of a request.

Use the GET Result of Request RESTful API to fetch the request results after the request state has changed to `READY`. Use the methods defined in the MATLABResult class to parse the response. Create a MATLABResult object using the MATLABParams object created in Step 1.2 and the response body of the GET Result of Request request. Write a helper method `printResult` which takes the result that is parsed from the response body as input and prints the corresponding 2-D array.

If an error occurs when the deployed MATLAB function executes, then the call to the `getResult` method throws a `MATLABException` that contains the error message from MATLAB. Even in this case , the state of the request is still READY as the function call was successful while the function execution resulted in an error.

If the request state is `ERROR`, use the `HTTPErrorInfo` class instead of `MATLABResult` class to parse the response. Use the methods defined in the `HTTPErrorInfo` class to get information about the error.

                url = new URL(mpsBaseUrl + mlInitialResponse.getRequestURL() + "/result?" + "format=protobuf");
                urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE);
                urlConnection.setRequestMethod("GET");
                urlConnection.connect();

                if (requestInfoTmp.compareTo(MATLABRequestState.ERROR_STATE) == 0) {
                    HTTPErrorInfo httpErrorInfo = HTTPErrorInfo.newInstance(urlConnection.getInputStream());
                    System.out.println("ErrorCode: " + httpErrorInfo.getHttpErrorCode());
                    System.out.println("Error Message: " + httpErrorInfo.getHttpErrorMessage());
                    System.out.println("Error body: " + httpErrorInfo.getHttpBody());
                }else{

                    MATLABResult<double[][]> mlFinalResult1 = MATLABResult.newInstance(mlMakeBody, urlConnection.getInputStream());
                    try{
                        double[][] magicSq1 = mlFinalResult1.getResult();
                        printResult(magicSq1);
                    }catch(MATLABException e){
                        e.printStackTrace();
                    }

                    private static void printResult(double[][] result) {
                        for (double[] row : result) {
                            for (double element : row) {
                                System.out.print(element + " ");
                            }
                            System.out.println();
                        }
                    }
                }

## Synchronous RESTful Requests using Protocol Buffers

Use the POST Synchronous Request RESTful API to make the initial request to the server.

- 1. Set the request headers.

  Set the HTTP Content-Type to `application/x-google-protobuf`, as the API returns a byte array of protocol buffer messages.

  The function `mymagic` in the deployed archive `mymagic` takes a single `int32` input and returns a magic square as a 2-D `double` array.

                URL url;
                url = new URL(mpsBaseUrl + "/mymagic/mymagic");
                HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                urlConnection.setDoOutput(true);
                urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE);

- 2. Create an HTTP request body containing the protocol buffer message and send the request to the server.

  Use the newInstance(arg1, arg2, arg3) method defined in the MATLABParams class to build the message. Since the `mymagic` function returns a single 2-D array, set `arg1` to `1` and `arg2` to `double[][].class`. Specify an integer value for `arg3`, which is the input to the `mymagic` function.

                MATLABParams mlMakeBody = MATLABParams.newInstance(1, double[][].class, 2);
                OutputStream output = urlConnection.getOutputStream();
                output.write(mlMakeBody.getRequestBody());
                output.flush();

- 3. Receive and interpret the server response which contains the result.

  On successful execution of the HTTP requests, the server responds with a protocol buffer message. Parse the protocol buffer message using methods from the MATLABResult class to get the result of the request. Pass the MATLABParams object created in Step 2 and the response body of the HTTP request to the newInstance method to create a MATLABResult object. Write a helper method `printResult` which takes the result that is parsed from the response body as input and prints the corresponding 2-D array.

  If an error occurs when the deployed MATLAB function executes, then the call to the `getResult` method throws a `MATLABException` that contains the error message from MATLAB.

                MATLABResult<double[][]> mlFinalResult1 = MATLABResult.newInstance(mlMakeBody, urlConnection.getInputStream());
                try{
                    double[][] magicSq1 = mlFinalResult1.getResult();
                    printResult(magicSq1);
                }catch(MATLABException e){
                    e.printStackTrace();
                }

                private static void printResult(double[][] result) {
                    for (double[] row : result) {
                        for (double element : row) {
                            System.out.print(element + " ");
                        }
                        System.out.println();
                    }
                }

## Struct Support for RESTful Request using Protocol Buffers

The Java client API also supports sending structs represented as Java objects as input during the evaluation of a MATLAB function deployed on the server. When you make the initial POST request to send data, extend the MWDefaultMarshalingRules interface to implement a new set of marshaling rules for the list of classes being marshaled.

- 1. Write a MATLAB function `sortstudents` that takes structs as input, then deploy it on the server. The fields of the struct are student name, score and grade. Create a Java class `Student` with the same data members as the struct. For more information about the MATLAB function `sortstudents` and the Java class `Student`, see Marshaling a Struct Between Client and Server.
- 2. Create a class `StudentMarshaler` that extends `MWDefaultMarshalingRules` interface. Since Java does not natively support structs, extending the `MWDefaultMarshalingRules` interface lets you serialize Java objects to structs and deserialize structs to Java objects.

                  public class StudentMarshaler extends MWDefaultMarshalingRules {
                      @override
                      public List<Class> getStructTypes() {
                          List structType = new ArrayList();
                          structType.add(Student.class);
                          return structType;
                      }
                  }

                  Student[] students = new Student[]{new Student("Toni Miller", 90, "A"),
                      new Student("Ed Plum", 80, "B+"),
                      new Student("Mark Jones", 85, "A-")};

- 3. Create the HTTP request body.
  To create the HTTP request body, pass the `StudentMarshaler` class as an argument to the `MATLABParams` `newInstance` method. `StudentMarshaler` class serializes an array of Java objects of the class `Student` into an array of structs and deserializes the array of structs into to an array of Java objects of class `Student`.

                  String mpsBaseUrl = "http://localhost:9910";
                  URL url;
                  url = new URL(mpsBaseUrl + "/sortstudents/sortstudents?mode=async&client="+clientId);
                  HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                  urlConnection.setDoOutput(true);
                  urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE);

                  MATLABParams mlMakeBody = MATLABParams.newInstance(1, Student[].class, new StudentMarshaler(), new Object[]{students});
                  OutputStream output = urlConnection.getOutputStream();
                  output.write(mlMakeBody.getRequestBody());
                  output.flush();

- 4. Interpret the server response.
  To interpret the response from the server, create a `MATLABResult` object using the MATLABParams object that you created in the request body and the response body of the GET Result of Request request. Set the return type of the `MATLABResult` object to `Student[]`.

                  MATLABResult<Student[]> mlFinalResult = MATLABResult.newInstance(mlMakeBody, urlConnection.getInputStream());
                  try{
                      Student[] magicSq = mlFinalResult.getResult();
                      for (Student student : magicSq) {
                          System.out.println(student);
                      }
                  }catch(MATLABException e){
                      e.printStackTrace();
                  }

Copyright 2010-2022 The MathWorks, Inc.