Java IoT Authors: Liz McMillan, Elizabeth White, Pat Romanski, Yeshim Deniz, Carmen Gonzalez

Related Topics: Java IoT

Java IoT: Article

A Return to Reflection

A Return to Reflection

When we last talked, I promised to finish up the CodeDocument class I'd so abruptly left behind back in July (JDJ Vol. 4, issue 7). Now, due to millions of desperate letters from fans around the globe, I've decided to finish off the series in this article, tackling reflection once again and ending with a text component that supports syntax highlighting and a simplified version of something similar to Borland's Code Insight. Along the way we'll see a few more tricks that JTextArea can do, and in general we'll just go hog wild in code!

A Refresher on Reflection
Those of you who read my last article can just skim through this part. For the others I'll try to explain, quickly, what reflection is and why we need it for this article.

Reflection allows object A, which is interested in object B, to interogate object B for any information object A is interested in at runtime - without having the source code on the machine. Interested in what attributes the object has? No problem, just use reflection. Wondering if the object has a particular method? Again, no problem, just use reflection. Now that you know the object has a particular method, you want to know what parameters the method requires. Just use reflection! Now you know what the parameters are for the method, but you want to know what your spouse is thinking? Just use...oh, wait, that doesn't work.

Well, anyway, reflection is one of the cooler features in the Java language (and oh, how I wish C++ had the same thing!). Used properly it offers some great benefits. Obviously, for development tools that need to know all sorts of details about the objects being manipulated, this is great. Other uses might be to generate SQL automatically based on some metadata scheme (this was a technique one of the developers used in a project I was on recently). When you use tools like Borland's JBuilder, the ability of the Inspector to "know" exactly what properties to display for a given UI component is based completely on reflection. So how do we use it?

To start, you need to get the Class object from whatever object you're interested in. Let's take a look at the code below.

Vector v = new Vector(); //this is the object we want to
//learn more about through
Class aClass = v.getClass();

Any object could have been chosen (Vector, JComponent or any other valid Java object), and once we have a valid instance we call the getClass() method to get the object's Class instance. The Class object serves as the starting point for obtaining all sorts of information, such as all the constructors for that object or all the declared methods -or even all the fields (attributes) of the object. Let's look at what we do once we get a method from the list of declared methods for the object:

