Contents

See: Description

Packages
Package | Description
--- | ---
com.mathworks.mps.client | Provides library support for Java clients to communicate with MATLAB Production Server.
com.mathworks.mps.client.annotations | Contains custom annotations for MATLAB Production Server Java client
com.mathworks.mps.client.rest | RESTful API and Protocol Buffer Support

## Contents

1. Overview
2. Quick Example
3. Programming Guide
4. Data Marshaling
5. Marshaling MATLAB structures (or structs)
6. Logging
7. RESTful API and Protocol Buffer Support

## Overview

MATLAB Production Server is a client-server framework created by MathWorks for deploying MATLAB code in scalable and robust manner. The server hosts one or more deployable archives, each exporting one or more MATLAB functions. These MATLAB functions can be invoked from a Java application using the Production Server Java client. The client sends request with all the information required to invoke the MATLAB function and receives the result in the response. The server may be running on the same machine as the client or on a remote machine.

The following example demonstrates how MATLAB Production Server can be used to create a scalable MATLAB application.

## Quick Example

This example deploys a simple MATLAB function to a MATLAB Production Server instance and creates a Java application that accesses it:

STEP 1: Write a MATLAB function.

STEP 2: Create a deployable archive.

STEP 3: Start a MATLAB Production Server instance.

STEP 4: Deploy the deployable archive to a MATLAB Production Server instance.

STEP 5: Write Java interface for MATLAB function.

STEP 6: Write Java application to call MATLAB function.

STEP 7: Enable Java client logging for information and debugging.

NOTE: For the sake of simplicity, we will assume that the client and server are running on the same machine. We will also assume that MATLAB and MATLAB Compiler SDK are installed on this machine.

### STEP 1 : Write a MATLAB function

Create a simple MATLAB function, `mymagic`, that takes a single `int32` input and returns a magic square as a 2-D `double` array:

        function m = mymagic(in)
          m = magic(in);
        end

### STEP 2 : Create a Deployable Archive

Compile the MATLAB function into a deployable archive as follows:

1. Start the Production Server Compiler app from MATLAB.
2. Create a new project with the name `magic` with `Deployable Archive` as the target.
3. Add the MATLAB function, `mymagic`, to this project.
4. Build the project to create `magic.ctf` in the `magic/for_redistribution_files_only` directory.

### STEP 3 : Start a MATLAB Production Server instance

Note: For this example the MATLAB Production Server is installed in `$MPS_INSTALL` directory and `$MPS_INSTALL/script` is on the system path. The directory where we want to create the MATLAB Production Server instance is `/tmp/mpsInst1`.

Note: The paths used in the instructions are for Linux.

Note: Before you can proceed:

1. You must have installed a MATLAB Runtime instance.

2. Configured MATLAB Production Server to use it by running `mps-setup`.

Before you can start a MATLAB Production Server instance, you must create it:

1. Enter the following command in a terminal window to create a new instance of MATLAB Production Server at `/tmp/mpsInst1`.

   Note : The directory `/tmp/mpsInst1` must not exist before entering the following command.

       % mps-new /tmp/mpsInst1
       %

2. Verify the configuration of a MATLAB Production Server instance by editing `/tmp/mpsInst1/config/main.config`.

   This file has the default configuration parameters when a MATLAB Production Server instance is created for the first time.

Start the server instance:

1. Change the current working directory to the new MATLAB Production Server instance.
2. Start the server with the `mps-start` command.

       % cd /tmp/mpsInst1
       % mps-start
       %

   By default, the MATLAB Production Server instance listens to port number `9910` for client requests. This can be verified in the `/tmp/mpsInst1/endpoint/http` file:

       % cat /tmp/mpsInst1/endpoint/http
       127.0.0.1:9910

3. Check status of MATLAB Production Server instance can be checked using the `mps-status` command:

       % mps-status
       'tmp/mpsInst1' STARTED
       license checked out

### STEP 4 : Deploy the Deployable Archive on the MATLAB Production Server instance

Once the MATLAB Production Server instance is started, you need to deploy the deployable archive to it. To deploy the deployable archive, `magic.ctf`, copy it to the `/tmp/mpsInst1/auto_deploy` folder of the server instance.

Now, it is available to the MATLAB Production Server Java client at URL: `http://localhost:9910/magic`

The format of the URL is: `http://<host_name>:<port_number>/<archive_file_name_without_extension>`

### STEP 5 : Write the Java Interface

In order to use the MATLAB function in a Java application, you need to define it using a Java interface. The interface must:

1. include a method with the same name as the MATLAB function
2. take parameters that are consistent with the MATLAB function's input arguments
3. return an object the is consistent with the MATLAB function's output arguments
4. declare two checked exceptions:
   1. `com.mathworks.mps.client.MATLABException` : For reporting MATLAB errors
   2. `java.io.IOException` : For any transport error during client-server communication

The Java interface for `mymagic`will look like following:

       interface MatlabMagic {
           double[][] mymagic(int size) throws IOException, MATLABException;
       }

The interface name can be any valid Java names.

### STEP 6: Write Java application to call MATLAB function.

Note: The MATLAB Production Server Java client API is included in `mps_client.jar`. It is located in the `$MPS_INSTALL/client/java` directory where `$MPS_INSTALL` is the root directory under which MATLAB Production Server is installed.

Before you can call the method representing the MATLAB function, you must:

1. Create an instance of `MWHttpClient` to manage connections to MATLAB Production Server instances.
2. Create a proxy object for the deployed archive hosting the MATLAB function.

    import java.net.URL;
    import java.io.IOException;
    import com.mathworks.mps.client.MWClient;
    import com.mathworks.mps.client.MWHttpClient;
    import com.mathworks.mps.client.MATLABException;

    interface MatlabMagic {
        double[][] mymagic(int size) throws IOException, MATLABException;
    }

    public class Magic {

        public static void main(String[] args){

            // Create a non-interruptible MWHttpClient instance
            MWClient client = new MWHttpClient();

            try{
                // Create the proxy object that represents magic.ctf
                MatlabMagic m = client.createProxy(new URL("http://localhost:9910/magic"), MatlabMagic.class );

                // The proxy object has mymagic as one of its public methods. Invocation of mymagic
                // results in a server request that gets the magic square in response
                double[][] result = m.mymagic(3);

                // Let's print the magic square
                printResult(result);

            }catch(MATLABException ex){

                // This exception represents errors in MATLAB and provides useful information
                // like the MATLAB stack trace or the error ID associated with this error.
                System.out.println(ex);
            }catch(IOException ex){

                // This exception can represent network issues. It is also thrown when the
                // HTTP response received from the server has a status of 4XX or 5XX
                System.out.println(ex);
            }finally{

                // We should close the client when we know that we are not going to need it any more
                // Once the client is closed, an exception will be thrown if a MATLAB function is
                // invoked using the proxy object that was created using client.
                client.close();
            }
        }

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

### STEP 7: Enable Java client logging for information and debugging.

You can quickly enable logging of the Java client operations by providing a log4j configuration file at the start of the Java virtual machine (JVM). The file can be provided using the `-D` JVM startup option to set the `log4j.configuration` property to point to the file.

A default `log4j.properties` file is provided along with the Java client library `mps_client.jar` at the `$MPS_INSTALL/client/java` location. This default logging configuration will output information of INFO level or higher to the standard output.

Note: Files should be provided with the `file:` prefix before the path.

        java -cp ./mps_client.jar:./Magic.jar -Dlog4j.configuration=file:/$MPS_INSTALL/client/java/log4j.properties Magic

For more information on logging, see the Logging section.

## Programming guide

1. Required JAR files
2. Maven™ co-ordinates for MPS Java client
3. Life cycle management of `MWHttpClient`
4. Configure the Client-Server Connection
5. Invoke MATLAB Functions Dynamically
6. Invoke MATLAB Functions Asynchronously
7. Exception Handling
8. Accessing secure CTFs using HTTPS
9. Handling MATLAB functions with multiple outputs
10. Handling MATLAB functions with varargin and varargout

### Required JAR files

The following JAR file is required to work with the MATLAB Production Server Java client API:

`$MPS_INSTALL/client/java/mps_client.jar`

### Maven™ co-ordinates for MPS Java client

The library is hosted in a Maven™ repository at https://mvnrepository.com/artifact/com.mathworks.prodserver/mps_java_client. To use the jar in your Maven project, include the following coordinates in the pom.xml file:

    <!-- https://mvnrepository.com/artifact/com.mathworks.prodserver/mps_java_client -->
    <dependency>
        <groupId>com.mathworks.prodserver</groupId>
        <artifactId>mps_java_client</artifactId>
        <version>release_number</version>
    <dependency>

### Life cycle management of `MWHttpClient`

A single Java client can connect to one or more servers available at different URL's. Even though users can create multiple instances of `MWHttpClient`, a single instance can be used to establish connections with multiple servers.

Proxy objects created by using an instance of `MWHttpClient` can communicate with MATLAB Production Server only until the `close` method of that instance is invoked. It is important to call the `close` method once the `MWHttpClient` instance is no more needed to reclaim the system resources.

For a locally scoped instance of `MWHttpClient` (e.g a standalone application), the Java client code will look like following:

    MWClient client = new MWHttpClient();
    try{
        // Code that uses client to communicate with the server
    }finally{
        client.close();
    }

If MATLAB Production Server Java client is used in a servlet, `MWHttpClient` instance can be tied to the life cycle of the servlet instance by initializing it in the `HttpServlet.init()` method and can be closed in the `HttpServlet.destroy()` method.

    public class ExampleServlet extends HttpServlet {
        private final MWClient client;

        public void init(ServletConfig config) throws ServletException {
            client = new MWHttpClient();
        }

        protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException,java.io.IOException {

           // Code that uses client to communicate with the server
        }

        public void destroy() {
            client.close();
        }
    }

### Configure the Client-Server Connection

You configure the client-server connection using an object that implements the `MWHttpClientConfig` interface. This interface defines the following properties:

1. `Interruptable` - determines if MATLAB functions can be invoked asynchronously
2. `TimeOutMs` - determines the amount of time, in milliseconds, the client waits for a response before timing out
3. `MaxConnections` - determines the maximum number of connections the client opens to fulfil multiple requests
4. `ResponseSizeLimit` - determines the maximum size, in bytes, of the response a client accepts.

The API provides a default implementation,`MWHttpClientDefaultConfig`, that is automatically used when an HTTP/HTTPS client is instantiated. To modify the configuration, extend `MWHttpClientDefaultConfig` and pass it to the HTTP client's constructor.

#### Using the Default Connection Configuration

When you create a client connection using the default constructor, `MWHttpClient()`, an instance of `MWHttpClientDefaultConfig` is automatically used to configure the client-server connection. The default configuration sets the connection properties as follows:

1. `Interruptable` = `false`
2. `TimeOutMs` = `120000`
3. `MaxConnections` = `-1` specifying that the client will use as many connections as allowed by the system
4. `ResponseSizeLimit` = `64*1024*1024` (64MB)

NOTE : The default connection configuration only allows a blocking call to MATLAB function. For a non-blocking invocation of MATLAB function, please refer to the section Invoke MATLAB Functions Asynchronously.

#### Using a Custom Connection Configuration

To change one or more connection properties, use the following steps:

1. Implement a custom connection configuration by extending `MWHttpClientDefaultConfig`.
2. Create the client connection using one of the constructors that accepts a configuration object.
   `MWHttpClient(MWHttpClientConfig config)`
   `MWHttpClient(MWHttpClientConfig config, MWSSLConfig sslConfig)`

The following code sample creates a client connection with a timeout value of 1000ms:

    class MyClientConfig extends MWClientDefaultConfig
    {
      public long getTimeOutMs()
      {
        return 1000;
      }
    }
    ...
    MWClient client = new MWHttpClient(new MyClientConfig());
    ...

#### Implement a Custom Connection Configuration

You implement a custom connection configuration by extending `MWHttpClientDefaultConfig`. `MWHttpClientDefaultConfig` with one getter method for each configuration property:

1. `public int getMaxConnectionsPerAddress()` - returns the value for the maximum number of connections a client can use to handle simultaneous requests.
2. `public long getTimeOutMs()` - returns the number of milliseconds the client will wait for a response before generating an error.
3. `public boolean isInterruptible()` - returns a boolean specifying if the MATLAB function can be invoked asynchronously. If this method returns `false`, `getMaxConnectionsPerAddress()` must return `-1`.
4. `public int getResponseSizeLimit()` - returns the maximum number of bytes the client can accept in a response.

You only need to override the getters for properties you wish to change. For example to specify that a client's MATLAB functions can be interrupted you provide an override for `isInterruptible()`:

    class MyClientConfig extends MWClientDefaultConfig
    {
      public boolean isInterruptible()
      {
        return true;
      }
    }

To specify that a client times out after one second and can only accept 4MB responses you override `getTimeOutMs()` and `getResponseSizeLimit()`:

    class MyClientConfig extends MWClientDefaultConfig
    {
      public long getTimeOutMs()
      {
        return 60000;
      }
      public int getResponseSizeLimit()
      {
        return 4*1024*1024;
      }
    }

### Invoke MATLAB Functions Dynamically

Dynamically invoking MATLAB functions does not require the creation of an interface modelling the contents of a deployable archive. This means that you do not need to recompile your application every time you add a function to a deployed archive.

Dynamic invocation uses a reflection-based proxy to construct the MATLAB function request that is passed to the server instance. When invoking a function, you specify the function name as one of the parameters to the method invoking the request.

To dynamically invoke a MATLAB function:

1. Instantiate an instance of the `MWHttpClient` class.
2. Create a reflection-based proxy object using one of the client connection's `createComponentProxy()` methods.
3. Invoke the function using one of the reflection-based proxy's `invoke()` methods.

#### Create a Reflection-Based Proxy

A reflection-based proxy implements the `MWInvokable` interface and provides methods that allow you directly invoke any MATLAB function deployed as part of a deployable archive. Like the interface-based proxy, it is created from the client connection object. The `MWHttpClient` class has two methods for creating a reflection-based proxy:

1. `MWInvokable createComponentProxy(URL archiveURL)` - creates a proxy that uses standard MATLAB data types
2. `MWInvokable createComponentProxy(URL archiveURL, MWMarshalingRules marshalingRules)` - creates a proxy that uses structures

To create a proxy for dynamically invoking functions in the archive `myMagic` hosted on your local computer:

    MWClient myClient = new MWHttpClient();

    URL archiveURL = new URL("http://localhost:9910/myMagic");
    MWInvokable myProxy =  myClient.createComponentProxy(archiveURL);

#### Invoke a MATLAB Function with a Reflection-Based Proxy

A reflection-based proxy has three methods that can be used to invoke functions on a server:

1. `Object[] invoke(final String functionName, final int nargout, final Class<T> targetType, final Object... inputs)` - invoke a function that returns `nargout` values
2. `<T> T invoke(final String functionName, final Class<T> targetType, final Object... inputs)` - invoke a functions that returns a single value
3. `invokeVoid(final String functionName, final Object... inputs)` - invoke a function that returns no values

All of the methods map to the MATLAB function as follows:

1. The first argument is the function's name
2. The middle set of arguments, `nargout` and `targetType`, represent the function's return values
3. The last arguments are the function's inputs

##### Return Multiple Outputs

The MATLAB function `myLimits` returns two values.

    function [myMin,myMax] = myLimits(myRange)
     myMin = min(myRange);
     myMax = max(myRange);
    end

To invoke `myLimits` from a Java client you use the `invoke()` method that takes the number of return arguments:

    double[] myRange = new double[]{2,5,7,100,0.5};
    try
    {
      Object[] myLimits = myProxy.invoke("myLimits", 2, Object[].class, myRange);
      double myMin = ((Double) myLimits[0]).doubleValue();
      double myMax = ((Double) myLimits[1]).doubleValue();
      System.out.printf("min: %f max: %f",myMin,myMax);
    }
    catch (Throwable e)
    {
      e.printStackTrace();
    }

Because Java cannot determine the proper types for each of the returned values, this form of `invoke` always returns `Object[]` and always takes `Object[].class` as the target type. You are responsible for casting the returned values into the proper types.

##### Return a Single Output

The MATLAB function `addmatrix` returns a single value.

    function a = addmatrix(a1, a2)
    a = a1 + a2;

To invoke `addmatrix` from a Java client you use the `invoke()` method that does not take the number of return arguments:

    double[][] a1={{1,2,3},{3,2,1}};
    double[][] a2={{4,5,6},{6,5,4}};
    try
    {
      Double[][] result = myProxy.invoke("addmatrix", Double[][].class, a1, a2);

      for(Double[] row : result)
      {
        for(double element : row)
        {
          System.out.print(element + " ");
        }
      }
    } catch (Throwable e)
    {
      e.printStackTrace();
    }

##### Return No Outputs

The MATLAB function `foo` does not return value.

    function foo(a1)
    min(a1);

To invoke `foo` from a Java client you use the `invokeVoid()` method:

    double[][] a={{1,2,3},{3,2,1}};
    try
    {
      myProxy.invokeVoid("foo", (Object)a);
    }
    catch (Throwable e)
    {
      e.printStackTrace();
    }

#### Marshal Structs

If any of the MATLAB functions in a deployable archive uses structures, you need to provide marshaling rules to the reflection-based proxy. You provide the marshaling rules to the proxy by:

1. Implementing a new set of marshaling rules by extending `MWDefaultMarshalingRules` to use a list of the classes being marshaled.
2. Creating the proxy using `createComponentProxy(URL archiveURL, MWMarshalingRules marshalingRules)`.

The deployable archive `studentChecker` includes functions that use a MATLAB structure of the form

    S =
    name: 'Ed Plum'
    score: 83
    grade: 'B+'

Your Java client code represents the MATLAB structure with a class named `Student`. To create a marshaling rule for dynamically invoking the functions in `studentChecker`, you create a class named `studentMarshaler`.

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

You create the reflection-based proxy for `studentChecker` by passing `studentMarshaler` to `createComponentProxy()`.

    URL archiveURL = new URL("http://localhost:9910/studentCheck");
    myProxy =  myClient.createComponentProxy(archiveURL, new StudentMarshaler());

For more information about using MATLAB structures see Marshaling MATLAB structures (or structs).

### Invoke MATLAB Functions Asynchronously

MATLAB functions can be invoked asynchronously using the `invokeAsync` method provided by the `MWInvokable` interface. As can be seen in the example later, the asynchronous feature uses the approach of dynamic invocation of MATLAB functions only and not the interface based approach. The `invokeAsync` method is a non-blocking method that fires the MATLAB execution request and returns the control back to the client application. This is particularly useful for long running MATLAB functions. There are 2 ways to get to the response of MATLAB function execution request:

1. The `MWRequest` instance returned by `invokeAsync` provides access to `java.util.concurrent.Future` using the `getFuture` method. Client application can invoke the `get` method provided by `java.util.concurrent.Future` to get the MATLAB result. The call to `get` is a blocking call and will wait for MATLAB to finish execution if it is not already done. Once MATLAB result is received, it is cached and future calls to the `get` method will result the cached response.

    import java.net.URL;
    import java.util.concurrent.Future;
    import com.mathworks.mps.client.*;

    class MyConfig extends MWHttpClientDefaultConfig{
        public boolean isInterruptible() { return true; }
        public int getMaxConnectionsPerAddress() { return 10; }
    }

    public class MagicAsync{

        public static void main(String[] args){
            MWClient client = new MWHttpClient( new MyConfig() );

            try{
                MWInvokable invokable = client.createComponentProxy(new URL("http://localhost:9910/magic"));

                MWInvokeRequest httpRequest = new MWInvokeRequest("mymagic", double[][].class);
                httpRequest.setInputParams(4);
                httpRequest.setNargout(1);

                MWRequest request = invokable.invokeAsync(httpRequest, null);
                Future f = request.getFuture();

                double[][] res = f.get();
                printResult(res);

            }catch(Exception ex){

                System.out.println(ex);
            }
            finally{
                client.close();
            }
        }

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

2. Users can register a callback using the `MWRequestListener` instance passed as an input to `invokeAsync`. This way, they will be notified of various state changes that a request goes through during its life time. However, it should be noted that the client is not guaranteed to receive notification of every state depending on how busy the server is. It is possible that request is ready with response before client gets a chance to ask for status of intermediate states.

    import java.net.URL;
    import com.mathworks.mps.client.*;

    class MyClientConfig extends MWHttpClientDefaultConfig{
        public boolean isInterruptible() { return true; }
        public int getMaxConnectionsPerAddress() { return 10; }
    }

    class ReqListener implements MWRequestListener{

        public ReqStateVisitor visitor;

        public ReqListener(ReqStateVisitor visitor) { this.visitor = visitor; }

        public void notify(MWRequest request) {
            MWRequestState state = request.getState();
            state.visit(visitor);
        }
    }

    class ReqStateVisitor implements MWRequestStateVisitor {

        private MWClient client;

        public ReqStateVisitor(MWClient client){ this.client = client; }

        public void cancelled() { }

        public void expired() { }

        public void failed(Exception ex) { }

        public void interrupted() { }

        public void inQueue(long timeStamp, URL requestURL) { }

        public void processing(long timestamp, URL requestURL) { }

        public void sending(byte[] data, URL serviceURL) { }

        public void ready(T responseData) {
            printResult( (double[][])responseData );
            client.close();
        }

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

    public class MagicAsyncWithListener{

        public static void main(String[] args){

            MWClient client = new MWHttpClient(new MyClientConfig());
            ReqStateVisitor v = new ReqStateVisitor(client);
            ReqListener listener = new ReqListener(v);

            try{
                MWInvokable invokable = client.createComponentProxy(new URL("http://localhost:9910/magic"));

                MWInvokeRequest httpRequest = new MWInvokeRequest("mymagic", double[][].class);
                httpRequest.setInputParams(4);
                httpRequest.setNargout(1);

                invokable.invokeAsync(httpRequest, listener);

            }catch(Exception ex){
                System.out.println(ex);
            }
        }
    }

NOTE : `invokeAsync` is only usable when the `MWHttpClient` instance is created using an interruptible `MWHttpClientConfig`. Users can either implement the `MWHttpClientConfig` interface or extend the `MWHttpClientDefaultConfig` class to override the `isInterruptible` method so that it returns true.

### Exception handling

MATLAB Production Server Java client application has to handle following checked exceptions:

1. `com.mathworks.mps.client.MATLABException` : This represents a MATLAB error. It is thrown if there is an error in MATLAB when a proxy object method is executed. Following MATLAB information can be obtained from an instance of this class :
   1. Stack trace
   2. Error ID
   3. Error message
2. `java.io.IOException` : This is thrown if there are either any network related failures or if the server returns with a response status of either 4XX or 5XX.
   1. `com.mathworks.mps.client.MWHttpException`, a subclass of `java.io.IOException` is also available if one needs to handle response status of 4XX or 5XX in a special manner.

### Accessing secure Programs using HTTPS

Connecting to a MATLAB Production Server instance over HTTPS provides a secure channel for executing MATLAB functions. To establish an HTTPS connection with a MATLAB Production Server instance:

1. Ensure that the server is configured to use HTTPS.
2. Install the required credentials on the client system.
3. Configure the client's Java environment to use the credentials.
4. Create the proxy using the program's `https://` URL.

MATLAB Production Server's Java client API also provides:

1. a hook for providing your own `HostnameVerifier`
2. a hook for implementing server authorization beyond that provided by HTTPS

#### Configure the client environment for SSL

Use `keytool` to manage the key store and trust stores on the client machine. At a minimum the client requires the server's root CA (Certificate Authority) in its truststore.

If the client needs to connect to a server that requires client-side authentication, it also needs a signed certificate in its key store.

For information on using `keytool` see Oracle's `keytool` documentation.

#### Establish a secure proxy connection

You can create a secure proxy connection with a MATLAB Production Server instance by using the `https://` URL for the desired program:

    MWClient client = new MWHttpClient();
    URL sslURL = new URL("https://hostname:port/myProgram");
    MyProxy sslProxy = client.createProxy(sslURL, MyProxy.class);

`sslProxy` will use the default Java trust store, stored in `JAVA_HOME\lib\security\cacerts`, to perform the HTTPS server authentication. If the server requests client authentication, the HTTPS handshake will fail because the default `SSLContext` object created by the JRE does not provide a key store.

To enable your client to connect with a server instance requiring client authentication, you set the key store location and password using Java system properties:

    System.setProperty("javax.net.ssl.keystore", "PATH_TO_KEYSTORE");
    System.setProperty("javax.net.ssl.keystorePassword", "keystore_pass");
    MWClient client = new MWHttpClient();
    URL sslURL = new URL("https://hostname:port/myfun");
    MyProxy sslProxy = client.createProxy(sslURL, MyProxy.class);

To use a non-default location for the client trust store, you set the trust store location and password using Java system properties:

    System.setProperty("javax.net.ssl.truststore", "PATH_TO_TRUSTSTORE");
    System.setProperty("javax.net.ssl.truststorePassword", "truststore_pass");
    MWClient client = new MWHttpClient();
    URL sslURL = new URL("https://hostname:port/myfun");
    MyProxy sslProxy = client.createProxy(sslURL, MyProxy.class);

To use a custom `SSLContext` implementation, add a custom `HostnameVerifier` implementation, or use the MATLAB Production Server Java API's server authorization, you must provide a custom implementation of `MWSSLConfig`.

#### SSL API Configuration

The Java API uses a `MWSSLConfig` object to get the information it needs to use HTTPS and perform the additional server authorization. The `MWSSLConfig` interface has three methods:

1. `getSSLContext()` - returns the `SSLContext` object
2. `getHostnameVerifier()` - returns the `HostnameVerifier` object to use if HTTPS hostname verification fails
3. `getServerAuthorizer()` - returns the `MWSSLServerAuthorizer` object to perform server authorization based on the server's certificate

The Java API provides a default `MWSSLConfig` implementation, `MWSSLDefaultConfig`, which it uses when no SSL configuration is passed to the `MWHTTPClient` constructor. The `MWSSLDefaultConfig` is implemented such that:

1. `getSSLContext()` returns the default `SSLContext` object created by the JRE.
2. `getHostnameVerifier()` returns a `HostnameVerifier` implementation that always returns `false`. If the HTTPS hostname verification fails, this will not override the HTTPS layer's decision.
3. `getServerAuthorizer()` returns a `MWSSLServerAuthorizer` implementation that authorizes all MATLAB Production Server instances.

#### Override default hostname verification

As part of the SSL handshake, the HTTPS layer attempts to match the hostname in the provided URL to the hostname provided in the server's certificate. If the two hostnames do not match, the HTTPS layer calls `HostnameVerifier.verify()` as an additional check. The return value of `HostnameVerifier.verify()` determines if the hostname is verified.

The implementation of `HostnameVerifier.verify()` provided by the `MWSSLDefaultConfig` object always returns `false`. The result is that if the hostname in the URL and the hostname in the server certificate do not match, the HTTPS handshake fails.

To use a hostname verification scheme that is more robust, you can extend the `MWSSLDefaultConfig` class to return a version of `HostnameVerifier.verify()` that uses custom logic. For example, if you only wanted to generate one certificate for all of the servers on which MATLAB Production Server instances run, you could specify `MPS` for the certificate's hostname. Then your implementation of `HostnameVerifier.verify()` returns `true` if the certificate's hostname is `MPS`.

    public class MySSLConfig extends MWSSLDefaultConfig {
      public HostnameVerifier getHostnameVerifier() {
        return new HostNameVerifier() {
          public boolean verify(String s, SSLSession sslSession) {
            if (sslSession.getPeerHost().equals("MPS"))
              return true;
            else
              return false;
          }
        }
      }
    }

For more information on `HostnameVerify` see Oracle's Java Documentation.

#### Use additional server authentication

After the HTTPS layer establishes a secure connection, a client can perform an additional authentication step before sending requests to a server. This additional authentication os performed by an implementation of the `MWSSLServerAuthorizer` interface. A `MWSSLSServerAuthorizer` implementation performs two checks to authorize a server:

1. `isCertificateRequired()` determines if server's must present a certificate for authorization. If this returns `true` and the server has not provided a certificate, the client does not authorize the server.
2. `authorize(Certificate serverCert)` uses the server's certificate to determine if the client authorizes the server to process requests.

The `MWSSLSServerAuthorizer` implementation returned by `MWSSLDefaultConfig` authorizes all servers without performing any checks.

To use server authentication extend `MWSSLDefaultConfig` and override the implementation of `getServerAuthorizer()` to return a `MWSSLSServerAuthorizer` implementation that does perform authorization checks.

### Handling MATLAB functions with multiple outputs

MATLAB allows users to write functions with multiple outputs. Java does not support methods with multiple outputs. Following is a simple MATLAB function signature with 2 outputs and 2 inputs. Let's assume that the first input is of type `double` and the second is a `char` array and for the sake of simplicity, let's assume the same types for the first and the second output of this function:

    function [out1 out2] = multipleOutputs(in1, in2)

The Java method signature for such a MATLAB function for MATLAB Production Server Java client must include the number of output arguments as the first input, of type `int`, followed by the remaining inputs. The return type of this Java method must be `Object[]`. Thus the Java method signature for MATLAB function `multipleOutputs` will look like :

    public Object[] multipleOutputs(int nargout, double in1, String in2);

The actual invocation of this method from the Java application may look something like:

    Object[] result = mycomp.multipleOutputs(2, 1.2, "test");

The output `result` will be an array of length 2 with the first element of Java type `double` and the second element of Java type `char`.

### Handling MATLAB functions with `varargin` and `varargout`

MATLAB Production Server Java client supports MATLAB's variable number of inputs, varargin, and outputs, varargout. Following is a MATLAB function signature that uses `varargin` and `varargout`:

    function varargout = vararginout(in1, in2, varargin)

Let's assume that the above MATLAB function has `double` as the type for first input and `char` array as the type for second input. The type of data being passed as part of `varargin` can be any supported type. Let's assume that this function returns 2 outputs as `varargout` with types `double` and `char`.

The Java method signature for MATLAB function `vararginout` will look almost similar to the one discussed in the previous section. The Java method signature supported by MATLAB Production Server Java client for this MATLAB function will look like :

    public Object[] vararginout(int nargout, double in1, String in2, Object... vararg);

The actual invocation of this method from the Java application may look something like:

    Object[] result = mycomp.vararginout(2, 1.2, "test", true, "another string");

or

    Object[] result = mycomp.vararginout(2, 1.2, "test", new Object[]{true, "another string"});

## Data Marshaling

1. MATLAB Data Types
2. Conversion of Java types to MATLAB types
3. Conversion of MATLAB types to Java types
4. Unsupported MATLAB data types
5. Numeric type coercion
6. Dimension coercion
7. Handling MATLAB empty data and Java `null`
8. Use of Java boxed types

When MATLAB Production Server Java client invokes a MATLAB function through a request and receives result in the response, data conversion takes place between MATLAB and Java data types.

### MATLAB Data Types

There are many different data types, or classes, that you can work with in MATLAB. You can build matrices and arrays of floating-point and integer data, characters and strings, and logical true and false states. Function handles connect your code with any MATLAB function regardless of the current scope. Structures and cell arrays, provide a way to store dissimilar types of data in the same array.

There are 15 fundamental classes in MATLAB. Each of these classes is in the form of a matrix or array. With the exception of function handles, this matrix or array is a minimum of 0-by-0 in size and can grow to an n-dimensional array of any size. A function handle is always scalar (1-by-1). All of the fundamental MATLAB classes are circled in the diagram below:

A structure consists of data containers, called fields, and each of these fields stores an array of some MATLAB data type. Every field has a unique name. A field in a structure can have a value of any of the MATLAB data types, including a cell array or another structure.

A cell array is a collection of containers called cells in which you can store different types of MATLAB data including other cell arrays and structures.

In MATLAB, dimensionality is an attribute of the fundamental types and does not add to the number of types as it does in Java. In Java, `double, double[]` and `double[][][]` are three different data types. Where as in MATLAB, there is just `double` data type and there can be a scalar instance, a vector instance or a multi dimensional instance of this type.

Also, numeric classes in MATLAB include signed and unsigned integers. Java does not have unsigned types.

### Conversion of Java types to MATLAB types

The table below shows the data marshaling rules applied when data is passed from Java to MATLAB.

Values passed to Java method | Input type received by MATLAB | Dimension of data in MATLAB
--- | --- | ---
java.lang.Byte, byte | int8 | {1,1}
byte[] data | {1, data.length}
java.lang.Short, short | int16 | {1,1}
short[] data | {1, data.length}
java.lang.Integer, int | int32 | {1,1}
int[] data | {1, data.length}
java.lang.Long, long | int64 | {1,1}
long[] data | {1, data.length}
java.lang.Float, float | single | {1,1}
float[] data | {1, data.length}
java.lang.Double, double | double | {1,1}
double[] data | {1, data.length}
java.lang.Boolean, boolean | logical | {1,1}
boolean[] data | {1, data.length}
java.lang.Character, char | char | {1,1}
char[] data | {1, data.length}
java.lang.String data | {1, data.length()}
java.lang.String[] data | cell | { 1, data.length}
java.lang.Object[] data | { 1, data.length}
In addition, for any convertible data type T above, the following Java type is also a convertible data type
T[] data | MATLAB type for T | { data.length, dimensions(T[0]) }, if T is an Array
{ 1, data.length }, if T is not an Array
NOTE : If T is an array type, then all elements of data must have exactly the same length

### Conversion of MATLAB types to Java types

The table below shows the data marshaling rules applied when data is passed from MATLAB to Java.

NOTE: Since Java does not have unsigned numeric types, MATLAB unsigned types are converted to the appropriate signed types in Java as shown in the following table. Also, data marshaling for MATLAB structures is discussed separately in its own section.

What MATLAB returns | Dimension of data in MATLAB | Java type that MATLAB data will be converted to
--- | --- | ---
int8, unit8 | {1,1} | byte, java.lang.Byte
{1,n} | byte[n], java.lang.Byte[n]
{m,n,p,...} | byte[m][n][p]... , java.lang.Byte[m][n][p]...
int16, unit16 | {1,1} | short, java.lang.Short
{1,n} | short[n], java.lang.Short[n]
{m,n,p,...} | short[m][n][p]... , java.lang.Short[m][n][p]...
int32, unit32 | {1,1} | int, java.lang.Integer
{1,n} | int[n], java.lang.Integer[n]
{m,n,p,...} | int[m][n][p]... , java.lang.Integer[m][n][p]...
int64, unit64 | {1,1} | long, java.lang.Long
{1,n} | long[n], java.lang.Long[n]
{m,n,p,...} | long[m][n][p]... , java.lang.Long[m][n][p]...
single | {1,1} | float, java.lang.Float
{1,n} | float[n], java.lang.Float[n]
{m,n,p,...} | float[m][n][p]... , java.lang.Float[m][n][p]...
double | {1,1} | double, java.lang.Double
{1,n} | double[n], java.lang.Double[n]
{m,n,p,...} | double[m][n][p]... , java.lang.Double[m][n][p]...
logical | {1,1} | boolean, java.lang.Boolean
{1,n} | boolean[n], java.lang.Boolean[n]
{m,n,p,...} | boolean[m][n][p]... , java.lang.Boolean[m][n][p]...
char | {1,1} | char, java.lang.Character
{1,n} | java.lang.String
{m,n,p,...} | char[m][n][p]... , java.lang.Character[m][n][p]...
cell (containing only strings) | {1,1} | java.lang.String
{1,n} | java.lang.String[n]
{m,n,p,...} | java.lang.String[m][n][p]...
cell (containing multiple types) | {1,1} | java.lang.Object
{1,n} | java.lang.Object[n]
{m,n,p,...} | java.lang.Object[m][n][p]...

### Unsupported MATLAB data types

Following data types in MATLAB are not supported for marshaling by MATLAB Production Server Java client:

1. MATLAB function handles
2. Complex (imaginary) data
3. Sparse arrays

### Numeric type coercion

With type coercion feature provided by MATLAB Production Server Java client, numeric MATLAB types can be assigned to multiple Java numeric types as long as there is no loss of data or precision. The main exception to this rule is the coercion of MATLAB `double` data into any Java numeric types. This is allowed because `double` is the default numeric type in MATLAB and this exception to the coercion rule provides more flexibility to the users of MATLAB Production Server. Following table describes the type compatibility for scalar and non-scalar numeric coercion.

MATLAB types | Compatible Java types supported by coercion
--- | ---
uint8 | short, int, long, float, double
int8 | short, int, long, float, double
uint16 | int, long, float, double
int16 | int, long, float, double
uint32 | long, float, double
int32 | long, float, double
uint64 | float, double
int64 | float, double
single | double
double | byte, short, int, long, float

NOTE: As non-scalar numeric coercion may impose a performance penalty, especially for large arrays, it is recommended to keep the Java return types consistent with MATLAB function.

### Dimension coercion

1. Dimension expansion
2. Dimension narrowing

MATLAB Production Server Java client provides some flexibility in how data is received from MATLAB. This flexibility is in the form of the dimensionality of the target Java type corresponding to a result received from MATLAB i.e it is possible for the target Java type to have dimensions either less than or more than the dimensions of data received from MATLAB.

Consider following simple MATLAB function that returns an array of type `double` with values from 1 to 10.

    function out = returnData
    out = 1:10;

In MATLAB, `out` is of type `double` with dimensions 1x10 (number_of_dimensions = 2).

MATLAB Production Server Java client allows a Java programmer to look at `out` as any of the following:

1. A 1-D array of length 10 i.e `double[10]` (number_of_dimensions = 1)
2. A 2-D array with dimensions {1,10} i.e `double[1][10]` (number_of_dimensions = 2)
3. A 3-D array with dimensions {1,10,1} i.e `double[1][10][1]` (number_of_dimensions = 3)
4. An N-D array with dimensions {1,10,1,1,...,1} i.e `double[1][10][1][1]..[1]` (number_of_dimensions = N)

With MATLAB Production Server Java client, MATLAB function `returnData` can be represented in Java as any one of the following methods:

    double[] returnData() throws MATLABException, IOException;
    double[][] returnData() throws MATLABException, IOException;
    double[][][] returnData() throws MATLABException, IOException;
    double[][][][] returnData() throws MATLABException, IOException;
    ...
    ...

Thus, on top of the default behaviour of preserving the number of dimensions of data received from MATLAB, MATLAB Production Server Java client allows dimension coercion in the form of following :

- Dimension expansion

When Java method's return type has more number of dimensions than MATLAB response, MATLAB's dimensions array will be padded with 1's to match the required number of output dimensions in Java.

Here's another example for more clarity. Consider following MATLAB function:

    function a = foo
    a = ones(2,3);

If following Java method was used to represent this MATLAB function,

    double[][][][] foo() throws MATLABException, IOException;

the dimensions of data received in Java will be {2,3,1,1}.
- Dimension narrowing

This is the case when Java method's return type has fewer number of dimensions than data in MATLAB. This case is possible only when extra dimensions for MATLAB array have value of 1 only. To compute number of dimensions in Java, excess 1's are removed first from the right in the dimensions array and then from the left.

For more clarity, consider following MATLAB function:

    function a = foo
    a = ones(1,2,1,1,3,1);

If following Java method was used to represent this MATLAB function,

    double[][] foo() throws MATLABException, IOException;

the dimensions of data received in Java will be {2,3}.

Here are some more examples of dimension narrowing:

MATLAB Array Dimensions | Declared Output Java Type | Output Java Dimensions
--- | --- | ---
1x1 | double | 0
2x1 | double[] | 2
1x2 | double[] | 2
2x3x1 | double[][] | 2x3
1x3x4 | double[][] | 3x4
1x3x4x1x1 | double[][][] | 1x3x4
1x3x1x1x2x1x4x1 | double[][][][] | 3x2x1x4

### Handling MATLAB empty data and Java `null`

- MATLAB empty -> Java

An empty array in MATLAB has at least one 0 as one of the dimensions. Following are a few examples of MATLAB expressions which create empty data:

    empty_double = [];
    empty_double_array = ones(0,0);
    empty_char_array = '';
    empty_cell_array = {};
    empty_int32_array = int32( ones(1,2,0,3) );
    empty_struct = struct([]);

Empty MATLAB data will be returned to Java as `null` for all the cases except when the target type in Java is a scalar primitive. In Java, primitive scalar types cannot be assigned value of `null` and a Java exception will be thrown by MATLAB Production Server Java client.

Also, empty MATLAB `char` array will be marshaled into Java as an empty string only if the target type in Java is `java.lang.String`. If the target type is not `java.lang.String`, it will be marshaled as `null`.

- Java `null` -> MATLAB

When a null value is passed from Java to MATLAB, it will always be marshaled into `[]` i.e a `0x0 double` array in MATLAB. This will be independent of the declared input type used in Java.

In Java, following methods can accept `null` as input value:

    void foo(String input);
    void foo(double[] input);
    void foo(double[][] input);
    void foo(Double input);

In MATLAB, for all the above methods, `null` will be received as:

    [] i.e. 0x0 double

### Use of Java boxed types

MATLAB Production Server Java client will do the primitive to boxed type conversion if users have used boxed types as return types in the Java method signature. E.g following Java method signatures will work interchangeably:

    double[] foo();      <->    Double[] foo();
    double[][][] foo();  <->    Double[][][] foo();

## Marshaling MATLAB structures (or structs)

1. Simple example
2. Define MATLAB structure in Java

Structures are MATLAB arrays with elements accessed by textual field designators. Following is an example of how structures are created in MATLAB:

    S.name = 'Ed Plum';
    S.score = 83;
    S.grade = 'B+'

creates a scalar structure with three fields:

    S =
         name: 'Ed Plum'
        score: 83
        grade: 'B+'

A multi dimensional structure array can be created in MATLAB by inserting additional elements:

    S(2).name = 'Toni Miller';
    S(2).score = 91;
    S(2).grade = 'A-';

creates a structure array of dimensions {1,2}. One can also create structure arrays with more than 2 dimensions.

Since Java does not have built-in support for structure data type, marshaling MATLAB structures between MATLAB Production Server server and client involves extra work.

### Simple Example

Following is a simple example of how MATLAB structure can be marshaled between MATLAB Production Server Java client and server

Consider a MATLAB function `sortstudents` that takes in an array of structures described above. Each element in this array is representing information about a student. This function sorts the input array in the ascending order by `score` of each student

    function sorted = sortstudents(unsorted)
    % Receive a vector of students as input
    % Get scores of all the students
    scores = {unsorted.score};
    % Convert the cell array containing scores into a numeric array or doubles
    scores = cell2mat(scores);
    % Sort the scores array
    [s i] = sort(scores);
    % Sort the students array based on the sorted scores array
    sorted = unsorted(i);

NOTE: Even though `sortstudents` is only using the `score` field of the input structure, `name` and `grade` fields are also available and can be accessed.

Let's assume that this MATLAB function is compiled into `scoresorter.ctf` and is now available for Java MATLAB Production Server client at URL: `http://localhost:9910/scoresorter`

Before defining the Java interface required by the MATLAB Production Server Java client, we need to define MATLAB structure, `student`, in Java. This will be achieved by a Java class `Student` with fields `name, score` and `grade` with appropriate types. It will also have public `get` and `set` functions to access these fields.

    public class Student{

        private String name;
        private int score;
        private String grade;

        public Student(){
        }

        public Student(String name, int score, String grade){
            this.name = name;
            this.score = score;
            this.grade = grade;
        }

        public String getName(){
            return name;
        }

        public void setName(String name){
            this.name = name;
        }

        public int getScore(){
            return score;
        }

        public void setScore(int score){
            this.score = score;
        }

        public String getGrade(){
            return grade;
        }

        public void setGrade(String grade){
            this.grade = grade;
        }

        public String toString(){
            return "Student:\n\tname : " + name + "\n\tscore : " + score + "\n\tgrade : " + grade;
        }
    }

NOTE: `toString` method is provided as a convenience method. It is not required for marshaling

Let's define Java interface `StudentSorter` that has method `sortstudents` and uses `Student` class for inputs and outputs. `Student` must be included in the `MWStructureList` annotation.

    interface StudentSorter {
        @MWStructureList({Student.class})
        Student[] sortstudents(Student[] students) throws IOException, MATLABException;
    }

The final Java application using MATLAB Production Server Java client will look like following:

    import java.net.URL;
    import java.io.IOException;
    import com.mathworks.mps.client.MWClient;
    import com.mathworks.mps.client.MWHttpClient;
    import com.mathworks.mps.client.MATLABException;
    import com.mathworks.mps.client.annotations.MWStructureList;

    interface StudentSorter {
        @MWStructureList({Student.class})
        Student[] sortstudents(Student[] students) throws IOException, MATLABException;
    }

    public class ClientExample {

        public static void main(String[] args){

            MWClient client = new MWHttpClient();
            try{
                StudentSorter s = client.createProxy(new URL("http://localhost:9910/scoresorter"), StudentSorter.class );
                Student[] students = new Student[]{new Student("Toni Miller", 90, "A"),
                                                   new Student("Ed Plum",     80, "B+"),
                                                   new Student("Mark Jones",  85, "A-")};
                Student[] sorted = s.sortstudents(students);
                System.out.println("Student list sorted in the ascending order of scores : ");
                for(Student st:sorted){
                    System.out.println(st);
                }
            }catch(IOException ex){
                System.out.println(ex);
            }catch(MATLABException ex){
                System.out.println(ex);
            }finally{
                client.close();
            }
        }
    }

### Define a MATLAB structure in Java

1. Map Java Field Names to MATLAB Field Names
2. Define input MATLAB structures
3. Define output MATLAB structures

A structure in MATLAB is an ordered list of name-value pairs. It can be represented in Java as a class with fields with the same case-sensitive names. This class also needs to have public `get` and/or `set` methods for each of these fields as shown in the `Student` class above. Whether or not the class needs both `get` and `set` methods for the fields depends on whether it is being used as input or output or both.

#### Map Java Field Names to MATLAB Field Names

Java classes that represent MATLAB structures use the Java Beans Introspector (http://docs.oracle.com/javase/6/docs/api/java/beans/Introspector.html) to map properties to fields and its default naming conventions are used.

This means that by default its decapitalize (http://docs.oracle.com/javase/6/docs/api/java/beans/Introspector.html#decapitalize(java.lang.String) method is used. This maps the first letter of a Java field into a lower-case letter. By default, it is not possible to define a Java field which will map to a MATLAB field which starts with an upper case.

You can override this behaviour by implementing a BeanInfo class with a custom getPropertyDescriptors() method. For example:

    import java.beans.IntrospectionException;
    import java.beans.PropertyDescriptor;
    import java.beans.SimpleBeanInfo;

    public class StudentBeanInfo extends SimpleBeanInfo
    {
      @Override
      public PropertyDescriptor[] getPropertyDescriptors()
      {
          PropertyDescriptor[] props = new  PropertyDescriptor[3];

          try
          {
              // name uses default naming conventions so we do not need to explicitly specify the accessor names.
              props[0] = new PropertyDescriptor("name",MyStruct.class);
              // score uses default naming conventions so we do not need to explicitly specify the accessor names.
              props[1] = new PropertyDescriptor("score",MyStruct.class);
              // Grade uses a custom naming convention so we do need to explicitly specify the accessor names.
              props[1] = new PropertyDescriptor("Grade",MyStruct.class,"getGrade","setGrade");
              return props;
          }
          catch (IntrospectionException e)
          {
              e.printStackTrace();
          }

          return null;
      }
    }

#### Define input MATLAB structures

When `Student` is passed as an input to method `sortstudents`, only the `get` methods for its fields are used by the data marshaling algorithm. As a result, if a Java class is being defined for a MATLAB structure that is only used as an input value, the `set` methods are not required. Thus a shorter version of `Student` class that is only used to represent input values will look like following:

    public class Student{

        private String name;
        private int score;
        private String grade;

        public Student(String name, int score, String grade){
            this.name = name;
            this.score = score;
            this.grade = grade;
        }

        public String getName(){
            return name;
        }

        public int getScore(){
            return score;
        }

        public String getGrade(){
            return grade;
        }
    }

#### Define output MATLAB structures

When `Student` is used as output only, the data marshaling algorithm needs to create new instances of it using the structure received from MATLAB. This can be achieved using the `set` methods or `@ConstructorProperties` annotation provided by Java. `get` methods are not required for a Java class defining output only MATLAB structure

1. Defining output MATLAB structure using `set` methods

An output only `Student` class using `set` methods will look like following:

    public class Student{

        private String name;
        private int score;
        private String grade;

        public void setName(String name){
            this.name = name;
        }

        public void setScore(int score){
            this.score = score;
        }

        public void setGrade(String grade){
            this.grade = grade;
        }
    }

2. Defining output MATLAB structure using `@ConstructorProperties` annotation

An output only `Student` class using `@ConstructorProperties` will look like following:

    import java.beans.ConstructorProperties;

    public class Student{

        private String name;
        private int score;
        private String grade;

        @ConstructorProperties({"name","score","grade"})
        public Student(String n, int s, String g){
            this.name = n;
            this.score = s;
            this.grade = g;
        }
    }

3. If both `set` methods and `@ConstructorProperties` annotation are provided, `set` methods get precedence over `@ConstructorProperties` annotation.

#### Defining input and output MATLAB structure

If `Student` is used as both an input and output, one needs to provide `get` methods to take care of marshaling to MATLAB. For marshaling from MATLAB, one can either use `set` methods or `@ConstructorProperties` annotation.

## Logging

### Java client Logging

You can record details such as HTTP request statuses, server URLs, and output data in your Java® client application using the logging capability available in the MATLAB® Production Server™ Java client library. To offer logging options, the Java client library, mps_client.jar, ships the SLF4J library, slf4j-api.jar. You can use the native logging support that SLF4J provides or use any SLF4J-supported logging framework such as Apache™ Log4j, Logback, or the java.util.logging package.

### Use Embedded SLF4J Library

To use the SLF4J library that is embedded in mps_client.jar for logging, include mps_client.jar in your Java class path. For details on setting the Java class path, see Oracle® documentation Setting the class path for UNIX® and Setting the class path for Windows®.+9

A default log4j configuration file that outputs to standard output is provided at `$MPS_INSTALL/client/java/log4j.properties`

#### Example

        java -cp ./mps_client.jar:./Magic.jar -Dlog4j.configuration=file:/$MPS_INSTALL/client/java/log4j.properties Magic

### Use SLF4J-supported Logging Framework

If you use an SLF4J-supported logging framework or an SLF4J library that is different from the one that is included in `mps_client.jar`, they must be present in front of the `mps_client.jar` on the Java class path.

The following examples assume that you have bundled your client application in `MyApplication.jar` and the entry point of the application is in `MainClass.`

1. To use the Log4j, Log4j 2 or Logback logging frameworks, pass the respective configuration files to your Java application at startup. To do so, add the URL of the file location, file:/path/to/file/filename, to the respective JVM property.

   For example, the following UNIX command adds the Log4j JAR file and configuration file to the class path.

       java -cp ./path/to/log4j.jar:./mps_client.jar -Dlog4j.configurationFile=file:/path/to/file MainClass

2. To use Logback, add both the logback-classic and logback-core JAR files onto the class path. The following example UNIX command shows how to add them and the configuration file to the class path.

       java -cp ./path/to/logback-classic.jar:./path/to/logback-core.jar:./mps_client.jar -Dlogback.configurationFile=/path/to/config.xml MainClass

3. If you encounter version mismatch issues between your engine and the embedded SLF4J library, load your own slf4j-api.jar of the appropriate version by adding it to the Java class path.

   The following example UNIX command shows how to load your own SLF4J library:

       java -cp ./path/to/your/slf4j-api.jar:./mps_client.jar MainClass

The following example UNIX command shows how to load your own SLF4J library and Logback JAR files:

    java -cp ./path/to/slf4j-api.jar:./path/to/logback-classic.jar:./path/to/logback-core.jar:./mps_client.jar -Dlogback.configurationFile=/path/to/config.xml MainClass

For logback, add both the `logback-classic` and `logback-core` jar files onto the classpath.

Note: If you encounter version mismatch issues between your engine and slf4j, it is best to load your own `slf4j-api.jar` of the appropriate version by setting it on the Java classpath. This can especially occur if using later versions of logback.

Refer to the respective 3rd party logging engine documentation for more information on how to configure the logging behavior.

Copyright 2010-2022 The MathWorks, Inc.