Java 8 Friday Goodies: Lambdas and SQL

At Data Geekery, we love Java. And as we’re really into jOOQ’s fluent API and query DSL, we’re absolutely thrilled about what Java 8 will bring to our ecosystem. We have blogged a couple of times about some nice Java 8 goodies, and now we feel it’s time to start a new blog series, the…

Java 8 Friday

Every Friday, we’re showing you a couple of nice new tutorial-style Java 8 features, which take advantage of lambda expressions, extension methods, and other great stuff. You’ll find the source code on GitHub. tweet this

Java 8 Goodie: Lambdas and SQL

If you’re used to writing Groovy, this may appear “so 2003” to you. We know. Groovy has known a very useful way to write string-based SQL since its early days. Here’s an example written in Groovy (see the official docs here):

import groovy.sql.Sql
sql = Sql.newInstance( 
    'jdbc:h2:~/test', 'sa', '', 
    'org.h2.Driver' )
sql.eachRow( 
    'select * from information_schema.schemata' 
) { 
    println "$it.SCHEMA_NAME -- $it.IS_DEFAULT" 
}

Note also Groovy’s built-in String interpolation, where you can put expressions into strings. But we’re in Java land, and with Java 8, things get better in the Java / SQL integration as well, if we’re using third-party libraries, instead of JDBC directly.

In the following examples, we’re looking at how to fetch data from an H2 database and map records into custom POJOs / DTOs using these three popular libraries:

As always, the sources are also available from GitHub. For these tests, we’re creating a little POJO / DTO to wrap schema meta-information:

class Schema {
    final String schemaName;
    final boolean isDefault;

    Schema(String schemaName, boolean isDefault) {
        this.schemaName = schemaName;
        this.isDefault = isDefault;
    }

    @Override
    public String toString() {
        return "Schema{" +
               "schemaName='" + schemaName + '\'' +
               ", isDefault=" + isDefault +
               '}';
    }
}

Our main method will get an H2 connection through DriverManager:

Class.forName("org.h2.Driver");
try (Connection c = getConnection(
        "jdbc:h2:~/test", "sa", "")) {

  String sql = "select schema_name, is_default "+
               "from information_schema.schemata "+
               "order by schema_name";
  // Library code here...
}

Now, how does Java 8 improve upon the jOOQ API, when using String-based SQL? Greatly! Check out the following little query:

DSL.using(c)
   .fetch(sql)
   .map(r -> new Schema(
       r.getValue("SCHEMA_NAME", String.class),
       r.getValue("IS_DEFAULT", boolean.class)
   ))
   .forEach(System.out::println);

This is how things should be, right? Note that jOOQ’s native APIs are also capable of mapping the database Record onto your POJO directly, as such:

DSL.using(c)
   .fetch(sql)
   .into(Schema.class)
   .forEach(System.out::println);

Things look just as nice when doing the same with Spring JDBC and RowMapper (note, the following still throws checked SQLExceptions):

new JdbcTemplate(
        new SingleConnectionDataSource(c, true))
    .query(sql, (rs, rowNum) -> 
        new Schema(
            rs.getString("SCHEMA_NAME"),
            rs.getBoolean("IS_DEFAULT")
        ))
    .forEach(System.out::println);

… and if you’re using Apache DbUtils, you can do almost the same:

new QueryRunner()
    .query(c, sql, new ArrayListHandler())
    .stream()
    .map(array -> new Schema(
        (String) array[0],
        (Boolean) array[1]
    ))
    .forEach(System.out::println);

Conclusion

All three solutions are more or less equivalent and quite lean. The point here, again, is that Java 8 will improve all existing APIs. The more unambiguous (few overloads!) methods accepting SAM arguments (single abstract method types), the better for a Java 8 integration.

Java 8 and SQL look very lean tweet this

Next week, we’re going to see a couple of things that will greatly improve when using the java.util.Map API

More on Java 8

In the mean time, have a look at Eugen Paraschiv’s awesome Java 8 resources page

Java 8 Friday Goodies: Lambdas and XML

At Data Geekery, we love Java. And as we’re really into jOOQ’s fluent API and query DSL, we’re absolutely thrilled about what Java 8 will bring to our ecosystem. We have blogged a couple of times about some nice Java 8 goodies, and now we feel it’s time to start a new blog series, the…

