Asynchronous RESTful Requests Using Protocol Buffers in the Java Client

This example shows how to make asynchronous RESTful requests using the Java® client API, MATLAB® Production Server™ RESTful API, and protocol buffers (protobuf). The example provides and explains a sample Java client, AsyncExample.java, for evaluating a MATLAB function deployed on the server.

To use protobuf when making a request to the server, set the HTTP Content-Type header to application/x-google-protobuf in the client code. The Java client library provides helper classes to internally create protobuf messages based on a proto format and returns the corresponding byte array. Use this byte array in the HTTP request body. The Java client library provides methods and classes to deserialize the protobuf responses.

To use the Java client library, you must include mps_client.jar in the CLASSPATH.

The following table shows where to find the mps_client.jar file, Javadoc, and sample code for the example.

Location of mps_client.jar
  • MPS_INSTALL/client/java

  • MATLABProductionServer_<release>_Clients/java

Location of Javadoc
  • MPS_INSTALL/client/java/doc

  • MATLABProductionServer_<release>_Clients/java/doc

Location of code for the example files
  • MPS_INSTALL/client/java/examples

  • MATLABProductionServer_<release>_Clients/java/examples/MagicSquare

The example uses the java.net package for making HTTP requests to evaluate a MATLAB function deployed on a MATLAB Production Server instance running on http://localhost:9910.

Deploy your MATLAB Function on the Server

Write a MATLAB function mymagic that uses the magic function to create a magic square, then deploy it on the server.

For information on how to deploy, see Create a Deployable Archive for MATLAB Production Server.

function m = mymagic(in)

  m = magic(in);
end

The function mymagic takes a single int32 input and returns a magic square as a 2-D double array.

Make an Asynchronous Request to the Server

  1. Construct the request URL.

    In the Java client, use the POST Asynchronous Request to make the initial request to the server. The request URL comprises of the address of the server instance, the name of the deployed archive and the name of the MATLAB function to evaluate. Set the HTTP request mode to async and client to a user-defined identifier value in the query parameters.

        String clientId = "123";
        String mpsBaseUrl = "http://localhost:9910";
        URL url;
        url = new URL(mpsBaseUrl + "/mymagic/mymagic?mode=async&client="+clientId);

  2. Set the request headers.

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

        final static protected String CONTENT_TYPE = "application/x-google-protobuf";
        HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
        urlConnection.setDoOutput(true);
        urlConnection.setRequestProperty("Content-Type", CONTENT_TYPE);
  3. Create an HTTP request body containing the protocol buffer message.

    Use the newInstance(arg1, arg2, arg3) method defined in the MATLABParams class to build the protocol buffer 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);
  4. Send the request to the server.

    Write the MATLABParams mlMakeBody object to the output stream of the HTTP request.

        OutputStream output = urlConnection.getOutputStream();
        output.write(mlMakeBody.getRequestBody());
        output.flush();
    
  5. 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 such as 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. Inital response is below");
        System.out.println("State: "+ mlInitialResponse.getState() + " " + "Request URL: "
            +mlInitialResponse.getRequestURL() + " Last modified sequence: " + 
                mlInitialResponse.getLastModifiedSeq());
    

Get the State Information of the Request

  1. Make a request to get the request state information.

    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 returns the output in protocol buffer format.

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

    Parse the response using methods defined in the MATLABRequest class to get the state of the request and the current lastModifiedSeq value at the server.

        MATLABRequest requestInfoTmp = MATLABRequest.newInstance(urlConnection.getInputStream());
        System.out.println("State: "+requestInfoTmp.getState() + " Last modified sequence: " + requestInfoTmp.getLastModifiedSeq());

In asynchronous mode, a client is able to post multiple requests to the server. To get the state information of each POST request, you must make a corresponding request to the GET State Information RESTful API.

View the Collection of Requests Owned by a Particular Client

Use the GET Collection of Requests RESTful API to view information about multiple 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. The MATLABRequests class has a getMATLABRequests method that returns a Map of requestURL and the 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());
    }

Retrieve the Results of a Request

  1. Make a request to fetch the response.

    Use the GET Result of Request RESTful API to fetch the request results after the request state has changed to READY or ERROR. In the request URL, set the query parameter format to protobuf, so that the server returns the output in protocol buffer format.

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

  2. Parse the response.

    If the request state is READY, use the methods defined in the MATLABResult class to parse the response. To create a MATLABResult object, pass the MATLABParams mlMakeBody object and the response body of the GET Result of Request request to the newInstance method.

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

    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.

        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();
            }
        }
    
  3. Display the results.

    Write a helper method printResult that takes as input the result that is parsed from the response body and prints the corresponding 2-D array.

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

Sample code for the AsyncExample.java Java client follows.

Code:

 AsyncExample.java

Related Topics