- Undocumented Matlab - https://undocumentedmatlab.com -

UDD and Java

Posted By Yair Altman On March 23, 2011 | 4 Comments

Once again I welcome Donn Shull, who concludes his series on Matlab’s undocumented UDD mechanism with a discussion of the UDD-Java relationship.

Introduction to the UDD-Java relationship

Over the course of this series we have mentioned connections between UDD and Java. In UDD Events and Listeners [1] we described how in Matlab each Java object can have a UDD companion. In Hierarchical Systems with UDD [2] we briefly noted that a UDD hierarchy may be passed to Java. This suggests that there is a two way relationship between between UDD and Java.
In this article we will use some undocumented built-in methods such as java and classhandle to explore the UDD-Java relationship. We have used built-in methods for UDD objects before. We have also mentioned the importance of studying code from The MathWorks. When you come across something that looks like it may be a UDD method you can check with the which command:

>> which java -all
C:\MATLAB\R2010b\toolbox\matlab\general\java.m
java is a built-in method                               % javahandle.com.mathworks.hg.peer.Echo method
java is a built-in method                               % ui.figure method
java is a built-in method                               % hg2utils.HGHandle method
java is a built-in method                               % JavaVisible method
java is a built-in method                               % hg.figure method
java is a built-in method                               % hg.GObject method
java is a built-in method                               % schema.class method
java is a built-in method                               % handle.handle method
java is a built-in method                               % schema.method method
C:\MATLAB\R2010b\toolbox\rptgen\rptgen\@sgmltag\java.m  % sgmltag method

If you find schema.class in the comments for built-in methods, then the method is a general UDD method.

UDD javahandle companions for Java object

Whenever a Java class is instantiated in Matlab, it is possible to create a companion UDD object [3]. The created companion can be in either the javahandle or the javahandle_withcallbacks package. The primary reason for creating the companion object is to avoid memory leaks [4] when attaching a Matlab callback to a callback property. It makes sense in general to use the javahandle_withcallbacks package.

>> % creage a java instance and the companion UDD object
>> javaFrame = javax.swing.JFrame;
>> % dot notation
>> javaFrameUDD = javaFrame.handle('CallbackProperties');
>> % or Matlab notation
>> javaFrameUDD = handle(javaFrame,'CallbackProperties');

We can use the built-in classhandle method to inspect our UDD companion object. This can be used, for example, to obtain a list of the events that the Java class generates:

>> % use classhandle to list a java classes events
>> jch = javaFrame.handle.classhandle;
>> for index = 1:numel(jch.Events), disp(jch.Events(index).Name); end
MouseWheelMoved
MouseClicked
MouseEntered
MouseExited
MousePressed
MouseReleased
WindowGainedFocus
WindowLostFocus
WindowActivated
WindowClosed
WindowClosing
WindowDeactivated
WindowDeiconified
WindowIconified
WindowOpened
ComponentHidden
ComponentMoved
ComponentResized
ComponentShown
MouseDragged
MouseMoved
ComponentAdded
ComponentRemoved
AncestorMoved
AncestorResized
FocusGained
FocusLost
WindowStateChanged
HierarchyChanged
CaretPositionChanged
InputMethodTextChanged
PropertyChange
KeyPressed
KeyReleased
KeyTyped
>> % Use one of the object's callbacks
>> set(javaFrameUDD,'WindowGainedFocusCallback',@myCallbackFcn);

If we do not wish to use callback properties, then we can create our UDD companion in the javahandle package and use handle.listener to respond to events.

javaFrame = javax.swing.JFrame;
javaFrameUDD = javaFrame.handle;
lis = handle.listener(javaFrameUDD,'WindowGainedFocus',@myCallbackFcn);

Passing UDD objects to Java code

You can pass any UDD object to your Java classes in Matlab. Matlab will create a Java bean adapter for the UDD object. The bean adapter created is a subclass of com.MathWorks.jmi.bean.UDDObject. UDDObject implements the Java interfaces com.MathWorks.jmi.bean.DynamicProperties, com.MathWorks.jmi.bean.MTObject, com.MathWorks.jmi.bean.TreeObject, and com.mathworks.services.Browseable.
The generated bean adapter will have the methods of the parent class the methods of the UDD class, as well as set and get methods for the class properties. To understand how this works, let’s start with our simple.object and use the java method to inspect the bean adapter:

