Last week, JetBrains announced their new statically typed language Kotlin at the JVM Language Summit. Kotlin joins the elite group of statically typed languages : Scala, Gosu, Ceylon, Fantom, targeted to run on the JVM. Scala is the most mature in this statically typed landscape. Fantom supports static and dynamic typing, so it may not be directly competing with others. Both Ceylon and Kotlin are not publicly available yet, but the documentation can give you a preview of how these languages shape up. Kotlin definitely has the potential to attract Java developers due to its backing from the leading Java IDE maker. The good news is Kotlin will debut with an IDE support from day one, but this keeps expectations high on this project.

While Kotlin and Ceylon try to score on the “complexity attribute” of its mature competitor Scala, it may very well become a competitor to Java 8 from an adoption perspective. Java 8 will include support for the most sought after language feature Lambda is slated for late 2012 release. Both Ceylon and Kotlin plans to support higher order functions among others may have stable releases around that time frame. As these young languages are work in progress, it provides an excellent opportunity for them to receive constructive critique from the community and possibly fix or clarify their design choices. Given some of the features that could be implemented as compiler plugins in Kotlin makes it a perfect candidate for experimenting advanced language constructs that were once alien to Java.

Can Kotlin attract Java developers?

Well, it certainly has the potential to attract Java developers and you can already see huge interest from the developer community (Kotlin language documentation is already flooded with feedback) trying to understand what Kotlin can bring to the rapidly innovating JVM platform languages. Some blogs debate its cool new features and its approach to becoming the next big JVM language (NBJL). In addition to the cool features it plans to support, Kotlin incorporates some good idioms from Josh Bloch’s Effective Java. The language documentation references at least 10+ idioms from Effective Java which shows its commitment to adopting best practices that aid developer productivity and program maintainability. Here are some of those idioms highlighted in Kotlin documentation:

Item 11: Override clone judiciously
Item 14: In public classes, use accessor methods, not public fields
Item 16: Favor composition over inheritance
Item 17: Design and document for inheritance or else prohibit it
Item 18: Prefer interfaces to abstract classes
Item 23: Don’t use raw types in new code
Item 24: Eliminate unchecked warnings
Item 25: Prefer lists to arrays
Item 28: Use bounded wildcards to increase API flexibility
Item 38: Check parameters for validity
Item 43: Return empty arrays or collections, not nulls
Item 65: Don’t ignore exceptions
Item 69: Prefer concurrency utilities to wait and notify

Kotlin documentation by far is the most comprehensive source of information about the language and its syntax and it is well maintained. Once again JetBrains folks hit the right chord as the documentation is crucial for any language adoption early on. I do believe JetBrains would continue to deliver its promise of “Develop With Pleasure” with Kotlin too. So far, I have liked Kotlin’s approach to becoming the NBJL and its rich feature set and expressive syntax undoubtedly makes it a compelling choice for developers alike.

Possibly Related Posts:


One of our customer was interested in performing a basic HTTP file transfer function using Flux APIs. I implemented a trivial HTTP file transfer Action in Flux plugins project. Here is a sample test case that shows how this action could be integrated within a Flux workflow.

Maven users could just drop this dependency in your POM to use this plugin in your project.

<dependency>
  <groupId>com.fluxcorp.plugins</groupId>
  <artifactId>http-filetransfer-action</artifactId>
  <version>1.0.2.SNAPSHOT</version>
</dependency>

Make sure you include this maven repository where the plugin snapshots are deployed.

<repository>
  <id>sonatype-nexus-snapshots</id>
  <name>sonatype-nexus-snapshots</name>
  <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>

There are few more interesting plugins available, you can check the project wiki for more details. Enjoy!

Possibly Related Posts:


Note: If you planning to co-locate JDK 5 alongside JDK 6 on Mac OS X Lion 10.7, refer this post. It worked like a charm on the recent 10.7.3

I recently installed Java for Mac OS X 10.6 Update 4 from Mac Software Update. This update basically installs 1.6.0_24 that contains fixes for security vulnerabilities from 1.6.0_22. I hesitated to apply this update for a while as I did not want to invite any trouble to my existing JDK 5 environment that was co-located with JDK 6 (shipped with Snow Leopard). We use JDK 5 to build Flux 7.10 as it requires 1.5. Now that I am mostly into Flux 7.11 development, which requires JDK 6, I switch back and forth on need basis.

I believe JDK 5 was not officially distributed in Snow Leopard, but JDK 5 was still popular and widely used when Snow Leopard first arrived. JDK 5 was officially retired for quite some time now, and I believe it is widely used in many production environments today. I had to find a way to have both 1.5 and 1.6 co-located on my development environment, and there were so many experiences shared by Java developers across the spectrum. The one which came to my rescue was from OneSwarm. It worked for me just fine and I have been living with that until I decided to upgrade to the latest Java update earlier this month. I knew I was going to mess with my development environment, but not a huge risk though. The upgrade went just fine and as expected the upgrade ripped off my JDK 1.5 and set the system Java preferences to JDK 1.6. I was not worried too much as I was using JDK 6 for Flux 7.11 development. So, I did not bother to look at setting up JDK 5 at that moment.

Today, I had to build Flux 7.10, so I had no other option than fixing my JDK mess. I had to dig through my notes to redo those steps. I wanted to share that experience so if any one runs into a similar requirement, you have a decent solution and update to the latest available JDK 1.5 distribution from Apple that is included in Mac OS X 10.5 updates.

Here are the three simple steps:

1. Download “Java for Mac OS X 10.5 Update 9” from Apple.

2. Assuming all your JDK versions point to your CurrentJDK which is JDK 1.6 under “/System/Library/Frameworks/JavaVM.framework/Versions/”.

Here is how mine looks:

Now, follow these instructions carefully:

cd /System/Library/Frameworks/JavaVM.framework/Versions/
sudo rm 1.5.0

3. You may want to install Pacifist (shareware app), which is handy for extracting OS X packages. Unlike other similar tools, this one allows users to select individual files and folders from the package to be extracted.

Right click on the DMG file (JavaForMacOSX10.5Update9.dmg) that you downloaded in Step 1 and select Open With -> Pacifist. Once the Pacifist opens up, just navigate to System -> Library -> Frameworks -> JavaVM.framework -> Versions -> 1.5.0 in the directory tree and right click on 1.5.0 directory and select “Install to Default Location”.

Here is a screen shot of this step:

After JDK 1.5.0 directory is extracted to the default location, the symlinks under “/System/Library/Frameworks/JavaVM.framework/Versions/” would look different, here is how mine looks after the update:

This shows that JDK 1.5.0 is no longer pointing to your CurrentJDK (JDK 1.6). You may want to reset the symlinks to point to the new 1.5.0 directory.

sudo rm 1.5
sudo ln -s 1.5.0 1.5

Now, you can point your JAVA_HOME to JDK 1.5.0 by setting the JAVA_HOME. For example,

export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.5/Home

java -version should print:

Voila! JDK 5 is ready to rock on your Mac along side JDK 6. Just switch between the latest and greatest versions you need.

Possibly Related Posts:


The improved varargs warnings, part of the Coin proposal finally made into the latest JDK 7 build. I believe build 123 is special as this milestone marks the completion of all the planned JSR 334 features (the head side of the Coin) scheduled for implementation in Java SE 7. So, Coin minting done? I think so. Let us get the final dose of Project Coin.

I would like to list out some key points that are worth refreshing when discussing varargs:

  • Generics are implemented by erasure and hence non-reifiable and enforces element types only at compile time.
  • Arrays are reified, which makes them enforce element types at runtime.
  • Arrays are covariant, while parameterized types are invariant.
  • Varargs are implemented as an array of objects and can hold only reifiable types.
  • Arrays when mixed with parameterized types are generally the source of unchecked warnings emitted by the compiler.

In essence, Generics and arrays (including varargs) do not play well together [Item 25: Prefer lists to arrays in Effective Java 2nd Edition Pg 119]. Whenever you invoke a varargs method, an array is created to hold the varargs parameters. If the element type of this array is not reifiable, it is likely to generate a compiler warning. On the other hand, it is not permitted to create an array whose component type is a concrete parameterized type, because it is not type safe.

Here is a simple example that shows generic array creation.

// Generic array creation is illegal - won't compile
List<List<String>> numbersInThreeLanguages = Arrays.asList(new List<String>[]{Arrays.asList("Un", "Deux", "Trois"), Arrays.asList("Uno", "Dos", "Tres"), Arrays.asList("One", "Two", "Three")});

