Monday, October 26, 2015

Approximating tuples in Java

What is a tuple? It's an ordered collection of individually typed elements. Wikipedia has a complicated explanation that comes down to the same thing in the context of ordinary programming. The Python implementation of tuples is a good example.

There are many related concepts, such as:

Arrays and lists
Ordered but all elements are the same type
Ordered dictionaries (maps)
Ordered but all values are of the same type, and they are named
Aggregates (structs, unions)
Individually typed but named and unordered

The closest matches to tuples in current Java are "structs" (more below) and arrays or lists, each with drawbacks. For most use of tuples, arrays and lists are non-starters: elements are all of the same nominal type. There is a lot of thought around how to do this best in Java.

What do I mean by saying Java has "structs" ala "C"? The vast bulk of Java code hides fields away with private, but exposes them with getter methods (and setters when non-final). This is the "Java Bean" anti-pattern. An alternative is to simply expose fields directly:

public final class CartesianPoint {
    public final int x;
    public final int y;

    public CartesianPoint(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

This is almost a tuple. However:

  • CartesianPoint extends java.lang.Object but should not be an object in the OOP sense
  • Elements are accessed by name, e.g., point.x, rather than position
  • Elements are unordered—you cannot write a general function to process the first and second elements of the tuple without knowing 1) the struct type and 2) the names of the fields

But for many use cases this can be close enough, for example as a return type to simulate multiple value return. Hopefully Java 10 brings value types which resolves the java.lang.Object issue. This may even bring true tuples!

This example can be improved with Lombok:

@EqualsAndHashCode
@RequiredArgsConstructor(staticName = "valueOf")
@ToString(includeFieldNames = false)
public final class CartesianPoint {
    public final int x;
    public final int y;
}

Calling code would look like:

public CartesianPoint locate() {
    int x = computeX();
    int y = computeY();

    return CartesianPoint.valueOf(x, y);
}

Notice the visual similarity of the local variables x and y to the corresponding fields in CartesianPoint. Users of CartesianPoint would see:

public static void main(final String... args) {
    Boat boat = Boat.rowBoat();
    CartesianPoint point = boat.locate();

    out.printf("%s -> x is %d, y is %d%n", point, point.x, point.y);
}

$ ./float-boat 1 2
CartesianPoint(1, 2) -> x is 1, y is 2

If you want to go hog wild, the ordered and unnamed qualities of tuples can be simulated though not without significant noise:

Function<CartesianPoint, Integer> first = p -> p.x;
Function<CartesianPoint, Integer> second = p -> p.y;

out.printf("first is %d, second is %d%n",
        first.apply(point),
        second.apply(point));

Update

Streaming functionally:

Function<CartesianPoint, Integer> first = p -> p.x;
Function<CartesianPoint, Integer> second = p -> p.y;
Stream.of(first, second).
    map(f -> f.apply(point)).
    forEach(out::println);

Sunday, October 25, 2015

What's wrong with Java 8 series by Pierre-Yves Saumont

Pierre-Yves Saumont wrote a series of articles for DZone. I feel remiss for having missed them. For example, What's Wrong in Java 8, Part IV: Monads explores java.util.Optional. Do not be misled by the post titles—yes, he criticizes Java 8 for what it could have been—, but he covers functional thinking in Java with depth, skill and panache.

The full list of "What's Wrong with Java 8" articles:

  1. Currying vs Closures
  2. Functions & Primitives
  3. Streams and Parallel Streams
  4. Monads
  5. Tuples
  6. Strictness
  7. Streams again

And all his DZone articles.

Wednesday, October 21, 2015

Tracking Java 8 stream count

I had a coding problem to fail when a Java 8 stream was empty. One way is illustrated below in example1. Another approach was interesting, shown in example2

public final class Streamy {
    private static <T, E extends RuntimeException> void example1(
            final Stream<T> items,
            final Consumer<? super T> process,
            final Supplier<E> thrown)
            throws E {
        if (0 == items.
                peek(process).
                count())
            throw thrown.get();
    }

    private static <T, E extends RuntimeException> void example2(
            final Stream<T> items,
            final Consumer<? super T> process,
            final Supplier<E> thrown)
            throws E {
        final AtomicBoolean foundSome = new AtomicBoolean();
        try (final Stream<T> stream = items) {
            stream.
                    onClose(() -> {
                        if (!foundSome.get())
                            throw thrown.get();
                    }).
                    peek(__ -> foundSome.set(true)).
                    forEach(process);
        }
    }

    public static void main(final String... args) {
        example1(Stream.of(), out::println, RuntimeException::new);
        example2(Stream.of(), out::println, RuntimeException::new);
    }
}

Comparing them I find:

  • Using count() is shorter and more clear
  • Using onClose() is more expressive

I found it odd to use peek() in example1 to execute the real purpose of the code, and was happy to discover onClose() though disappointed to need try-with-resources for it to run.

It was unfortunate that the more expressive approach (peek() for side effect, forEach() for processing, onClose for post-processing check) was also harder to understand.

Sunday, October 18, 2015

Downloading sources and javadocs automatically

Thanks to Ted Wise, I taught my "modern java" build to automatically download sources and javadocs. Using maven:

<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <version>${maven-dependency-plugin.version}</version>
    <executions>
        <execution>
            <id>download-sources</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>sources</goal>
            </goals>
        </execution>
        <execution>
            <id>download-javadocs</id>
            <phase>generate-sources</phase>
            <configuration>
                <classifier>javadoc</classifier>
            </configuration>
            <goals>
                <goal>resolve</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Friday, October 16, 2015