>> myObj = simple.object('myObj', 2);
>> % using dot notation with the java method
>> myObj.java.getClass
ans =
class objectBeanAdapter0
>> myObj.java.methods
Methods for class objectBeanAdapter0:
acquireReference                    createNullMatlabObjectListener      lastDown
addBelow                            createNullPropertyChangeListener    left
addBrowseableListener               dialog                              notify
addFirstBelow                       disp                                notifyAll
addLeft                             dispose                             objectBeanAdapter0
addMatlabObjectListener             equals                              releaseReference
addObjectPropertyChangeListener     findProperty                        removeBrowseableListener
addRight                            firstDown                           removeMatlabObjectListener
browseableCanHaveChildren           getChildAt                          removeObjectPropertyChangeListener
browseableChild                     getChildCount                       right
browseableChildCount                getClass                            setDirtyFlag
browseableChildFetchCount           getClassName                        setDynamicPropertyValue
browseableChildren                  getDynamicProperties                setName
browseableDataObject                getDynamicPropertyValue             setPropertyValue
browseableDisplayObject             getIndex                            setThreadSafetyCheckLevel
browseableHasChildren               getIndexOfChild                     setValue
browseableNChildren                 getName                             toString
browseableNextNSiblings             getNewInstance                      up
browseableNextSibling               getPropertyValue                    updateCache
browseableParent                    getValue                            updateChildCount
browseablePrevNSiblings             hashCode                            updateIndex
browseablePrevSibling               isDirty                             wait
checkThreadSafety                   isLeaf
clearDirtyFlag                      isObservable
compareTo                           isValid

The parent class has added a large number of methods to the bean adapter for our original class. By looking at the list we can see our dialog and disp methods. There are also getName, setName, getValue, and setValue methods for our classes properties. The rest of the methods were inherited from the base UDDObject superclass. We can use any superclass method directly with the bean adapter object. For example:

>> myObj.java.getPropertyValue('Name')
ans =
myObj

Java interface class

To be able to use our UDD object in user-written Java code, we need a Java interface class for it. While we could manually write an interface file, UDD provides a very handy convenience method to automatically create the interface file. For this, we use the classhandle method again. The schema.class object obtained using classhandle has a method called createJavaInterface that takes two string arguments: the Java interface classname, and the folder in which to place the interface file. The steps to create and use this interface file are:

  1. Create and test your UDD class
  2. Create a Java interface file using schema.class‘s CreateJavaInterface
  3. Modify your UDD class definition file (schema.m) to reference the Java interface file
  4. Create the Java code that uses your class

For example, to create a Java interface file for the simple object we created above, use the following commands in Matlab:

classH = classhandle(myObj);
classH.createJavaInterface('simpleObjectInterface',pwd);

This will create the following simpleObjectInterface.java file in the current working directory:

public interface simpleObjectInterface
       extends com.mathworks.jmi.bean.TreeObject
{
    /* Properties */
    public java.lang.String getName();
    public void setName(java.lang.String value);
    public double getValue();
    public void setValue(double value);
    /* Methods */
    public void dialog();
    public void disp();
}

The interface file contains set and get accessor methods for our UDD object properties, and Java prototypes for the UDD methods (in our case, dialog and disp).
The next step is to modify our class definition file (schema.m) to reference the Java interface file we have created. This modification provides the information that Matlab needs to create the bean adapter that implements the Java interface:

simpleClass = schema.class(simplePackage, 'object');
simpleClass.JavaInterfaces = { 'simpleObjectInterface' };

We can verify that the generated bean adapter implements the interface using Java Reflection techniques. As always when we have made changes to the class definition file, we need to use the clear classes command, and then recreate our objects:

>> myObj = simple.object('myObj', pi)
myObj =
  Name: myObj
 Value: 3.141593
>> myObjBean = java(myObj)
myObjBean =
  Name: myObj
 Value: 3.141593
>> interfaces = myObjBean.getClass.getInterfaces
interfaces =
java.lang.Class[]:
    [java.lang.Class]
>> interfaces(1)
ans =
interface simpleObjectInterface

Using UDD in Java

Let’s create a simple Java class that illustrates passing a UDD object to Java. Here we will just have two methods: The first gets the Value property from a class instance and doubles it; the second launches the class instance dialog:

public class accessUDDClass
{
  double localValue;
  public void accessUDDClass() {
  }
  public void doubleValue(simpleObjectInterface UDDObj) {
    localValue = UDDObj.getValue();
    UDDObj.setValue(2*localValue);
  }
  public void launchDialog(simpleObjectInterface UDDObj) {
    UDDObj.dialog();
  }
}

If we have set up the Java compiler and environment variables correctly, we can compile our interface and Java class files from inside Matlab using the system command (alternately, we can compile using any external Java compiler or IDE):

>> system('javac accessUDDClass.java simpleObjectInterface.java')
ans =
     0

Now test our simple Java class with the UDD object created earlier:

>> javaObj = accessUDDClass
javaObj =
accessUDDClass@eb9b73
>> javaObj.doubleValue(myObj)  % pi => 2*pi
>> myObj
myObj =
  Name: myObj
 Value: 6.283185

This concludes the UDD series. I would like to thank Yair for his help in preparing and presenting this information.

