Saturday, January 25, 2014

Introduction to Nashorn

Nashorn (pronounced naz-horn) is the Javacript engine for the JVM that will be shipped with JDK8. It's a written using 100% Java, is highly optimized and is InvokeDynamic based. Javascript code is converted into bytecode by Nashorn so that it will run on the JVM.

What does that mean?

It means that Nashorn provides complete interoperablity between JavaScript and Java worlds. i.e JavaScript code can directly call Java code, and vice versa. Nashorn also lets you create and manipulate Java objects, extend Java classes and implement Java interfaces. This interoperability also gives access to many additional tools and libraries and gives you the best of both worlds.

Why Javascript?

Javascript as been really taking off along with the popularity of HTML5. Loads of libraries are being introduced every day and there are many Javascript developers out there as well. In fact, stats in 2013 show that there are almost as many Javascript developers as there are Java developers. Turns out Javascript it no longer 'just a' scripting language that is only used for front end development on browsers. :)

How do you start using Nashorn?

You have two options

  • Command Line with jjs
  Set your environment variables to point to your JDK8 installation. (you can get an early access release from here.
  Open up your cmd line and enter jjs
~>jjs
 jjs> print("Hello World");
 
  •  Embed in Java code and use javax.script api
 ScriptEngineManager m = new ScriptEngineManager();
 ScriptEngine e = m.getEngineByName("nashorn");
   
 try {
     e.eval("print('Hello World')");
 } catch (ScriptException e1) {
     e1.printStackTrace();
 }



Examples

Calling Java methods 
As you can see you may treat Java objects just like javascript objects. (Which is achived through InvokeDynamic - which I will come to later)

Java arrays can be created as follows

Collections are interpreted as arrays

Here we are subclassing the abstract TimerTask class.

And since this is really javascript, we can directly pass in the function as a Lambda.

Similarly, functionality can be directly passed into a new thread (again as a Lambda)


Nashorn also integrates well with JavaFX. See this for a pretty cool demo. Just run it with jjs -fx -scripting fireworks.js


InvokeDynamic and Dynalink

This is what enables languages on the JVM to talk to each other. When you make a call, the Dynalink library (using the invokeDynamic instruction) determines at run time if it's a call to a JavaScript function,  Java function or a function of any other JVM language.


Tuesday, December 24, 2013

Introduction to Java 8 lambda expressions

Value parameterization is useful - but only to certain extent. When we try to handle additional use cases, we find the need to handle many special cases. Some developers, try to deal with these special cases using special values (-1, Integer.MAX_VALUE, null) However this is error prone and adds unnecessary complexity to the code. 

Lets start by looking at an example. Say we are developing a car sales application.
The entity class may look something like this.


 public class Car {

   private String make;
   private String model;
   private String type;
   private Integer year;
   private Integer kilometers;
   private String colour;
   private Transmission transmision;
   private BigDecimal price;

   //getters and setters
 }


A functionality required for the app might be the ability to display between a year range. The following method would cater this;


 void showCarsFilterByYearRange(Integer min, Integer max){
   for (Car c : getAllCars()) {
    if(c.getYear() > min && c.getYear() < max){
     display(c);
    }
   }
 }



We can call this with a range like


 showCarsFilterByYearRange(2000, 2005);


This works fine for the range, but we are forced to provide a max year even if we don’t want to. Maybe we can modify the method to support null value params and treat it as a special value ( in this case, when max is null we can safely substitute Integer.MAX_VALUE in it’s place as we are dealing with years here )

 void showCarsFilterByYearRange(Integer min, Integer max){
   for (Car c : getAllCars()) {
    if(c.getYear() > ((min != null)? min : 0)
      && c.getYear() < ((max != null)? max : Integer.MAX_VALUE)){
     display(c);
    }
   }
  }


Now we can only display cars after a particular YOM by passing in null for max


 showCarsFilterByYearRange(2000, null);


Sure this works, but what about additional search requirements? We are bound to need to search vehicles by other parameters such as price, kilometers, transmission. And surely, you should also be able to apply multiple filters? Our approach is obviously quite brittle and code complexity could increase exponentially with each new requirement.

The solution? Parameterization of behaviour (as opposed to values and types)  
The expected behavior should be able to be passed as a function...

In our usecase we need to pass the car filtering logic as such a function. Unfortunately, (at least before Java 8) you cannot just pass a method as a parameter - you can only pass instances of objects. Therefore, this will need to be implemented using functional interfaces (also known as Single Abstract Method (SAM) interfaces).

A functional interface is an interface with only one method. In our case, this method needs to apply a filter to a Car and return a boolean flag.
 public interface CarPredicate {
   boolean test(Car p);
 }


We can have a single filter method that will expect an instance that implements this interface, and uses test method to check the cars.
 public void showFilteredCars(CarPredicate pred){
   for(Car c: getAllCars()){
    if(pred.test(c)){
     display(c);
    }
   }
 }


On the caller end, we can wrap an anonymous inner class declaration and instantiation along with an implementation for the test method and pass it to our showFilteredCars().  In the example below we are displaying the cars made after 2008.
 showFilteredCars(new CarPredicate(){
   public boolean test(Car c){
    return c.getYear() > 2008;
   }
 });

Note we’ve now parameterized the behaviour! The filtering logic is pushed out to the caller, which means we can do any type of filtering without having to touch showFilteredCars(). For example if we need to filter and display cars made after 2008 with manual transmission, the caller just needs to add that logic in;
 showFilteredCars(new CarPredicate(){
   public boolean test(Car c){
    return c.getYear() > 2008 
     && c.getTransmision().equals(Transmission.MANUAL);
   }
 });


It’s instantly obvious that this is a much better implementation. However, there is just too much boilerplate code here which deters programmers from following this approach. That’s where Java8 Lambda expressions come in - we can define the same logic as above with the minimum effort, only using the ‘important bits’.
Revisiting the previous example below, I have highlighted what we can consider the ‘important bits’. I.e (1) the parameter the predicate takes, and (2) the logic of what it returns.
 showFilteredCars(new CarPredicate(){
    public boolean test(Car c){
     return c.getYear() > 2008;
    }
 });

With Java 8 lambda expressions (also called closures) we only need to specify these two things using the following syntax.
 showFilteredCars(c -> c.getYear() > 2008);


It’s important to note that internally still gets converted to an instance of a functional interface. The compiler figures out what type c has to be through type inference.

Note that we did not need to update our showFilteredCars() implementation. However, it turns out that a functional interface that takes an object and returns a Boolean is such a common case that Java8 also provides and generalized predicate so that we don’t have to write our own.
 Interface Predicate {
   Boolean test(T t);
 }

So for completeness, we may update our showFilteredCars() to use this instead.
 public void showFilteredCars(Predicate pred){
   for(Car c: getAllCars()){
    if(pred.test(c)){
     display(c);
    }
   }
 }



The sample code for the above examples are available here

Eclipse IDE with support for Lambda expressions can be found here