Struggling with Travis CI and Maven 3.3

I struggled with fixing Travis CI for my "labs" code. The main problem is lack of support for Maven 3.3; my POM enforcer requires it. Eventually I got something working with help from the Internet, though I'm not happy with it. It manually downloads and uses maven 3.3:

sudo: false
language: java
jdk:
  - oraclejdk8
# TODO: Gross until Travis support setting maven version or upgrades to 3.3
before_install:
  - wget http://apache.claz.org/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.tar.gz
  - tar zxvf apache-maven-3.3.3-bin.tar.gz
  - chmod +x apache-maven-3.3.3/bin/mvn
  - export M2_HOME=$PWD/apache-maven-3.3.3
  - export PATH=$PWD/apache-maven-3.3.3/bin:${PATH}
  - hash -r
before_script:
  - export M2_HOME=$PWD/apache-maven-3.3.3
  - export PATH=$PWD/apache-maven-3.3.3/bin:${PATH}
  - hash -r
script: mvn verify -Dgpg.skip=true

Bonus

On another project using Travis CI I ran afoul of the 10,000 line limit for displaying build output in the web UI. Workaround, add this to the build_install section:

  - echo 'MAVEN_OPTS="-Dorg.slf4j.simpleLogger.defaultLogLevel=warn"' >~/.mavenrc

If you're using maven 3.3 or better, Karl Heinz Marbaise has a better approach with .mvn/jvm.config.

Thursday, October 15, 2015

Spring advice

Today I had an exchange with an erstwhile colleague, one of those talented few equally comfortable in C++ and Java, great with demanding clients and fellow developers. He asked me for thoughts on Spring dependency injection. Branching out a bit, I replied:

Matter of taste/opinion.

Some things I prefer:

  • Avoid setter injection if at all possible. I want my beans to be finished after DI, not changeable at runtime on accident (very nasty bug to track down) Constructor injection most preferred, followed by field
  • Use standard annotations rather than Spring ones (@Inject), though @Value is needed for injected configuration if you're not using a dedicated configuration object
  • Spring Java configuration beats XML almost all the time
  • If the program doesn't need Spring DI, I prefer using Guice or Dagger. They're simpler, everything is at compile time, and error messages are better. The Spring non-DI libraries play fine with others (e.g., spring-jdbc)
  • Avoid mixing business objects with wiring unless it makes sense. For example, JdbcTemplate should be new'ed as needed, injecting only the DataSource. Injecting the template is an anti-pattern
  • Do use Spring Boot or Dropwizard, et al, if it makes sense. Big time savers, lots of good integration prepackaged
  • For webby programs (apps, services) remember to test unit, controller and integration separately. Spring boot intro page has excellent code examples

Things get more interesting with multiple configurations and with cloud. For example:

  • Do you make separate builds for each env, or one build with multiple configurations? Latter is traditional in EE world, former much better for cloud (devops, immutable, unikernel, etc)
  • Do you pull in configuration externally, e.g., Spring Cloud Config, Netflix Archaius or Apache Zookeeper. I like this approach, but more complex and overkill for simple programs. Nearly mandatory for microservices, and strong choice when in cloud

Did I answer fairly?

Monday, October 12, 2015

Blog code 6

(Updated) I've published my blog code version 6 to Maven Central with javadocs. The previous version was 0.5; having a leading "0." was silly (there won't be a 1.0).

Interesting changes:

  • Added the YAML modules. This is an annotation processor which takes YAML descriptions of Java data structures, and generates immutable classes for them.
  • Added the Matching class for a pattern-matching DSL in Java. I'll improve on over time.

Tuesday, October 06, 2015

Automating dependency versions in Maven

Reading the most excellent Modern Java series of posts, I realized I could automate a command line step I always did manually—updating dependency versions:

$ mvn versions:update-properties

I can automate that! The simplest possible POM demonstrating:

<?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>example-group</groupId>
    <artifactId>example-artifact</artifactId>
    <version>0-SNAPSHOT</version>

    <properties>
        <example-dependency.version>1</example-dependency.version>
        <generateBackupPoms>false</generateBackupPoms>
        <versions-maven-plugin.version>2.2</versions-maven-plugin.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>example-group</groupId>
            <artifactId>example-dependency</artifactId>
            <version>${example-dependency.version}</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>versions-maven-plugin</artifactId>
                <version>${versions-maven-plugin.version}</version>
                <executions>
                    <execution>
                        <id>update-dependencies</id>
                        <phase>validate</phase>
                        <goals>
                            <goal>update-properties</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

My hypothetical maven build says:

$ mvn clean
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Building example-artifact 0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ example-artifact ---
[INFO]
[INFO] --- versions-maven-plugin:2.2:update-properties (update-dependencies) @ example-artifact ---
[INFO] Property ${example-dependency.version}: Leaving unchanged as 1.2.3
[INFO] Property ${versions-maven-plugin.version}: Leaving unchanged as 2.2

The key is using <phase>validate</phase> in the plugin execution. The first lifecycle phase for maven is "validate". Setting the property "generateBackupPoms" to "false" prevents pom.xml.versionsBackup files from littering the project. You are using source control, aren't you?

Update

This approach is best during development, especially for greenfield projects. I would not recommend it for stable or legacy projects where dependency versions need to be kept constant.