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 we described how in Matlab each Java object can have a UDD companion. In Hierarchical Systems with UDD 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. 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 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:
- Create and test your UDD class
- Create a Java interface file using
schema.class
‘s CreateJavaInterface - Modify your UDD class definition file (schema.m) to reference the Java interface file
- 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, or add a short comment 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
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
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.
When I modify the “Text” property, it works perfectly well.
However, the callback does not trigger on every properties. For example,
So, my second try was to use UDD property event mechanism.
This works, but only when the property value is changed from the set method on the UDD object :
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.
@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
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