The legal code would look like, but this would generate an unchecked warning:

//[unchecked] unchecked generic array creation for varargs parameter of type List<String>[]
    List<List<String>> numbersInThreeLanguages = Arrays.asList(Arrays.asList("Un", "Deux", "Trois"),
            Arrays.asList("Uno", "Dos", "Tres"), Arrays.asList("One", "Two", "Three"));

The warning can be suppressed at the call site as this is considered a safe invocation:

    @SuppressWarnings(value = "unchecked")
    List<List<String>> numbersInThreeLanguages = Arrays.asList(Arrays.asList("Un", "Deux", "Trois"),
            Arrays.asList("Uno", "Dos", "Tres"), Arrays.asList("One", "Two", "Three"));

These unchecked warnings issued when invoking varargs methods that are tagged as candidates for inducing heap pollution are considered harmless. Some of the widely used helper methods in JDK library produce such warnings which are useless and requires the client code to explicitly suppress them at the call site, if you hate them.

  • public static List Arrays.asList(T… a)
  • public static boolean Collections.addAll(Collection c, T… elements)
  • public static > EnumSet EnumSet.of(E first, E… rest)

The Coin varargs improvement adds a new @Documented annotation type, java.lang.SafeVararags, that can be used at the declaration site to suppress unchecked warnings for certain varargs invocations which are considered safe such as the ones listed above.

When the JDK libraries are retrofitted to take advantage of this new annotation type, client code can safely remove any SuppressWarnings annotation from the call site. For example, Arrays.asList() would carry this special annotation that reduces these warnings at the call site.

  @SafeVarargs
  public static <T> List<T> asList(T... a) {
    return new ArrayList<T>(a);
  }

In addition to this annotation type, a new mandatory compiler warning “Possible heap pollution from parameterized vararg type : {0}” is generated on declaration sites of problematic varargs methods that are able to induce contributory heap pollution. To illustrate this, let us look at Alex Miller’s generics puzzler code below.

//[unchecked] Possible heap pollution from parameterized vararg type T[]
  public static <T> T[] mergeArrays2(T[]... arrays) {
      List<T> result = new ArrayList<T>();

      for(T[] array : arrays) {
          for(T item : array) {
              result.add(item);
          }
      }
      // BROKEN: This generates a compiler warning about checking against an erased type
      return (T[])result.toArray();
  }