Java 8 Friday

Every Friday, we’re showing you a couple of nice new tutorial-style Java 8 features, which take advantage of lambda expressions, extension methods, and other great stuff. You’ll find the source code on GitHub. tweet this

Java 8 Goodie: Lambdas and XML

There isn’t too much that Java 8 can do to the existing SAX and DOM APIs. The SAX ContentHandler has too many abstract methods to qualify as a @FunctionalInterface, and DOM is a huge, verbose API specified by w3c, with little chance of adding new extension methods.

Luckily there is a small Open Source library called jOOX that allows for processing the w3c standard DOM API through a wrapper API that mimicks the popular jQuery library. jQuery leverages JavaScript’s language features by allowing users to pass functions to the API for DOM traversal. The same is the case with jOOX. Let’s have a closer look:

Assume that we’re using the following pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>org.jooq</groupId>
  <artifactId>java8-goodies</artifactId>
  <version>1.0-SNAPSHOT</version>

  <dependencies>
    <dependency>
      <groupId>org.jooq</groupId>
      <artifactId>joox</artifactId>
      <version>1.2.0</version>
    </dependency>
  </dependencies>

  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>2.3.2</version>
        <configuration>
          <fork>true</fork>
          <maxmem>512m</maxmem>
          <meminitial>256m</meminitial>
          <encoding>UTF-8</encoding>
          <source>1.8</source>
          <target>1.8</target>
          <debug>true</debug>
          <debuglevel>lines,vars,source</debuglevel>
        </configuration>
      </plugin>
    </plugins>
  </build>
</project>

Let’s assume we wanted to know all the involved artifacts in Maven’s groupId:artifactId:version notation. Here’s how we can do that with jOOX and lambda expressions:

$(new File("./pom.xml")).find("groupId")
                        .each(ctx -> {
    System.out.println(
        $(ctx).text() + ":" +
        $(ctx).siblings("artifactId").text() + ":" +
        $(ctx).siblings("version").text()
    );
});

Executing the above yields:

org.jooq:java8-goodies:1.0-SNAPSHOT
org.jooq:joox:1.2.0
org.apache.maven.plugins:maven-compiler-plugin:2.3.2

Let’s assume we only wanted to display those artifacts that don’t have SNAPSHOT in their version numbers. Simply add a filter:

$(new File("./pom.xml"))
    .find("groupId")
    .filter(ctx -> $(ctx).siblings("version")
                         .matchText(".*-SNAPSHOT")
                         .isEmpty())
    .each(ctx -> {
        System.out.println(
        $(ctx).text() + ":" +
        $(ctx).siblings("artifactId").text() + ":" +
        $(ctx).siblings("version").text());
    });

This will now yield

org.jooq:joox:1.2.0
org.apache.maven.plugins:maven-compiler-plugin:2.3.2

We can also transform the XML content. For instance, if the target document doesn’t need to be a POM, we could replace the matched groupId elements by an artifical artifact element that contains the artifact name in Maven notation. Here’s how to do this:

$(new File("./pom.xml"))
    .find("groupId")
    .filter(ctx -> $(ctx).siblings("version")
                         .matchText(".*-SNAPSHOT")
                         .isEmpty())
    .content(ctx ->
        $(ctx).text() + ":" +
        $(ctx).siblings("artifactId").text() + ":" +
        $(ctx).siblings("version").text()
    )
    .rename("artifact")
    .each(ctx -> System.out.println(ctx));

The above puts new content in place of the previous one through .content(), and then renames the groupId elements to artifact, before printing out the element. The result is:

<artifact>org.jooq:joox:1.2.0</artifact>
<artifact>org.apache.maven.plugins:maven-compiler-plugin:2.3.2</artifact>

More goodies next week

What becomes immediately obvious is the fact that the lambda expert group’s choice of making all SAMs (Single Abstract Method interfaces) eligible for use with lambda expressions adds great value to pre-existing APIs. Quite a clever move.

But there are also new APIs. Last week, we have discussed how the existing JDK 1.2 File API can be improved through the use of lambdas. Some of our readers have expressed their concerns that the java.io API has been largely replaced by java.nio (nio as in New I/O). Next week, we’ll have a look at Java 8’s java.nnio API (for new-new I/O ;-) ) and how it relates to the Java 8 Streams API.

