May 27, 2015

In Vegas For WSOP

I'm currently sitting in my hotel room in Las Vegas, Nevada, prepping for a good night's sleep knowing I've got a reliable house sitter, and getting mentally ready for the World Series of Poker.

This year, I'm not participating in the Main Event.  Instead, I'm going to be in the new Colossus event that will be starting on Friday.  If you're going to be in the area, I start at table 113 in Pavilion White and I'll be wearing a Jurassic Park cap the entire event.

Expect delays in responses between now and June 4.

May 14, 2015

Enabling Nashorn Autocomplete/Intellisense In Eclipse

(Update 5/14/2015, 1:00pm: Discovered that for this to work, you should be running Eclipse Luna SR2 for Java EE Developers at a minimum.)

At Netflix, we have a system called Netflix Test Studio.  Under the hood, it uses Nashorn to execute test cases that are written in JavaScript.  Several of the objects that get instantiated within the Nashorn context are native Java objects that inherit from a couple of base classes or implement a specific interface.

One of the biggest downsides to the way our system was set up was that we didn't have autocompletion for our test cases.  I decided to spend a day to try to figure out what we needed to do, and here are the results of my investigation.

Please note that I won't be sharing my exact code here.  The code I wrote relies on some inner assumptions about our code base.  I'm here to talk you through what I did so that you can replicate the behavior in your own code base.  Also, I'm using Eclipse Luna SR2, so instructions may differ from version to version.  Finally, this is only a day's worth of work.  A final version will be significantly more robust than what I describe here.

The first step is enabling the JavaScript facet in your Java project.  To do this, right-click on your project in Project Explorer, go to Project Facets, select "JavaScript" and hit "Apply" and "OK."  This will also give you syntax error checking for JavaScript files inside your Java application, which is always a nice thing.

Second, you need to create a JsDoc file.  JsDoc is the JavaScript equivalent of JavaDoc.  What I did was I added a new main class to my project that I could run that would use the Reflections library to find all the classes in my project that inherited from our test step base class and generate a JsDoc stub like this:

/** @external com.netflix.nts.steps.tocap.NrdpCompareFriendlyName

Constructors:
NrdpCompareFriendlyName()

@class NrdpCompareFriendlyName
 */
function NrdpCompareFriendlyName() {}


/** Add com.netflix.nts.steps.tocap.NrdpCompareFriendlyName to JavaImporter */ NrdpCompareFriendlyName.prototype._ = function() {}
/** getTargetId()
*/
NrdpCompareFriendlyName.prototype.getTargetId = function() {};
/** promptUserForResponse(UserPrompt arg0)
*/
NrdpCompareFriendlyName.prototype.promptUserForResponse = function() {};
/** wait(long arg0, int arg1)
wait(long arg0)
wait()
*/

NrdpCompareFriendlyName.prototype.wait = function() {};
...

Let me walk you through each of these items.

NrdpCompareFriendlyName is a Java class.  /** */ is how you delimit a JsDoc comment block in JavaScript, so I put some metadata there.  Eventually, I'll be pulling in some data from our JavaDoc, but for now, I really only needed to add the @class attribute to help Eclipse know that this is a valid item to show up after a "new" statement.  I then declare an empty function with the same name.

Now, there's a bit of a bug in Eclipse Luna SR2 where if you hover over a class name, rather than pull up the JsDoc information that came immediately before the function definition, it will pull up the JsDoc for the method immediately following it.  So, I emit a dummy underscore so I can have the class name that needs to be added to the JavaImporter class immediately after.  This way, I can hover over the class name, then copy the full class name and easily paste it into my JavaImporter statement.

To associate the method with the class, I add it to the class prototype.

For each method in the class, I then emit a simple JsDoc block with all the overloads of the methods and their expected parameter types.

Finally, we add the JsDoc to the project references.  Right-click on JavaScript Resources in your project and pick "Properties" and add your JsDoc file there.  You should then get this data to show up as part of your Eclipse autocomplete/content assist.

A couple of additional recommendations before I leave.  In Preferences > JavaScript > Editor > Content Assist, check "Enable Auto Activation."  Also, if your JsDoc file is massive (ours is 4.6MB right now), you might need to increase the timeout under Preferences > JavaScript > Editors > Content Assist > Advanced.

Have fun, and let me know what kind of enhancements you guys can make with this.