This code would cause a ClassCastException at runtime and the warning generated by the compiler is indeed legitimate, so this is a case where the warning should never be suppressed and should be fixed. I believe there are couple different ways to solve this puzzle (details in Alex’s blog comments), but the recommended approach is to prefer collections to arrays when designing APIs (as in Puzzle #3 in the recent installment of Java Puzzlers from Josh Bloch and Bob Lee).

The solution outlined below requires the caller to provide a hint on the return type, which is kind of ugly, but works.

  @SafeVarargs
  static <T, U extends T> T[] mergeArrays(T[] returnType, U[]... arrays) {
    Class<?> componentType = returnType.getClass().getComponentType();
    // Determine total length
    int length = 0;
    for (T[] a : arrays) {
      length += a.length;
    }
    @SuppressWarnings(value = "unchecked")
    T[] result = (T[]) Array.newInstance(componentType, length);
    int j = 0;
    for (T[] anArray : arrays) {
      for (T element : anArray) {
        result[j++] = element;
      }
    }
    return result;
  }

If you notice, the use of @SafeVarargs annotation at the declaration site is valid since we have fixed the underlying problem of creating type safe array. The unsafe casting at line#10 when reflectively creating an array instance is harmless, so we can suppress that unchecked warning too.

The client code that invokes this method using a String array and an Integer array is shown below:

    String[] s1 = new String[]{"one", "two", "three"};
    String[] s2 = new String[]{"four", "five", "six"};
    String[] s3 = new String[]{"seven", "eight", "nine"};
    String[] sHint = new String[]{};
    String[] sMerged = mergeArrays(sHint, s1, s2, s3);
    System.out.println(Arrays.toString(sMerged));
//Output: [one, two, three, four, five, six, seven, eight, nine]
    Integer[] i1 = new Integer[]{1, 2, 3};
    Integer[] i2 = new Integer[]{4, 5, 6};
    Integer[] i3 = new Integer[]{7, 8, 9};
    Integer[] iHint = new Integer[]{};
    Integer[] iMerged = mergeArrays(iHint, i1, i2, i3);
    System.out.println(Arrays.toString(iMerged));
//Output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

@SafeVarargs Applicability

This annotation type is applicable to Constructor and Method types only as defined by the Target meta-annotation. Here is the specification copied from the javadoc of @SafeVarargs which clearly outlines its scope and requirements in detail.

In addition to the usage restrictions imposed by its @Target meta-annotation, compilers are required to implement additional usage restrictions on this annotation type; it is a compile-time error if a method or constructor declaration is annotated with a @SafeVarargs annotation, and either:

  • the declaration is a fixed-arity method or constructor
  • the declaration is a variable-arity method that is neither static nor final.

Compilers are encouraged to issue warnings when this annotation type is applied to a method or constructor declaration where:

  • The variable-arity parameter has a reifiable element type, which includes primitive types, Object, and String. (The unchecked warnings this annotation type suppresses already do not occur for a reifiable element type.)
  • The body of the method or constructor declaration performs potentially unsafe operations, such as an assignment to an element of the variable-arity parameter’s array that generates an unchecked warning.

Another important thing Joe clarified regarding overriding on coin-dev: “As documented in its specification, the SafeVarargs annotation is only applicable to static methods, final instance methods, and constructors; therefore, overriding does not occur. Annotation inheritance only works on classes (not methods, interfaces, or constructors) so without changing annotation inheritance, a SafeVarargs-style annotation cannot be passed through general instance methods in classes or through interfaces.”

Conclusion

I think the Coin chapter for Java 7 has come to an end. Now, what is pending is the dogfooding, which has already begun as JDK libraries are getting a dose of Coin in form of Diamond finishings. IDEs are gearing up support for these new language features. Both, NetBeans 7 Beta and IntellijIDEA 10 has a decent support for some of the Project Coin features. The ride with Project Coin has been an exciting one so far. Hope you all enjoyed exploring these cool new Java 7 features with me; why wait, mint yours today 🙂

Possibly Related Posts:


Recently I started developing some custom Flux plugins I wanted to share with Flux users. It is always fun to develop custom plugins and use them within a Flux workflow. Our users are more used to the concept of custom actions and triggers. I believe plugin is a more generic and widely used terminology these days. Flux 7.10 ships over 50 built-in plugins (actions/triggers) which covers most of the common customer requirements (ex: TimerTrigger, ProcessAction, MailAction, Split, Join, etc and a slew of File based triggers and actions). Writing your own is a child’s play as Flux uses plain-old JavaBean framework to build custom actions/triggers that can be used seamlessly in your workflows. Some of our customers write their own based on their requirements and sometimes we quickly develop one for them. You just need a Java API (Ex: RabbitMQ integration) or an HTTP interface (Ex: Twitter integration) to build one yourself.

Custom plugins make it lot easier to manage your workflow integration points with external systems and enjoy load of Flux benefits like scheduling, file transfer, error handling, variable substitution, runtime data mapping, job dependencies, and the most important real-time monitoring from within a web browser.

Developing applications around Twitter is always fun with their well documented REST APIs. Twitter notification plugin supports OAuth for authentication when accessing protected resources and does all the magic behind the scenes without any user intervention for getting OAuth access token and invoking the protected resource.

The next thing I developed was a messaging plugin based on RabbitMQ. RabbitMQ is a popular high-performant AMQP implementation built using erlang. Using RabbitMQ plugin, users can publish and consume messages from its queue and it supports variety of topologies (fanout, direct, etc). RabbitMQ provides a decent Java API to interface with the broker and integrating it with Flux is no brainer. Now comes the interesting part, I need to show something so I can keep my long story short 🙂

Here is a simple Flux web designer screenshot of Twitter plugin configured to send a direct message to a user:

Here is a simple Flux web designer screenshot of RabbitMQ plugin configured to publish message to a queue:.

Here is a simple Flux web designer screenshot of Twitter plugin configured to consumes messages from a queue:

The next thing you may want to do is to try out yourself. Maven users should include these dependencies in your POM.

<dependency>
  <groupId>flux</groupId>
  <artifactId>flux</artifactId>
  <version>7.10.1</version>
</dependency>
<dependency>
  <groupId>flux</groupId>
  <artifactId>rabbitmq-action</artifactId>
  <version>1.0.0</version>
</dependency>
<dependency>
  <groupId>flux</groupId>
  <artifactId>rabbitmq-trigger</artifactId>
  <version>1.0.0</version>
</dependency>
<dependency>
  <groupId>flux</groupId>
  <artifactId>twitter-action</artifactId>
  <version>1.0.0</version>
</dependency>

And, add the following repository to your repositories tag in your POM.

<repository>
  <id>maven2-repository.dev.java.net</id>
  <name>Java.net Repository for Maven</name>
  <url>http://download.java.net/maven/2/</url>
  <layout>default</layout>
</repository>

Non-maven users can download it from the project website. If you wish to use the Java APIs, here are some examples to get started. Complete examples are available in the source repository.

Publishing an AMQP message to a RabbitMQ channel would look something like this using Java API:

FlowChart flowChart = helper.makeFlowChart("RabbitMQ Action Example");
RabbitMQActionFactory customActionFactory = (RabbitMQActionFactory) flowChart.makeFactory("RabbitMQActionFactory");
RabbitMQAction rabbitMQAction = customActionFactory.makeRabbitMQAction("Publish AMQP Message");
rabbitMQAction.setHost("localhost");
rabbitMQAction.setUsername("guest");
rabbitMQAction.setPassword("guest");
rabbitMQAction.setExchangeName("nasdaq.exchange");
rabbitMQAction.setExchangeType("direct");
rabbitMQAction.setQueueName("nasdaq.request");
rabbitMQAction.setQueueType("shared");
rabbitMQAction.setRoutingKey("nasdaq.request");
rabbitMQAction.setMessage("BUY GOOG 200");

//Schedule this job
String name = engine.put(flowChart);

Consuming a message using RabbitMQTrigger which monitors for messages in the RabbitMQ queue would look something like this using Java API:

FlowChart flowChart = helper.makeFlowChart("RabbitMQ Trigger Example");
RabbitMQTriggerFactory customTriggerFactory = (RabbitMQTriggerFactory) flowChart.makeFactory("RabbitMQTriggerFactory");
RabbitMQTrigger rabbitMQTrigger = customTriggerFactory.makeRabbitMQTrigger("Consume AMQP Message");
rabbitMQTrigger.setHost("localhost");
rabbitMQTrigger.setUsername("guest");
rabbitMQTrigger.setPassword("guest");
rabbitMQTrigger.setQueueName("nasdaq.request");

JavaAction messageProcessor = flowChart.makeJavaAction("Message Processor");
messageProcessor.setListener(MessageProcessor.class);

rabbitMQTrigger.addFlow(messageProcessor);

//loop back required for polling
messageProcessor.addFlow(rabbitMQTrigger);

//Schedule this job
String name = engine.put(flowChart);

Twitter plugin allows to access OAuth protected resources. For example, retrieving twitter mentions would look something like this using Java API:

FlowChart flowChart = helper.makeFlowChart("Twitter Action Example");
TwitterActionFactory customActionFactory = (TwitterActionFactory) flowChart.makeFactory("TwitterActionFactory");
TwitterAction twitterMentions = customActionFactory.makeTwitterAction("Twitter Action");
twitterMentions.setConsumerKey(CONSUMER_KEY);
twitterMentions.setConsumerSecret(CONSUMER_SECRET);
twitterMentions.setOAuthEnabled(true);
twitterMentions.setRequestMethod(RestActionType.GET);
twitterMentions.setResourceUrl("http://api.twitter.com/1/statuses/mentions.json");
twitterMentions.setUsername(TWITTER_USER);
twitterMentions.setPassword(TWITTER_PASS);

//Schedule this job
engine.put(flowChart);

For example, sending a direct message would look something like this using Java API:

TwitterAction directMessage = customActionFactory.makeTwitterAction("Twitter DM");
directMessage.setConsumerKey(CONSUMER_KEY);
directMessage.setConsumerSecret(CONSUMER_SECRET);
directMessage.setOAuthEnabled(true);
directMessage.setRequestMethod(RestActionType.POST);
directMessage.setResourceUrl("http://api.twitter.com/1/direct_messages/new.xml");
directMessage.setUsername(TWITTER_USER);

//add the required parameters
Properties properties = new Properties();
properties.put("screen_name", "fluxarul");
properties.put("user_id", "97133917");
properties.put("text", "Hello from Flux Twitter Action!");

directMessage.setParameters(properties);
directMessage.setPassword(TWITTER_PASS);

//Schedule this job
engine.put(flowChart);

The Flux plugins project is hosted at bitbucket.org. Feel free to check it out, shout should you have any feedback or log an issue for bugs/improvements or support for additional plugins.

Possibly Related Posts:


Last November, Mark Reinhold announced that Closures will be added to the Java language and six months later we had an initial prototype based on the Straw-Man proposal and last month’s update was considered a significant progress for the language in years. As mentioned in Mark’s post, “Working with parallel arrays in Java, unfortunately, requires lots of boilerplate code to solve even simple problems. Closures can eliminate that boilerplate.” In my earlier post, I discussed how Lambda expressions make Aggregate operations a breeze to work with in Java. But, we still lack parallel looping constructs such as parallel for, foreach APIs that would take advantage of the multi-core machines we have today.

In this next Lambda adventure, I will be revisiting the Parallel ForEach example discussed by Howard in his “New Control Structures for Java” post, where he explains the use of anonymous inner classes to map a function that executes in parallel and retains the order of the original map, handles exceptions and implements continue operation. Here is the anonymous inner class version of the code:

The program produces the below output:

{1=H, 2=e, 3=l, 4=l, 5=o}

Now, that we have a working Lambda prototype, this code could be modified to take advantage of Lambda expressions. Let us enable the Lambda finder option in the compiler that identifies potential candidates for converting an anonymous inner class instance to an Lambda expression. Here is the updated javac.bat used to run with the latest prototype compiler.

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar com.sun.tools.javac.Main -XDidentifyLambdaCandidate=true %1

Compiling Parallel.java with this hidden compiler option identifies 2 candidates for Lambda expressions.

C:\JDK7\lambda\samples&gt;javac.bat Parallel.java
Parallel.java:16: Note: This anonymous inner class creation can be turned into a lambda expression.
            return new Callable&lt;O&gt;() {
                                     ^
Parallel.java:70: Note: This anonymous inner class creation can be turned into a lambda expression.
        final ForEach&lt;Character, Integer, Character&gt; trim = new ForEach&lt;Character, Integer, Character&gt;() {
C:\JDK7\lambda\samples&gt;

Let us quickly refactor Howard’s code using Lambda expressions and here is my take.

This version does not significantly change from its anonymous counterpart, it reduces at most 10 lines of code. But, it introduces two important concepts in addition to use of Lambda expressions. Lines 6 and 13 uses the new exception transparency mechanism and Line 62 shows how lexical scoping makes Lambda expressions different from anonymous inner classes.

Exception Transparency

Exception transparency is a new feature proposed as part of the umbrella Lambda proposal. While this feature is not required to support Lambda expressions, it is useful in library implementations that require abstraction over generic exceptions. Java Generics does a decent job at abstracting over method return types and argument types, leaving abstraction over types of checked exceptions in limbo. This makes it difficult for libraries to support generic exception types in APIs. The two extreme cases where libraries usually model their exception types are :

In case of Runnable, the run() method throws nothing.

public interface Runnable {
    public abstract void run();
}

In case of Callable, the call() method throws everything.

public interface Callable<V> {
    V call() throws Exception;
}

As more and more libraries would take advantage of executing Lambda expressions as a block of code, the inability to generify thrown exception types makes this proposal a compelling use case.

A throws type parameter is a generic type parameter that is introduced with the keyword throws; throws type parameters implicitly have an upper bound of Exception (though any upper bound that is a subtype of Throwable may be explicitly specified) and can correspond to zero or more actual types that are subtypes of the upper bound.

With this support in the language, we should be able to abstract generic exception types:

	interface Block<throws E> {
		public void execute() throws E;
	}

Lexical scoping

Unlike anonymous inner classes, lambda expressions are lexically scoped. This means that code inside the Lambda body sees only what is available immediately outside the lambda expression. For instance, access to names from inherited classes/interfaces is not allowed as seen in Line #62 of our example above.

I wanted to briefly touch upon these concepts that are relevant to our discussion. Please refer to the proposal for more details.

.NET world

Let us look at how modern languages support Parallelism in their libraries. Here is an closest example using C# Task Parallel Library (TPL) (from Patterns of Parallel Programming Guide).

But this is just an attempt if someone wanted to write their own parallel foreach construct using existing C# APIs. But, this is not required. In C#, parallel constructs are available for a while now. Using the Parallel.ForEach construct in TPL, iterating all the Test records of a Student and calculate the GPA would look something like:

Fair enough, this construct is concise and abstracts all the machinery from the Client code. Are we close enough to get a similar construct in Java? I think so, we do have parallel collections library that supports parallelism using Fork-Join framework today. It looks like Doug Lea has recently revealed his plans for developing new library components for parallel operations on aggregates (collections and arrays) for JDK8 (based on proposed language support for lambdas). I believe this effort would produce these constructs in Java.

For the sake of fun, I compiled the extry166y sources with the compiler option “-XDidentifyLambdaCandidate=true”, it identified 168 candidates that can be turned into a lambda expression. Less code means more fun and you see that for real.

Update (6/11/2011) : Updated the Parallel class (Lambda version) to compile with the latest lambda prototype compiler. Abstract classes with single abstract method are no longer considered valid SAM types as per the revised rules.

Possibly Related Posts:


One of the primary uses of Lambda expressions is to implement aggregate operations that can often be parallelized using multi-core processors we have today. The computation over bulk data structures is an area where Lambda expressions provide much needed support where part of the computation is caller defined. Doug Lea’s JSR166y Concurrency interest group exactly brings these rich set of Collections that supports parallel operations to perform bulk computation over data in the Java platform.

Let us look at an aggregate operations example using a ParallelArray, that maintains a ForkJoinPool and an array in order to provide parallel aggregate operations. The jsr166y package is already included in Java 7 as part of the ForkJoin framework. The extra166y package that contains Collections supporting parallel operations is not part of the JDK yet, but you should be able to use them today as an add-on library.

import extra166y.Ops;
import extra166y.ParallelArray;
import extra166y.ParallelDoubleArray;

public class AggregateOpsExample {

    ParallelArray<Student> students;

    public AggregateOpsExample() {
        jsr166y.ForkJoinPool fjPool = new jsr166y.ForkJoinPool();
        // Create a "fictional" Student array
        Student s1 = new Student("S1", 2010, 85, 5);
        Student s2 = new Student("S2", 2010, 91, 4);
        Student s3 = new Student("S3", 2010, 95, 3);
        Student[] data = new Student[]{s1, s2, s3};
        students = ParallelArray.createFromCopy(new Student[]{s1, s2, s3}, fjPool);
    }

    public Student getStudent(int index) {
        return students.get(index);
    }

    public double getMaxSeniorGpa() {
        return students.withFilter(isSenior)
        			   .withMapping(gpaField)
        			   .max();
    }

    public ParallelDoubleArray.SummaryStatistics getSummaryStatistics() {
        return students.withFilter(isSenior)
	                   .withMapping(gpaField)
        	           .summary();
    }

    // helpers:
    static final class IsSenior implements Ops.Predicate<Student> {
        public boolean op(Student s) {
            return s.credits > 90;
        }
    }

    static final IsSenior isSenior = new IsSenior();

    static final class GpaField implements Ops.ObjectToDouble<Student> {
        public double op(Student s) {
            return s.gpa;
        }
    }

    static final GpaField gpaField = new GpaField();

    public static void main(String[] args) {
        AggregateOpsExample test = new AggregateOpsExample();
        double bestGpa = test.getMaxSeniorGpa();
        System.out.println("Best GPA : " + bestGpa);
        ParallelDoubleArray.SummaryStatistics summary = test.getSummaryStatistics();
        System.out.println("Last Best Student: " + test.getStudent(summary.indexOfMin()).name);
        System.out.println("Average GPA in class of 2010 : " + summary.average());
    }

    public class Student {
        String name;
        int graduationYear;
        int credits;
        double gpa;

        public Student(String name, int graduationYear, int credits, double gpa) {
            this.name = name;
            this.graduationYear = graduationYear;
            this.credits = credits;
            this.gpa = gpa;
        }
    }
}

In Line#10, a ForkJoinPool is created with parallelism equal to Runtime.availableProcessors(), in my case 2. Lines 24-26 and 30-32 perform aggregate operations on Students array. These operations take advantage of multi-core processors than the traditional sequential approach we used to filter and map a collection. By introducing Lambda expressions in the client code, you can remove much of the boilerplate in lines 36-50 in our code.

Let us build upon the above example to time these aggregate operations and erase some of the boilerplate using Lambda expressions.

import extra166y.Ops;
import extra166y.ParallelArray;
import extra166y.ParallelDoubleArray;

public class TimedAggregateOps {

	ParallelArray<Student> students;

	public TimedAggregateOps() {
		jsr166y.ForkJoinPool fjPool = new jsr166y.ForkJoinPool();
        // Create a "fictional" Student array
		Student s1 = new Student("S1", 2010, 85, 5);
		Student s2 = new Student("S2", 2010, 91, 4);
		Student s3 = new Student("S3", 2010, 95, 3);
		Student[] data = new Student[]{s1, s2, s3};
		students = ParallelArray.createFromCopy(new Student[]{s1, s2, s3}, fjPool);
	}

	interface Block {
		public void execute();
	}

	static void time(boolean maxGpa, Block block) throws Exception {
		long startTime = System.nanoTime();
		boolean success = true;
		try {
			block.execute();
		} catch (final Throwable ex) {
			success = false;
			throw ex;
		} finally {
			recordTiming(maxGpa, System.nanoTime() - startTime, success);
		}
	}

	static void recordTiming(boolean maxGpa, long nanoseconds,  boolean succeeded) {
		if (maxGpa) {
			System.out.println("maxGpa took " + nanoseconds + "ns and operation " + (succeeded ? "succeeded." : "failed."));
		} else {
			System.out.println("avgGpa took " + nanoseconds + "ns and operation " + (succeeded ? "succeeded." : "failed."));
		}
	}

    static final Ops.Predicate<Student> isSenior = #{s -> s.credits > 90};
    static final Ops.ObjectToDouble<Student> gpaField = #{s -> s.gpa};

    public void findMaxSeniorGpa() {
        double maxGpa = students.withFilter(isSenior)
        						.withMapping(gpaField)
        						.max();
        System.out.println("Maximum GPA : " + maxGpa);
    }

    public void findAverageGpa() {
        ParallelDoubleArray.SummaryStatistics summary = students.withFilter(isSenior)
                												.withMapping(gpaField)
                												.summary();
		double avgGpa = summary.average();
		System.out.println("Average GPA : " + avgGpa);
    }

	void test(boolean maxGpa) throws Exception {
		try {
			time(maxGpa, #{
				if (maxGpa)
					findMaxSeniorGpa();
				else
					findAverageGpa();
			});
		} catch (final Throwable t) {
			throw t;
		}
	}

	public static void main(String[] args) throws Exception {
		TimedAggregateOps tao = new TimedAggregateOps();
		tao.test(true);
		tao.test(false);
	}
}

The client code that consumes this parallel Collections library has become more concise and removes much of the boilerplate with the use of Lambda expressions. Lines 36-50 in the earlier example is reduced to Lines 44-45 in this example. When these libraries take advantage of Lambda expressions, implementations would become powerful and more efficient. For example, much of the today’s verbose APIs such as map, reduce, filter defined in ParallelArray class would benefit from executing block of code using Lambda expressions. I recommend watching Closures Cookbook JavaOne 2008 presentation from Neal Gafter.

You can run this example using the prototype compiler that supports Lambda expressions. The batch scripts used in my original post should be updated to include JSR166y libraries in classpath, which you could download from JSR-166 maintenance website.

javac.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar;jsr166y.jar;extra166y.jar com.sun.tools.javac.Main %1

java.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar;.;jsr166y.jar;extra166y.jar %1

Possibly Related Posts:


Recently, Brian Goetz published modified draft of the Lambda proposal. This draft is mature in terms of the direction where Lambda is heading for in the Java world and introduces some breaking changes from earlier draft to align with this direction. While there are few things that need to be sorted out, this draft is simple to understand, unlike the earlier proposals we have seen. Last week, Maurizio pushed an updated prototype that aligns with this new draft.

Lambdas (originally knows as Closures) are available in the form of anonymous inner classes in Java. Anonymous inner classes are a form of nested classes that has no name and exhibits the following behavior as detailed in JLS 15.9.5.

  • An anonymous class is never abstract
  • An anonymous class is always an inner class; it is never static
  • An anonymous class is always implicitly final

One common use of anonymous inner classes is to create function objects in Java on the fly. [Refer Item 21 in Effective Java 2nd Edition pg 103]

Let us look at sorting an array of strings based on its length using an anonymous Comparator instance.

        String[] teams = {"Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red"};
        Arrays.sort(teams, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        });

To create process objects, such as Runnable, Thread, or TimerTask instances.

        final ExecutorService executor = Executors.newCachedThreadPool();
        executor.submit(new Runnable() {
            @Override
            public void run() {
                System.out.println("Processing a short-lived asynchronous task.");
            }
        });

Anonymous classes have many limitations as outlined in Item 22 in Effective Java 2nd Edition [pg 108]. With Lambda expressions, you should be able to rewrite these samples more concisely eliminating the bulky syntax that comes with anonymous inner classes :

        final ExecutorService executor = Executors.newCachedThreadPool();
        // assignment context
        Runnable task = #{ System.out.println("Processing a short-lived asynchronous task.") }; //take1
        executor.submit(task);
        // cast target context
        task = (Runnable)#{System.out.println("Processing a short-lived asynchronous task.")}; //take 2
        executor.submit(task); 
        // method invocation context
        executor.submit((Runnable)#{System.out.println("Processing a short-lived asynchronous task.")}); //take 3

Array sorting using a comparator with Lambda expressions is a one liner:

	String[] teams = {"Violet", "Indigo", "Blue", "Green", "Yellow", "Orange", "Red"};
	final Comparator<String> c = #{s1, s2 -> s1.length() - s2.length()};
	Arrays.sort(teams, c); //take1
	Arrays.sort(teams, #{s1, s2 -> s1.length() - s2.length()}); //take 2

So, what next? Let us do some hands-on with these Lambdas and explore what Lambdas has to offer for Java developers. I setup the new prototype on my Windows environment following Remi’s instructions. It was fairly straight forward (all you need is Mercurial Client, Apache Ant, and latest JDK 7 build).

Here is a simple build script (build.bat) I used in Windows, that you can place in the “make” sub-directory under “langtools” :

ant -Dboot.java.home=C:\jdk1.7.0 clean build

This would create classes.jar under “dist\lib” sub-directory. You need to place this jar in your classpath when using the prototype.

You can use the following batch scripts for compiling and running your Lambda examples. I tested with the recent JDK 7 build (b115).

javac.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar com.sun.tools.javac.Main %1

java.bat

@echo off
C:\jdk1.7.0\bin\java.exe -cp classes.jar;. %1

It is required to include classes.jar in the classpath due to runtime dependencies that are not available in the binary build. To make sure if you are running the prototype compiler, the output should show “internal” tag:

C:\JDK7\lambda\samples>javac.bat -version
javac 1.7.0-internal

Let us look at a simple example:

public class SimpleLambda {
	abstract class HelloWorld {
		abstract void greet();
	}
	{
		HelloWorld greeting = #{ System.out.println("Hello World!") };//nilary Lambda expression
		greeting.greet();
	}
	public static void main(String[] args) {
		new SimpleLambda();
	}
}

To compile this example:

javac.bat SimpleLambda.java

To run this example:

java.bat SimpleLambda

Voila, you ran your first lambda example successfully if you see “Hello World!” output.

Let us look at another example which uses parameterized types in this case.

	interface Squarer<X, Y> {
		Y square(X x);
	}
	{
		Squarer<Integer, Integer> s = #{ Integer x -> x * x };// 1-ary Lambda expression
		System.out.println(s.square(5));
	}

In both these examples, you notice a pattern commonly referred to as single abstract method (SAM), defined using an interface or an abstract class with exactly one abstract method. This is a structural property identified by the compiler and it does not take into account methods inherited from java.lang.Object (as in java.util.Comparator).

For example, Runnable, Callable, etc belongs to this category of SAM types that can be converted in the context of assignment as shown below.

final Runnable task = #{ System.out.println(“Processing a short-lived asynchronous task.”) };

In this code, “task” is an Runnable instance, while the lambda expression #{…} is not. Only after conversion, the target type becomes an instance of that SAM type.

Syntax – The Holy Grail of Lambda


Lambda expressions begin with ‘#’ special character and an arrow token ‘->’ is used to separate the formal parameters from the body of the Lambda. In case of single line Lambda expression, return keyword and trailing semicolon can be omitted. For nilary Lambda expression, the arrow token can be omitted.

Lambdas in Java exhibit the following behavior :

  • An interface, or abstract class, with exactly one abstract method are referred to as a SAM types.
  • Lambdas are not instances of classes.
  • Lambdas are converted to SAM types.
  • SAM types are instances of classes.
  • Lambdas are lexically scoped.

Lambda definition (excerpt from draft)

A lambda expression e is convertible-to a SAM type S if an anonymous inner class that is a subtype of S and that declares a method with the same name as S’s abstract method and a signature and return type corresponding to the lambda expressions signature and return type would be considered assignment-compatible with S.

The return type and exception types of a lambda expression are inferred by the compiler; the parameter types may be explicitly specified or they may be inferred from the assignment context.

The type of a formal parameter can be omitted, in which case the compiler will infer a type from the target type of the lambda conversion. Let us see couple examples where the types are inferred by the compiler.

	enum Decision {
	    APPROVE, DECLINE, APPROVE_REFER
	}

	abstract class DecisionService {
	    abstract Decision getRiskDecision(Applicant applicant);
	}

	class Applicant {
		private int score;
		public Applicant(int score) {
			this.score = score;
		}
		public int getScore() {
			return score;
		}
	}

	public void test() {
		DecisionService cs = #{ a ->
								if (a.getScore() > 700) {
									return Decision.APPROVE;
								} else if (a.getScore() > 600 && a.getScore() < 650) {
									return Decision.APPROVE_REFER;
								} else {
									return Decision.DECLINE;
								}
							};
		Decision decision = cs.getRiskDecision(new Applicant(800));
		System.out.println(decision.toString());
	}

In line #20 above, the type of the formal parameter Applicant is inferred by the compiler.

	class Payment {
		private int amount;
		Payment(int amount) {
			this.amount = amount;
		}
		public int getAmount() {
			return amount;
		}
	}
	interface PaymentProcessor {
		void process(Payment pmt);
	}
	{
		invokeProcessor(#{pmt -> log("Processed # " + pmt.getAmount() + " at " + new Date())});
	}
	void invokeProcessor(PaymentProcessor processor) {
		processor.process(new Payment(42));
	}

In line #14, the type of the formal parameter Payment is inferred by the compiler.

Extension Methods

One of the significant benefits of Lambdas is that it enables the development of more powerful libraries with less code and more efficiency. To enhance the core libraries to take advantage of these powerful language features without compromising backward compatibility, the concept of public defender methods was introduced. This proposal suggests adding virtual extension methods to existing interfaces allowing the use of new language features to enhance the capabilities of core libraries.

While, extension methods by itself is more useful and when combined with Lambdas, they can be powerful. The traditional way of sorting a collection.

        Collections.sort(people, new Comparator<Person>() {
            public int compare(Person x, Person y) {
                return x.getLastName().compareTo(y.getLastName());
            }
        });	        

With Lambdas, this can be expressed more concisely (this works with the prototype).

Collections.sort(people, #{ x, y -> x.getLastName().compareTo(y.getLastName()) });

And this still leaves room for improvement where virtual extension methods come to rescue. When core libraries are enhanced to take advantage of Lambda expressions, this can be made less verbose.

people.sortBy(#Person.getLastName);

Virtual extension methods are declared using the ‘extension’ keyword.

public interface List<T> extends Collection<T> {
	// .... The existing List methods 
  	extension void sort() default Collections.sort;
}

When Collections library is enhanced to support extensions methods, we should be able to use many of the Collections APIs directly in a collection:

List.sort();
//instead of
Collections.sort(List);

Some of these minor improvements are most sought after and makes Java less verbose and one less class to deal with.

Conclusion

I haven’t touched upon other fundamental concepts such as Exception transparency, Method references and Lexical Scoping. I will be covering them once I do some hands-on with these concepts. The prototype is still evolving around these areas and has made some good progress in catching up with this new draft. As we know, Lambdas are scheduled to go in Java 8 (in late 2012), almost six years after Closures were originally proposed in 2006. I believe there are plans to make binary builds available for all platforms, so the hassle of building from the source would no longer be required.

[Photo credit: http://www.lumaxart.com/]

Update (10/25/2010) : Omitted the use of optional trailing semicolon and return keyword in single line Lambda expressions.

Update (6/11/2011) : The definition of SAM types have changed since this post was originally written. Here is the latest definition.

SAM types:
1. An interface that has a single abstract method
2. Having more than one distinct methods, but only one is “real”, the others are overridden public methods in Object – example:

Comparator<T>

3. Having more than one methods due to inheritance, but they have the same signature
4. Having more than one methods due to inheritance, but one of them has a sub-signature of all other methods

    a) parameter types compatible
    b) return type substitutable
    c) thrown type not conflicting with the thrown clause of any other method
    d) mixed up

5. Type-dependent SAM types

non-SAM types:
6. An interface that has a single abstract method, which is also public method in Object
7. Having more than one methods due to inheritance, and none of them has a sub-signature of all other methods

With these new rules, some of the examples won’t compile. Abstract classes with single abstract method are no longer considered valid SAM types. Switching to an interface should fix these examples.

Possibly Related Posts:


There are two features that are very cool in the recent CXF 2.3 release that deserves its mention in the release notes/features document as they prove to be quite useful and powerful in certain use cases. Advanced search capabilities and Atom Logging features make CXF a compelling choice for developers looking for this support in JAX-RS frameworks. I first read about these features when Sergey introduced their availability in 2.3 snapshots.

In this post, I am going to explore FIQL based advanced search query support in CXF. I have experimented Atom logger before and it deserves a separate blog post and when used with FIQL, they are more powerful.

Introduction to FIQL Expressions in CXF

The Feed Item Query Language (FIQL, pronounced “fickle”) is a draft specification by Mark Nottingham that proposes URL-friendly syntax for expressing filters that operate on the feed entries. An FIQL expression is composed of one or more constraints, related to each other with Boolean operators. FIQL expressions yield Boolean values: True or False.

Let us look at each of the operators defined in the draft spec with an example FIQL expression and the equivalent SQL query produced by CXF.

Two boolean operators:
“;” is the Boolean AND operator; it yields True for a particular entry if both operands evaluate to True, otherwise False.

/sakila/searchActors?_s=firstname==PENELOPE;lastname==GUINESS
SELECT * FROM actor WHERE lastname = 'GUINESS' AND firstname = 'PENELOPE'

“,” is the Boolean OR operator; it yields True if either operand evaluates to True, otherwise False.

/sakila/searchActors?_s=lastname==MONROE,lastname==GUINESS
SELECT * FROM actor WHERE (lastname = 'MONROE') OR (lastname = 'GUINESS')

Two comparison operators are applicable to simple text comparisons:
“==” yields True if the string value (as per XPath) of any selected node matches the argument; otherwise False.

/sakila/searchActors?_s=lastname==MONROE
SELECT * FROM actor WHERE lastname = 'MONROE'

“!=” yields True if the string value of every selected node does not match the argument; otherwise False.

/sakila/searchActors?_s=lastname!=MONROE
SELECT * FROM actor WHERE lastname <> 'MONROE'

If the argument string begins or ends with an asterisk character (“*”), it acts as a wild card, matching any characters preceding or following (respectively) that position.

/sakila/searchActors?_s=lastname==PEN*
SELECT * FROM actor WHERE firstname LIKE 'PEN%'

[Note: The spec mentions that text comparisons should allow case insensitive textual content. CXF text comparison is case sensitive.]

Four operators are relevant to date comparisons:
“==” yields True if the point in time specified in the argument matches that indicated by the string-value of the selected node; otherwise False.

/sakila/searchRentals?_s=returndate==2005-08-31T20:00:25.000%2B06:00
SELECT * FROM rental WHERE returndate = 'Wed Aug 31 08:00:25 MDT 2005'

[Note: The database contains the following timestamp for the returndate ‘2005-08-31T20:00:25-06:00’, but when I query this using the above FIQL expression, it returned no matching entry. I tried another similar expression with no success: /sakila/searchRentals?_s=returndate==2005-08-31T20:00:25Z]

“!=” yields True if the point in time specified in the argument does not match that indicated by the string-value of the selected node; otherwise False.

/sakila/searchRentals?_s=returndate!=2005-08-31T20:00:25.000%2B06:00
SELECT * FROM rental WHERE returndate <> 'Wed Aug 31 08:00:25 MDT 2005'

“=lt=” yields True if the point in time specified in the argument follows that indicated by the string-value of the selected node; otherwise False.

/sakila/searchRentals?_s=rentaldate=lt=2005-05-27T00:00:00.000%2B00:00
SELECT * FROM rental WHERE rentaldate < 'Thu May 26 18:00:00 MDT 2005'

“=le=” yields True if the point in time specified in the argument follows that indicated by the string-value of the selected node, or is equal to it; otherwise False.

/sakila/searchRentals?_s=returndate=le=2005-05-27T00:00:00.000%2B00:00
SELECT * FROM rental WHERE returndate <= 'Thu May 26 18:00:00 MDT 2005'

“=gt=” yields True if the point in time specified in the argument precedes that indicated by the string-value of the selected node; otherwise False.

/sakila/searchRentals?_s=returndate=gt=2005-08-30T00:00:00.000%2B00:00
SELECT * FROM rental WHERE returndate > 'Mon Aug 29 18:00:00 MDT 2005'

“=ge=” yields True if the point in time specified in the argument precedes that indicated by the string-value of the selected node, or is equal to it; otherwise False.

/sakila/searchRentals?_s=returndate=ge=2005-09-01T00:00:00.000%2B00:00
SELECT * FROM rental WHERE returndate >= 'Wed Aug 31 18:00:00 MDT 2005'

Some advanced FIQL expressions prove to be very powerful when dealing with date range and relative comparison:

/sakila/searchRentals?_s=returndate=gt=%2DP5Y2M
SELECT * FROM rental WHERE returndate > 'Wed Aug 17 14:53:44 MDT 2005'
 (assuming processing on Oct 17th, 2010)

/sakila/searchRentals?_s=returndate=ge=2005-05-27T00:00:00.000%2B00:00;rentaldate=le=2005-06-27T00:00:00.000%2B00:00
SELECT * FROM rental WHERE rentaldate <= 'Sun Jun 26 18:00:00 MDT 2005' AND returndate >= 'Thu May 26 18:00:00 MDT 2005'

Four operators are relevant to numeric comparisons:

“==” yields True if the string-value of the selected node is numerically equal to the argument; otherwise False.

/sakila/searchFilms?_s=filmid==1;rentalduration!=0
SELECT * FROM film WHERE filmid = '1' AND rentalduration <> '0'

“!=” yields True if the string-value of the selected node is not numerically equal to the argument; otherwise False.

/sakila/searchFilms?_s=filmid!=1;rentalduration!=0
SELECT * FROM film WHERE filmid <> '1' AND rentalduration <> '0'

“=lt=” yields True if the string-value of the selected node evaluates as numerically less than the argument; otherwise, False.

/sakila/searchFilms?_s=filmid=lt=2;rentalduration!=0
SELECT * FROM film WHERE filmid < '2' AND rentalduration <> '0'

“=le=” yields True if the string-value of the selected node evaluates as numerically less than the argument, or as equal to it; otherwise, False.

/sakila/searchFilms?_s=filmid=le=2;rentalduration!=0
SELECT * FROM film WHERE filmid <= '2' AND rentalduration <> '0'

“=gt=” yields True if the string-value of the selected node evaluates as numerically greater than the argument; otherwise, False.

/sakila/searchFilms?_s=filmid=gt=995;rentalduration!=0
SELECT * FROM film WHERE filmid > '995' AND rentalduration <> '0'

“=ge=” yields True if the string-value of the selected node evaluates as numerically greater than the argument, or as equal to it; otherwise, False.

/sakila/searchFilms?_s=filmid=ge=995;rentalduration!=0
SELECT * FROM film WHERE filmid >= '995' AND rentalduration <> '0'

I believe this covers majority of the FIQL operators used in various proportions as documented in the spec and these FIQL expressions are not just examples, all of these searches can be tested with our sample Sakila database.

Sakila Database

Sakila is a MySQL sample database that represents a DVD rental store and comes with some useful data. This is handy for demonstrations and the schema is well designed. I will be using this sample database to demonstrate the advanced search capabilities using CXF. Java IDEs provide a decent support to reverse engineer JPA entities from a database schema. Here is one which walks through creating JPA entities using a NetBeans IDE from the Sakila database. I will be using these generated entities in this example with Hibernate as the JPA provider. The entire example is available as a maven project in Git, so feel free to check this out.

The meat of this example lies in the SakilaResource implemented as a CXF JAX-RS endpoint. In this code, a SearchContext is injected to the resource which will be used in the resource methods to get the SearchCondition specified in the query. FiqlParser does the magic for you in parsing an FIQL expression to construct these search conditions.

@Path("/sakila")
public class SakilaResource {

    @Context
    private SearchContext searchContext;

    List<Actor> actors = new ArrayList<Actor>();
    List<Film> films = new ArrayList<Film>();
    List<Rental> rentals = new ArrayList<Rental>();

    public SakilaResource() {
       // JPA Plumbing omitted for clarity.
    }

    @GET
    @Produces("application/xml")
    @Path("searchActors")
    public List<Actor> searchActors() {
        SearchCondition<Actor> sc = searchContext.getCondition(Actor.class);

        if (sc == null) {
            throw new NotFoundException("Invalid search query.");
        }
        System.out.println(sc.toSQL("actor"));

        List<Actor> found = sc.findAll(actors);
        if (found.size() == 0) {
            throw new NotFoundException("No matching actor found.");
        }
        return found;
    }

    @GET
    @Produces("application/xml")
    @Path("searchFilms")
    public List<Film> searchFilms() {
        SearchCondition<Film> sc = searchContext.getCondition(Film.class);

        if (sc == null) {
            throw new NotFoundException("Invalid search query.");
        }
        System.out.println(sc.toSQL("film"));

        List<Film> found = sc.findAll(films);
        if (found.size() == 0) {
            throw new NotFoundException("No matching film found.");
        }
        return found;
    }

    @GET
    @Produces("application/xml")
    @Path("searchRentals")
    public List<Rental> searchRentals() {
        SearchCondition<Rental> sc = searchContext.getCondition(Rental.class);

        if (sc == null) {
            throw new NotFoundException("Invalid search query.");
        }
        System.out.println(sc.toSQL("rental"));

        List<Rental> found = sc.findAll(rentals);
        if (found.size() == 0) {
            throw new NotFoundException("No matching rental found.");
        }
        return found;
    }
}

One can think of FIQL based search support in CXF is somewhat similar to using Hibernate Search to query JPA entities. I think Hibernate Search is a heavy weight solution which uses Lucene as the search provider and it requires annotating your entities. FIQL support in CXF is light weight and implementing advanced search capabilities in resources is a child’s play. Unlike Hibernate Search, CXF FIQL cannot be used to perform joins on multiple entities as the FIQL spec was designed for syndication feed data model.

In CXF, there are couple options to test these search conditions and they are easy to develop. One approach is to use the search extension API. You can find an example in the javadoc of SimpleSearchCondition.

The other approach is the traditional CXF way of using HTTP centric WebClient.

public class SakilaSearchTest {

    static Server server;

    @BeforeClass
    public static void setUp() {
        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
        sf.setResourceClasses(SakilaResource.class);
        sf.getInInterceptors().add(new LoggingInInterceptor());
        sf.getOutInterceptors().add(new LoggingOutInterceptor());
        sf.setResourceProvider(SakilaResource.class, new SingletonResourceProvider(new SakilaResource()));
        sf.setAddress("http://localhost:9000");
        server = sf.create();
    }

    @Test
    public void searchActors() {
        //http://localhost:9000/sakila/searchActors?_s=firstname==PENELOPE
        WebClient wc = WebClient.create("http://localhost:9000/sakila/searchActors?_s=firstname%3D%3DPENELOPE");
        Collection<? extends Actor> actors = wc.getCollection(Actor.class);
        assertEquals(4, actors.size());
    }

    @Test
    public void searchFilms() {
        //http://localhost:9000/sakila/searchFilms?_s=rating==PG;rentalduration!=0;title==SANTA*
        WebClient wc = WebClient.create("http://localhost:9000/sakila/searchFilms?_s=rating%3D%3DPG;rentalduration%21%3D0;title%3D%3DSANTA*");
        Collection<? extends Film> films = wc.getCollection(Film.class);
        assertEquals(1, films.size());
    }

    @Test
    public void searchRentals() {
        //http://localhost:9000/sakila/searchRentals?_s=rentaldate=lt=2005-05-27T00:00:00.000%2B00:00
        WebClient wc = WebClient.create("http://localhost:9000/sakila/searchRentals?_s=rentaldate%3Dlt%3D2005-05-27T00:00:00.000%2B00:00");
        Collection<? extends Rental> rentals = wc.getCollection(Rental.class);
        assertEquals(278, rentals.size());
    }

    @AfterClass
    public static void tearDown() {
        server.destroy();
    }
}

One thing I noticed with WebClient is that I need to encode certain operators specified in the search condition and this is inconsistent when testing with a web browser. I would expect the java API should take care of this for you instead of providing partially encoded URLs. Also, the date comparison can be tricky, although it works for most cases discussed above.

Possibly Related Posts:


Project Coin includes the following proposals that will make into Java 7.

Binary literals and underscores in literals

Strings in switch

– Simplified Varargs Method Invocation

– Improved Type Inference for Generic Instance Creation (Diamond)

– Improved Exception Handling for Java

– try-with-resources (ARM)

I have briefly touched upon try-with-resources construct in my earlier post. ARM was implemented in July and JDBC APIs were recently retrofitted to support these changes. In this installment, I will give you an overview of other Coin proposals.

Binary literals and underscores in literals

This feature is again we are trying to catch up with languages such as Ruby and Python where this is already supported.

You need to prefix the literal with 0b or 0B. Now, we can define binary literals in our code as show below.

int maxInteger = 0b01111111111111111111111111111111;// Integer.toBinaryString(2147483647)
byte nybbles = 0b00100101;// Math.pow(2, 5)+Math.pow(2, 2)+Math.pow(2, 0) = 37

Now, this can be better represented visually using underscores, which is addressed in the supplementary proposal:

int maxInteger = 0b0111_1111_1111_1111_1111_1111_1111_1111;// Integer.toBinaryString(2147483647)
byte nybbles = 0b0010_0101;// Math.pow(2, 5)+Math.pow(2, 2)+Math.pow(2, 0) = 37

Some more common usage of this feature,

int phoneNumber = 123_456_7890;
long creditCardNumber = 1234_5678_9012_3456L;
int socialSecurityNumber = 999_99_9999;
int hexEquivalentOfIntegerMAX = 0x7f_ff_ff_ff;// Integer.toHexString(2147483647)
int hexBytes = 0xFF_EC_DE_5E;// Integer.toHexString(-1253794)
int hexWords = 0xFFEC_DE5E;// Integer.toHexString(-1253794)
long maxLong = 0x7fff_ffff_ffff_ffffL;// Long.toHexString(9223372036854775807L)
int weirdBitfields = 0b000_10_101;// Integer.toBinaryString(21)

System.out.println("The value 10100001 in decimal is " + 0B10100001);// 161

More advanced example (from the proposal), do you see the happy face in bitmap?

// Binary literals can be used to make a bitmap more readable:
public static final short[] HAPPY_FACE = {
       (short)0b0000011111100000,
       (short)0b0000100000010000,
       (short)0b0001000000001000,
       (short)0b0010000000000100,
       (short)0b0100000000000010,
       (short)0b1000011001100001,
       (short)0b1000011001100001,
       (short)0b1000000000000001,
       (short)0b1000000000000001,
       (short)0b1001000000001001,
       (short)0b1000100000010001,
       (short)0b0100011111100010,
       (short)0b0010000000000100,
       (short)0b0001000000001000,
       (short)0b0000100000010000,
       (short)0b0000011111100000
};

This feature was implemented more than a year ago.

Strings in switch

We are familiar with the purpose of switch and what types are allowed in them.

A simple example from the Joe Darcy’s JavaOne Coin presentation:

    GregorianCalendar c = new GregorianCalendar();
    int monthNameToDays(String s, int year) {
        switch (s) {
            case "April":
            case "June":
            case "September":
            case "November":
                return 30;
            case "January":
            case "March":
            case "May":
            case "July":
            case "August":
            case "December":
                return 31;
            case "February":
                int days = 28;
                days += c.isLeapYear(year) ? 1 : 0;
                return days;
            default:
                return -1;
        }
    }

Here is a more complex one with nested switch :

public class SwitchTest {
    private static class Member {
        int id;
        String type;
        String category;

        private Member(int id, String type, String category) {
            this.id = id;
            this.type = type;
            this.category = category;
        }
    }

    public static int getMemberFee(Member member) {
        int fee = 50;
        switch (member.type) {
            case "BUSINESS":
                switch (member.category) {
                    case "LICENSED":
                    case "GOVERNMENT":
                    case "FARMERS":
                    case "RANCHERS":
                        break;

                    case "NON_PROFIT":
                        fee = 25;
                }
            case "GOLD_STAR":
                break;
            case "EXECUTIVE":
                fee = 100;
                break;
        }
        return fee;
    }

    public static int getMemberDiscount(Member member) {
        int discount = 5;
        switch (member.type) {
            case "BUSINESS":
                discount = 10;
                //fall through
            case "GOLD_STAR":
                break;
            case "EXECUTIVE":
                discount = 15;
                break;
        }
        return discount;
    }

    public static void main(String... args) {
        Member member = new Member(1234_5678_90, "BUSINESS", "NON_PROFIT");
        System.out.println("$" + SwitchTest.getMemberFee(member) + " fee for " + member.category);
        System.out.println(SwitchTest.getMemberDiscount(member) + "% discount for " + member.category);
    }
}

This feature was implemented almost a year ago.

Simplified Varargs Method Invocation

Before going into the details of this proposal, I would like to provide some background so it helps to understand the problem better. One of the well known restrictions introduced by Generics is its inability to create generic arrays. For example, the following code would not compile in Java:

    public static List<String>[] mergeLists() {
        List<String> a = Arrays.asList("one", "two", "three");
        List<String> b = Arrays.asList("four", "five", "six");
        return new List<String>[]{a, b};  // compile-time error: generic array creation
    }

For instance, let us compile the above code using Java 6 compiler using the printflat hidden option

javac -d /tmp -XD-printflat MergeLists.java

The generated file in /tmp would look something like:

    public static List[] mergeLists() {
        List a = Arrays.asList(new String[]{"one", "two", "three"});// type information is lost here
        List b = Arrays.asList(new String[]{"four", "five", "six"});// type information is lost here
        return List[] {a, b};// added for completion, this is illegal.
    }

As a consequence of Generics, type information is erased after compilation, making it unavailable at run time. So, types such as E, List, and List are called non-reifiable types [JLS 4.7]. Varargs are implemented as an array of objects and can hold only reifiable types.

When a programmer tries to invoke a varargs method with non-reifiable varargs type, the compiler currently generates an “unchecked” warning. This proposal moves the warning from the call site to the method declaration.

    static List<List<String>> listOfListOfStrings() {
      List<String> a = new ArrayList<String>(), b = new ArrayList<String>(), c = new ArrayList<String>();

      // Warning: [unchecked] unchecked generic array creation for varargs parameter of type List<String>[]
      return Arrays.asList(a, b, c);
    }

It looks like a new annotation is being planned to support this at the declaration and varargs warnings will be revised. Callers may be able to remove @SuppressWarnings(“unchecked”) from their code once this is supported by the compiler. This support is not yet available as of build b114.

Improved Type Inference for Generic Instance Creation (Diamond)

This one is much easier of all the Coin proposals, at least in terms of simplicity and eliminates much of the Generics verbosity. Generics enforced type redundancy during declaration. For example, the traditional way (>=1.5) of declaring a Generic type is shown below.

    static class Library<E> {
        Set<Method> methods = new HashSet<Method>();

        Library(Set<Method> methods) {
            this.methods = methods;
        }
    }

    Set<Method> methods = new HashSet<Method>();
    Library<Set<Method>> library = new Library<Set<Method>>(methods);

Now, with this language support, the declaration can be simplified as shown below:

    static class Library<E> {
        Set<Method> methods = new HashSet<>(); // saves typing

        Library(Set<Method> methods) {
            this.methods = methods;
        }
    }

    Set<Method> methods = new HashSet<>(); // saves typing
    Library<Set<Method>> library = new Library<>(methods); // saves typing

While libraries such as Guava have attempted similar support for this, language level sugar is more intuitive than alternatives. This feature was implemented more than a year ago.

Improved Exception Handling for Java

Prior to Java 7, it was very cumbersome to catch multiple exception types leading to boilerplate code. This proposal addresses this concern by catching multiple exception types with a single catch clause and improves checking for rethrown exceptions.

Here is a simple class we will be using to test reflection:

public class CoinByReflection {
    public int code = 10_10_2010;

    public void printTheme() {
        System.out.println("Making things programmers do everyday easier.");
    }
}

This pattern is noticed when working with reflective operations where we may need to handle different types of exceptions.

    public void multicatch() throws ClassNotFoundException, InstantiationException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException {
        try {
            Class clazz = Class.forName("CoinByReflection");
            Object instance = clazz.newInstance();
            Field field = clazz.getField("code");
            int code = field.getInt(instance);
            System.out.println(code);
            Method method = clazz.getMethod("printTheme");
            method.invoke(instance);
        } catch (ClassNotFoundException cnfe) {
            log(cnfe);
            throw cnfe;
        } catch (InstantiationException ie) {
            log(ie);
            throw ie;
        } catch (NoSuchMethodException nsme) {
            log(nsme);
            throw nsme;
        } catch (NoSuchFieldException nsfe) {
            log(nsfe);
            throw nsfe;
        } catch (IllegalAccessException iae) {
            log(iae);
            throw iae;
        } catch (InvocationTargetException ite) {
            log(ite);
            throw ite;
        }
    }

With this proposal, we should be able to simplify the exception handling when performing reflection with single catch.

    public void singlecatch() throws ClassNotFoundException, InstantiationException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException {
        try {
            Class clazz = Class.forName("CoinByReflection");
            Object instance = clazz.newInstance();
            Field field = clazz.getField("code");
            int code = field.getInt(instance);
            System.out.println(code);
            Method method = clazz.getMethod("printTheme");
            method.invoke(instance);
        } catch (final ClassNotFoundException|
        InstantiationException |
                NoSuchMethodException |
                NoSuchFieldException |
                IllegalAccessException |
                InvocationTargetException
        e){
            log(e);
            throw e;
        }
    }

ReflectiveOperationException, a new common super class of exceptions thrown by reflective operations was introduced to simplify this further. You can catch this exception and precisely rethrow one of the exceptions defined in the method signature.

    public void singlecatch() throws ClassNotFoundException, InstantiationException, NoSuchMethodException, NoSuchFieldException, IllegalAccessException, InvocationTargetException {
        try {
            Class clazz = Class.forName("CoinByReflection");
            Object instance = clazz.newInstance();
            Field field = clazz.getField("code2");
            int code = field.getInt(instance);
            System.out.println(code);
            Method method = clazz.getMethod("printTheme");
            method.invoke(instance);
        } catch (final ReflectiveOperationException e){
            log(e);
            throw e;
        }
    }

This feature was implemented in May.

Conclusion

With more than 80% of the Coin features implemented and “ready” for battle test, it is evident from the fact that these features live up to its expectations:

Making things programmers do everyday easier.

[as quoted from JavaOne Coin presentation]. Now that we have a definitive plan for Java 7, IDEs should start supporting these features as mid-2011 is not very far and play a vital role in accelerating adoption of these new syntaxes. It looks like Coin 2 will include other interesting proposals such as Collection literals, Multi-line strings, Large arrays, etc, possibly for Java 8?

Recently, NetBeans announced that it will support JDK 7 language features in its forthcoming 7.0 release and Eclipse plans to include Java 7 support in its next release 3.7 (Indigo). Intellij 9 has some support for Java 7, and I hope Intellij X brings the rest.

Possibly Related Posts: