Structures (or structs) are MATLAB® arrays with elements accessed by textual field designators.
Structs consist of data containers, called fields. Each field stores an array of some MATLAB data type. Every field has a unique name.
A field in a structure can have a value compatible with any MATLAB data type, including a cell array or another structure.
In MATLAB, a structure is created as follows:
S.name = 'Ed Plum'; S.score = 83; S.grade = 'B+'
S
) with three fields: S = name: 'Ed Plum' score: 83 grade: 'B+'
S(2).name = 'Toni Miller'; S(2).score = 91; S(2).grade = 'A-';
(1,2)
is created. Structs with additional
dimensions are also supported.Since Java® does not natively support MATLAB structures, marshaling structs between the server and client involves additional coding.
MATLAB structures are ordered lists of name-value pairs. You represent them in Java with a class using fields consisting of the same case-sensitive names.
The Java class must also have public
get
and set
methods
defined for each field. Whether or not the class needs both get
and set
methods
depends on whether it is being used as input or output, or both.
Following is a simple example of how a MATLAB structure can be marshaled between Java client and server.
In this example, MATLAB function sortstudents
takes
in an array of structures (see Marshal MATLAB Structures (Structs) in Java for details).
Each element in the struct array represents different information
about a student. sortstudents
sorts the input array
in ascending order by score of each student, as follows:
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 this example only uses the |
You compile sortstudents
into a deployable
archive (scoresorter.ctf
) using the Production
Server Compiler app (see Compile Deployable Archives with Production Server Compiler
App for
details) and make it available on the server at http://localhost:9910/scoresorter
for
access by the Java client (see Share the Deployable Archive).
Before defining the Java interface required by the client,
define the MATLAB structure, Student
, using
a Java class.
Student
declares the fields name
, score
and grade
with
appropriate types. It also contains public get
and set
functions
to access these fields.
Next, define the Java interface StudentSorter
,
which calls method sortstudents
and uses the Student
class
to marshal inputs and outputs.
Since you are working with a struct type, Student
must
be included in the annotation MWStructureList
.
interface StudentSorter { @MWStructureList({Student.class}) Student[] sortstudents(Student[] students) throws IOException, MATLABException; }
Finally, you write the Java application (MPSClientExample
)
for the client:
Create MWHttpClient
and associated
proxy (using createProxy
) as shown in Create a Java Client.
Create an unsorted student struct array in Java that mimics the MATLAB struct in naming, number of inputs and outputs, and type validity in MATLAB. See Java Client Coding Best Practices for more information.
Sort the student array and display it.
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(); } } }
Java classes that represent MATLAB structures use
the Java Beans Introspector
class (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()
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 behavior 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; } }
When defining Java structs as inputs, follow these guidelines:
Ensure that the fields in the Java class match the field names in the MATLAB struct exactly. The field names are case sensitive.
Use public get
methods on the fields
in the Java class. 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. In this example, note that 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 defined for a MATLAB structure
that is only used as an input value, the set
methods
are not required. This version of the Student
class
only represents input values:
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; } }
When defining Java structs as outputs, follow these guidelines:
Ensure that the fields in the Java class match the field names in the MATLAB struct exactly. The field names are case sensitive.
Create a new instance of the Java class using
the structure received from MATLAB. Do so by using set
methods
or @ConstructorProperties
annotation provided by Java. get
methods
are not required for a Java class when defining output-only MATLAB structures.
An output-only Student
class using set
methods
follows:
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; } }
An output-only Student
class using @ConstructorProperties
follows:
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; } }
Note:
If both |
If the Student
class is used as both an input
and output, you need to provide get
methods to
perform marshaling to MATLAB. For marshaling from MATLAB,
use set
methods
or @ConstructorProperties
annotation.