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.