Method[] methods = aClass.getDeclaredMethods();
for (int i=0;i[methods.length;i++){
  Method aMethod = methods[i];
  System.out.println( aMethod.getName() ); }

All we have to do, once we have a Class object, is call the getDeclaredMethods() function, which returns an array containing all the declared methods of the class (this includes methods declared as private!). Once we have this array we can iterate through all of the elements in the array calling the Method class's getName() method. If we're interested in determining the accessibility of a particular method, we can use the getModifiers() function:

int mods = aMethod.getModifiers();
System.out.println( Modifier.toString(mods) + " " +
aMethod.getName() );

If we're interested in the parameters a method took, we can do the following, using the Method class's getParameters(), which returns an array of Class objects representing the arguments to the method:

Class[] params = aMethod.getParameters();

We can also invoke methods dynamically on an object by using reflection. First we retrieve the desired method as we did above or by using the Class class's getDeclaredMethod (which is useful if you already know the name and parameters of a particular kind of method - for example, say you were trying to determine if a series of objects has a method called "setText" that takes a single parameter of type String). Then we create an array of Object and call the Method class's invoke() method.

Class[] argParams = new Class[1];
argParams[0] = Object.class;
aMethod = aClass.getDeclaredMethod( "addElement", arg- Params );

Object[] argVals = new Object[1];
argVals[0] = new String( "A New String Object !" );
aMethod.invoke( v, argVals );

The first part of the code gets a single method from the aClass variable and then prepares to invoke the method. The argVals array has its first element set to a new instance of a String, and then the invoke method is called: the first parameter is the object that the method is being invoked on (in this case our Vector variable from before), and the second parameter is the object array of method arguments (methods that take no arguments could just pass in null).

So we've looked very quickly at a simple example of how to retrieve information about an object, all of it done at runtime, using reflection. Remember to import the java.lang.reflect package into your code to do your experiments. Now we'll move on to the CodeDocument and how we'll start hooking this all together.

When a State Isn't a State (and Other Dumb Plays on Words...)
For the CodeDocument to do its work it has to know its current state - in other words, not only what word you've just typed in (or inserted), but whether or not you're just typing in the package name, typing in imports, creating a class declaration or creating variables in code within a method. The document also has to know what type the variable is as well as whether you've worked with it before so it can look it up if necessary. Obviously, this could get quite complex, and to make this function as a production tool you'd end up with a sophisticated state machine and parser to work all this out. In the interest of time (yours) and energy (mine), I'm going to develop a simplified version of this that should serve as a possible model or at least inspire you to feats greater than mine.

So, back to State. To keep track of the state of what you're typing in, I'll introduce several new constants as well as a number of new variables to keep track of it all.

To save the information for future use, we'll create several small classes to hold the information for us, namely, class CodePackage to hold information about the package just created; class CodeClass for the outer public class that's normally created; and class ClassElement, which will hold all the dynamically discovered fields and methods we display in our drop-down listbox. To simplify all the reflection code we'll use a class called ClassLister, which will do all the reflection work whenever we encounter a possible need to get at the information.

The following code shows the possible states we'll keep track of in the CodeDocument:

private static final int STATE_TEXT_INPUT = 10;
private static final int STATE_CLASS_INPUT = 11;
private static final int STATE_VARIABLE_INPUT = 12;
private static final int STATE_PACKAGE_INPUT = 13;
private static final int STATE_IMPORT_INPUT = 14;
private static final int STATE_VARIABLE_TYPE_INPUT = 15;

The generic default state (STATE_TEXT_INPUT) represents typing in text, as I'm doing right now. STATE_PACKAGE_INPUT defines when the CodeDocument determines that the user is typing in a package name. This is needed for the reflection to pick classes just created in the package. STATE_IMPORT_INPUT is used to describe when the user is typing in the name of an imported package, like "java.lang.reflect.*", for instance. STATE_CLASS_INPUT signifies the creation of the new outer class. STATE_VARIABLE_TYPE_INPUT and STATE_VARIABLE_INPUT are used to determine when a variable or variable type is entered. As the user types, the state will also be changed, which is handled by the checkForStateChange() method inside the processChar() method. Inside checkForStateChange() the method looks at what kind of character has been passed in and then makes a call to checkState(), which either ouputs diagnostic information or adds the appropriate data to model being built up. Then checkForStateChange() calls the changeState() method, which actually changes the CodeDocument's state. Depending on the character passed in, checkForStateChange() may also call other methods to handle things like a "." or a "(", both of which can cause reflection to take place. Figure 1 shows this in diagrammatic form. The handleDot() and handleOpenParen() methods will be discussed in more detail in the next section, as these are responsible for triggering events.

The CodeDocument now both triggers and listens to events in this new version. Every time the handleOpenParen() method is called, the MethodEvent is fired, via the fireMethodEvent method. This allows outside controls to be notified whenever the CodeDocument is ready to display the arguments of a method, similar to what happens in JBuilder when you type in a method and then type the "(" character and the tool tip pops up with all the method's arguments. Outside controls interested in this event can use the CodeDocument's addMethodListener() method to register themselves as listeners to the documents event, assuming they implement the MethodListener interface given in Listing 1.

The document also listens to events, which is how the drop-down list with the available methods for a given object works. If the handleDot() method is called, the CodeDocument gets the current position and extracts the appropriate text (see the earlier JDJ articles pertaining to the CodeDocument for exactly how this is done) until the class name is found for the variable in question. This is currently the Achilles heel of the whole thing, and those of you interested in making this more sophisticated will want to start improving this part, but it works for our purposes. Once the class name is found, a new set of attributes is created and the classLister attribute's setClassName() method is called, which sets the classLister's class name attribute. To retrieve all the info, the method then calls the classLister's listAll() method, which returns a Vector containing a list of ClassElement objects (which are simply convenient ways to store all the method or attribute data).

Now that all the data is put together, we can go ahead and create our drop-down list. But wait, you say. Where on earth are you going to put it? And how? Patience, my young one, all in good time!

One of the neat features of the Document model class is the ability to insert not only text of different formats, but also visual components, like drop-down listboxes. To do this we use the SimpleAttributeSet class and create a new instance. Then, using the StyleConstants class's static method setComponent(), we pass in our newly created list box and the attribute set we just created. Let's look at the code in Listing 2.

The setComponent() method attaches the newly created JComboBox to inputAttributes object. To make this show in the document, we use the insertString() method at the current position plus one, with a space (" "), and passing in the attribute set. Notice that we're calling the super classes insertString() method. Otherwise we'd end up cycling through all our code, which we don't need to do at this point.

The other thing that's important is to register the CodeDocument as a listener to the JcomboBox. This is done so the CodeDocument knows when the user has selected an item from the list and can safely remove the JComboBox and insert the selected text back into the document. Which is why, as you'll see in Listing 3, the declaration for the CodeDocument class has also changed, and yet another method has been added.

The ClassElement stores the information about any of the methods or attributes in the list. The Element value, which stores the actual name of the attribute or method, is retrieved. After this, the combo box is removed and the string retrieved from the ClassElement is put in its place.

The ClassLister
The ClassLister class is at the heart of all the reflection that goes on in the CodeDocument. Its primary method is the listAll() method, which uses the ClassLister currentClassName attribute to attempt to return a Vector containing a complete listing of all methods and attributes belonging to the class named from the currentClassName attribute. The first thing the listAll() method tries to do is obtain a Class object from the currentClassName String. This is done via the Class class's static method classForName(), which takes a fully qualified class name and attempts to return a valid Class instance. A fully qualified classname would be something like "java.util.Hashtable" or "com.sun.java.swing.JListBox". Since the String parameter to the listAll method may not be a fully qualified name, the ClassLister keeps track of a list of packages it knows about. Thus, if the first try of the class match fails, the listAll() method catches the exception and tries prepending the package names it knows about to the currentClassName until a Class instance is successfully created or it runs out of package names, in which case the method fails. If the method does create a Class instance, it uses reflection, as discussed above, to add all the method and attribute names to a Vector, packaging each method or attribute into a ClassElement object that is added to the Vector list and then returned.

   ClassLister has several other methods:

  • listMethods(), which does something similar to listAll(), except it only returns methods
  • listMethodArgs(), which, given a method name, tries to list out the arguments for the method
  • isNameAClass(), which returns true if the supplied String is a class (like listAll(), the String passed in to isNameAClass() does not have to be a fully qualified class name), or false if the String is not a class name.
  • addPackage, which adds a package name to its internal list (a Vector) of known packages
Tying It All Together
Let's make a simple test application to try this out. Listing 4 shows how it works. Although it looks a bit long, it's actually pretty simple. The main() creates new instances for a frame (class TestFrame - we'll get to that in just a bit), an editor (the infamous JTextArea component) and the doc (our beloved CodeDocument). A keywords list, of type Vector, is created and all the Java keywords are added to it (this is what takes up the bulk of code). The CodeDocument setKeywords() method is called to set the CodeDocument's keyword list. The frame is then registered as a listener to the CodeDocument by the addMethodListener() method. The editor's Document model is set with a call to setDocument(), which sets the CodeDocument as the editor's Document model. The frame size is then set and...we're done!

If you run this, remember to type a few nonkeyword characters (like "//" followed by the actual text). Otherwise you'll encounter a known bug, which can be looked up on the Swing Web site (for more information look at http://developer.java.sun.com/developer/bugParade/bugs/4128967.html).

We've now covered how to make our CodeDocument, highlight use, defined syntax, control, numbers, strings and comments. Along the way we've added code completion (a la JBuilder's Code Insight) and method hints using the magic of Java's reflection classes. We've learned how to use the power of reflection to build the start of a really useful tool as well. I hope you found this as interesting a topic as I did !

More Stories By Jim Crafton

Jim Crafton is software developer currently doing a variety of work in C++, C#, and Java. He is the author of the Visual Component Framework (more at http://vcf-online.org/), an advanced C++ application framework. He's also interested in graphics, particularly 3D graphics using tools like Houdini and ZBrush.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.

@ThingsExpo Stories
With major technology companies and startups seriously embracing Cloud strategies, now is the perfect time to attend @CloudExpo | @ThingsExpo, June 6-8, 2017, at the Javits Center in New York City, NY and October 31 - November 2, 2017, Santa Clara Convention Center, CA. Learn what is going on, contribute to the discussions, and ensure that your enterprise is on the right path to Digital Transformation.
SYS-CON Events announced today that EARP Integration will exhibit at SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. EARP Integration is a passionate software house. Since its inception in 2009 the company successfully delivers smart solutions for cities and factories that start their digital transformation. EARP provides bespoke solutions like, for example, advanced enterprise portals, business intelligence systems an...
Existing Big Data solutions are mainly focused on the discovery and analysis of data. The solutions are scalable and highly available but tedious when swapping in and swapping out occurs in disarray and thrashing takes place. The resolution for thrashing through machine learning algorithms and support nomenclature is through simple techniques. Organizations that have been collecting large customer data are increasingly seeing the need to use the data for swapping in and out and thrashing occurs ...
Amazon started as an online bookseller 20 years ago. Since then, it has evolved into a technology juggernaut that has disrupted multiple markets and industries and touches many aspects of our lives. It is a relentless technology and business model innovator driving disruption throughout numerous ecosystems. Amazon’s AWS revenues alone are approaching $16B a year making it one of the largest IT companies in the world. With dominant offerings in Cloud, IoT, eCommerce, Big Data, AI, Digital Assis...
SYS-CON Events announced today that Progress, a global leader in application development, has been named “Bronze Sponsor” of SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. Enterprises today are rapidly adopting the cloud, while continuing to retain business-critical/sensitive data inside the firewall. This is creating two separate data silos – one inside the firewall and the other outside the firewall. Cloud ISVs oft...
The 21st International Cloud Expo has announced that its Call for Papers is open. Cloud Expo, to be held October 31 - November 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA, brings together Cloud Computing, Big Data, Internet of Things, DevOps, Digital Transformation, Machine Learning and WebRTC to one location. With cloud computing driving a higher percentage of enterprise IT budgets every year, it becomes increasingly important to plant your flag in this fast-expanding busin...
Internet of @ThingsExpo, taking place October 31 - November 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA, is co-located with the 21st International Cloud Expo and will feature technical sessions from a rock star conference faculty and the leading industry players in the world. @ThingsExpo Silicon Valley Call for Papers is now open.
As cloud adoption continues to transform business, today's global enterprises are challenged with managing a growing amount of information living outside of the data center. The rapid adoption of IoT and increasingly mobile workforce are exacerbating the problem. Ensuring secure data sharing and efficient backup poses capacity and bandwidth considerations as well as policy and regulatory compliance issues.
SYS-CON Events announced today that Interoute has been named “Bronze Sponsor” of SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. Interoute is the owner operator of Europe's largest network and a global cloud services platform, which encompasses over 70,000 km of lit fiber, 15 data centers, 17 virtual data centers and 33 colocation centers, with connections to 195 additional partner data centers. Our full-service Unifie...
In order to meet the rapidly changing demands of today’s customers, companies are continually forced to redefine their business strategies in order to meet these needs, stay relevant and continue to see profitable growth. IoT deployment and development is integral in this transformation, and today businesses are increasingly seeing the value of investing their resources into IoT deployments. These technologies are able increase ROI through projects such as connecting supply chains or enabling sm...
SYS-CON Events announced today that Progress, a global leader in application development, has been named “Bronze Sponsor” of SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. Enterprises today are rapidly adopting the cloud, while continuing to retain business-critical/sensitive data inside the firewall. This is creating two separate data silos – one inside the firewall and the other outside the firewall. Cloud ISVs ofte...
DevOps is often described as a combination of technology and culture. Without both, DevOps isn't complete. However, applying the culture to outdated technology is a recipe for disaster; as response times grow and connections between teams are delayed by technology, the culture will die. A Nutanix Enterprise Cloud has many benefits that provide the needed base for a true DevOps paradigm.
SYS-CON Events announced today that DivvyCloud will exhibit at SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. DivvyCloud software enables organizations to achieve their cloud computing goals by simplifying and automating security, compliance and cost optimization of public and private cloud infrastructure. Using DivvyCloud, customers can leverage programmatic Bots to identify and remediate common cloud problems in rea...
SYS-CON Events announced today that Outscale, a global pure play Infrastructure as a Service provider and strategic partner of Dassault Systèmes, will exhibit at SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. Founded in 2010, Outscale simplifies infrastructure complexities and boosts the business agility of its customers. Outscale delivers a secure, reliable and industrial strength solution for its customers, which in...
New competitors, disruptive technologies, and growing expectations are pushing every business to both adopt and deliver new digital services. This ‘Digital Transformation’ demands rapid delivery and continuous iteration of new competitive services via multiple channels, which in turn demands new service delivery techniques – including DevOps. In this power panel at @DevOpsSummit 20th Cloud Expo, moderated by DevOps Conference Co-Chair Andi Mann, panelists will examine how DevOps helps to meet th...
SYS-CON Events announced today that Cloudistics, an on-premises cloud computing company, has been named “Bronze Sponsor” of SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. Cloudistics delivers a complete public cloud experience with composable on-premises infrastructures to medium and large enterprises. Its software-defined technology natively converges network, storage, compute, virtualization, and management into a ...
SYS-CON Events announced today that A&I Solutions has been named “Bronze Sponsor” of SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. Founded in 1999, A&I Solutions is a leading information technology (IT) software and services provider focusing on best-in-class enterprise solutions. By partnering with industry leaders in technology, A&I assures customers high performance levels across all IT environments including: mai...
Every successful software product evolves from an idea to an enterprise system. Notably, the same way is passed by the product owner's company. In his session at 20th Cloud Expo, Oleg Lola, CEO of MobiDev, will provide a generalized overview of the evolution of a software product, the product owner, the needs that arise at various stages of this process, and the value brought by a software development partner to the product owner as a response to these needs.
Most technology leaders, contemporary and from the hardware era, are reshaping their businesses to do software in the hope of capturing value in IoT. Although IoT is relatively new in the market, it has already gone through many promotional terms such as IoE, IoX, SDX, Edge/Fog, Mist Compute, etc. Ultimately, irrespective of the name, it is about deriving value from independent software assets participating in an ecosystem as one comprehensive solution.
SYS-CON Events announced today that EARP will exhibit at SYS-CON's 20th International Cloud Expo®, which will take place on June 6-8, 2017, at the Javits Center in New York City, NY. "We are a software house, so we perfectly understand challenges that other software houses face in their projects. We can augment a team, that will work with the same standards and processes as our partners' internal teams. Our teams will deliver the same quality within the required time and budget just as our partn...