More on Java 8

In the mean time, have a look at Eugen Paraschiv’s awesome Java 8 resources page

Java 8 Friday Goodies: java.io finally rocks!

At Data Geekery, we love Java. And as we’re really into jOOQ’s fluent API and query DSL, we’re absolutely thrilled about what Java 8 will bring to our ecosystem. We have blogged a couple of times about some nice Java 8 goodies, and now we feel it’s time to start a new blog series, the…

Java 8 Friday

Every Friday, we’re showing you a couple of nice new tutorial-style Java 8 features, which take advantage of lambda expressions, extension methods, and other great stuff. You’ll find the source code on GitHub. tweet this

Interacting with the file system has been a bit of a pain in Java. CTMMC shows us an example of how to copy a file with Java. While some issues still remain, at least, we can now use lambdas and the new Streams API to traverse the file system and list files! Here is the FileFilterGoodies example that we’ve pushed to our GitHub repository:

public class FileFilterGoodies {

    public static void main(String args[]) {
        listRecursive(new File("."));
    }

    /**
     * This method recursively lists all
     * .txt and .java files in a directory
     */
    private static void listRecursive(File dir) {
        Arrays.stream(dir.listFiles((f, n) ->
                     !n.startsWith(".")
                  &&
                     (new File(f, n).isDirectory()
                  ||  n.endsWith(".txt")
                  ||  n.endsWith(".java"))
              ))
              .forEach(unchecked((file) -> {
                  System.out.println(
                      file.getCanonicalPath()
                          .substring(new File(".")
                              .getCanonicalPath()
                              .length()));

                  if (file.isDirectory()) {
                      listRecursive(file);
                  }
              }));
    }

    /**
     * This utility simply wraps a functional
     * interface that throws a checked exception
     * into a Java 8 Consumer
     */
    private static <T> Consumer<T>
    unchecked(CheckedConsumer<T> consumer) {
        return t -> {
            try {
                consumer.accept(t);
            }
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        };
    }

    @FunctionalInterface
    private interface CheckedConsumer<T> {
        void accept(T t) throws Exception;
    }
}

The output of the above programme is:

\LICENSE.txt
\out
\out\production
\out\production\jOOQ's Java 8 Goodies
\out\production\jOOQ's Java 8 Goodies\org
\out\production\jOOQ's Java 8 Goodies\org\jooq
\out\production\jOOQ's Java 8 Goodies\org\jooq\java8
\out\production\jOOQ's Java 8 Goodies\org\jooq\java8\goodies
\out\production\jOOQ's Java 8 Goodies\org\jooq\java8\goodies\io
\README.txt
\src
\src\org
\src\org\jooq
\src\org\jooq\java8
\src\org\jooq\java8\goodies
\src\org\jooq\java8\goodies\io
\src\org\jooq\java8\goodies\io\FileFilterGoodies.java

Now, that’s really awesome, isn’t it? Let’s decompose the above listRecursive() method:

// With this method, we wrap the File[] array
// into a new Java 8 Stream, which has awesome
// new methods.
Arrays.stream(

// The Java 1.2 File.listFiles() method luckily
// accepts a @FunctionalInterface, which can be
// instantiated using a lambda expression
// ...
// In this example, we'll just ignore the fact
// that listFiles can return null
              dir.listFiles((f, n) ->
             !n.startsWith(".")
          &&
             (new File(f, n).isDirectory()
          ||  n.endsWith(".txt")
          ||  n.endsWith(".java"))
      ))

// Each Stream (and also java.util.List) has this
// awesome forEach method, that accepts a Consumer
      .forEach(

// Unfortunately, Java 8 Consumers don't allow
// throwing checked exceptions. So let's quickly
// wrap it (see details below) ...
               unchecked(

// ... and pass another lambda expression to it,
// which prints the local path and recurses
                         (file) -> {
          System.out.println(
              file.getCanonicalPath()
                  .substring(new File(".")
                      .getCanonicalPath()
                      .length()));

          if (file.isDirectory()) {
              listRecursive(file);
          }
      }));

More goodies next week

Stay tuned for next week, when we show you how Java 8 improves using XML with jOOX

More on Java 8

In the mean time, have a look at Eugen Paraschiv’s awesome Java 8 resources page