Editor’s note

I would like to thank Donn for his enourmously detailed work on UDD, and for preparing it in easy-to-follow articles. I can personally attest to the huge time investment it has taken him. I trully believe he deserves a warm “thank you” from the Matlab community. Please visit Donn’s website [5], or add a short comment [6] below.
In the following weeks, I return to the regular stuff that made this website famous: solving day-to-day Matlab problems using simple undocumented built-in Matlab gems.
– Yair

Categories: High risk of breaking in future versions, Java, Listeners, Undocumented feature, Undocumented function


4 Comments (Open | Close)

4 Comments To "UDD and Java"

#1 Comment By Matt Whitaker On March 24, 2011 @ 11:51

I totally agree Yair. I have been reading this series closely and have learned an immense amount of detail on these UDD objects.
Bravo, Donn! Much appreciated

#2 Comment By julien On April 6, 2011 @ 00:18

Thanks Donn for these excellent and well written articles !
I have a question, maybe you could help me. My problem is simple, I would like to trigger a Matlab callback when the value of a property of a java object changes.
I tried 2 things : First is to set ‘PropertyChangeCallback’ to the UDD companion of my java Object.

J=handle(javax.swing.JLabel('Hello'),'CallbackProperties');
set(J,'PropertyChangeCallback',@(h,e)disp('Property changed'));

When I modify the “Text” property, it works perfectly well.

>> J.setText('New Value');
Property changed

However, the callback does not trigger on every properties. For example,

J.setAutoscrolls(true); % Does not trigger the Callback

So, my second try was to use UDD property event mechanism.

J=handle(javax.swing.JLabel('Hello'),'CallbackProperties');
P=findprop(J,'Text');
L=handle.listener(J,P,'PropertyPostSet',@(h,e)disp('UDD property changed'));

This works, but only when the property value is changed from the set method on the UDD object :

>> J.setText('Again a new value'); % Java side : does not trigger listener callback
>> set(J,'Text','Hello'); % This triggers the listener callback
UDD property changed

What I would like is to be able to trigger the callback on all properties of java objects and from property changes which come from java side (j.setProperty syntax) or Matlab side (set(obj,’Property’,Value) syntax).

Do you know how I could do that from Matlab side ?
Thank you very much in advance for your help.

#3 Comment By Donn On April 6, 2011 @ 10:49

@julien – I do not have an answer for you. Perhaps a person with more knowledge of java can explain why ‘PropertyChange’ is only fired for a subset of JLabels properties. As for the ‘PropertyPostSet’ listener this looks like a bug to me. I suspect that the MATLAB notation changes the UDD peer and generates the ‘PropertyPostSet’ event and synchronizes the java objects property. When the java notation is used it may be that the java object is set and then the UDD object is synchronized. If that is the order of events then this may be related to MATLABs lack of support for asynchronous events in COM objects. Both the java peer mechanism and COM support are based on UDD. The MathWorks explicitly states with COM that asynchronous events are not supported.

Sorry I can’t be of more help,

Donn

#4 Comment By julien On April 6, 2011 @ 12:24

Thank you for your answer Donn ! Unfortunately, I will have to deal with Bound properties (JavaBeans) to be sure that the properties I want to monitore fire PropertyChange events…
Thanks again for your articles,
Best Regards


Article printed from Undocumented Matlab: https://undocumentedmatlab.com

URL to article: https://undocumentedmatlab.com/articles/udd-and-java

URLs in this post:

[1] UDD Events and Listeners: http://undocumentedmatlab.com/blog/udd-events-and-listeners/

[2] Hierarchical Systems with UDD: http://undocumentedmatlab.com/blog/hierarchical-systems-with-udd/

[3] create a companion UDD object: http://undocumentedmatlab.com/blog/udd-events-and-listeners/#Java

[4] memory leaks: http://mathforum.org/kb/message.jspa?messageID=5950839

[5] Donn’s website: http://aetoolbox.com/default.aspx

[6] comment: http://undocumentedmatlab.com/blog/udd-and-java/#respond

[7] Matlab callbacks for Java events : https://undocumentedmatlab.com/articles/matlab-callbacks-for-java-events

[8] Accessing internal Java class members : https://undocumentedmatlab.com/articles/accessing-internal-java-class-members

[9] JMI – Java-to-Matlab Interface : https://undocumentedmatlab.com/articles/jmi-java-to-matlab-interface

[10] Extending a Java class with UDD : https://undocumentedmatlab.com/articles/extending-a-java-class-with-udd

[11] MathWorks-solicited Java survey : https://undocumentedmatlab.com/articles/mathworks-solicited-java-survey

[12] Static Java classpath hacks : https://undocumentedmatlab.com/articles/static-java-classpath-hacks

Copyright © Yair Altman - Undocumented Matlab. All rights reserved.