Monthly Archives: July 2015

Maven: Skinning Generated Site

PROBLEM

The default Maven generated site looks like web pages created in the 80s:-

SOLUTION

The good news is Maven allows us to change the skin.

To use one of these pre-defined skins, create site.xml at this location:-

myproject
├── pom.xml
├── src
│   ├── main
│   │   └── java
│   │       └── ...
│   ├── site
│   │   └── site.xml

In site.xml, enter the following:-

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/DECORATION/1.6.0"
         xsi:schemaLocation="http://maven.apache.org/DECORATION/1.6.0
         http://maven.apache.org/xsd/decoration-1.6.0.xsd">
    <bannerLeft>
        <name>${project.name}</name>
        <href>${project.url}</href>
    </bannerLeft>

    <publishDate position="right" format="MMMM dd, yyyy"/>
    <version/>
    <poweredBy>
        <logo img="#" alt=""/>
    </poweredBy>

    <skin>
        <groupId>org.apache.maven.skins</groupId>
        <artifactId>maven-fluido-skin</artifactId>
        <version>1.4</version>
    </skin>

    <body>
        <menu ref="reports"/>
        <footer/>
    </body>
</project>

In the above example, we use Maven Fluido Skin.

In Maven 3, site:attach-descriptor has been removed from the built-in lifecycle bindings, so we need to explicitly define attach-descriptor goal in Maven Site Plugin to pick up src/site/site.xml.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-site-plugin</artifactId>
    <version>3.4</version>
    <executions>
        <execution>
            <id>attach-descriptor</id>
            <goals>
                <goal>attach-descriptor</goal>
            </goals>
        </execution>
    </executions>
</plugin>

When you run mvn clean site, oh hey, welcome to 21st century!

Advertisements

JaCoCo Web Report Not Rendering Properly in GitHub Pages

PROBLEM

When pushing JaCoCo web report to GitHub’s gh-pages branch, it does not render properly on the web. For example:-

The GitHub pages are powered by Jekyll. By default, Jekyll does not allow directories or files that begin with a dot, pound sign, tilde or underscore.

Since JaCoCo places all the image and CSS files in a directory called .resources, this directory will not be pushed to GitHub’s gh-pages branch.

SOLUTION UPDATE: 2015-07-23

GitHub Site Plugin has a noJekyll parameter that will create the .nojekyll file at the root path if it is set to true.

<plugin>
    <groupId>com.github.github</groupId>
    <artifactId>site-maven-plugin</artifactId>
    <version>${site-maven-plugin.version}</version>
    <configuration>
        <message>Creating site for ${project.version}</message>
        <server>github</server>
        <noJekyll>true</noJekyll>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>site</goal>
            </goals>
            <phase>site</phase>
        </execution>
    </executions>
</plugin>

SOLUTION 1: Disable Jekyll

One simple fix is to completely disable Jekyll by creating an empty file called .nojekyll at this location:-

myproject
├── pom.xml
├── src
│   ├── main
│   │   └── java
│   │       └── ...
│   ├── site
│   │   └── resources
│   │       └── .nojekyll

SOLUTION 2: Configure Jekyll

While disabling Jekyll works, it may 1) seem rather risky since there maybe other hidden directories/files and 2) possibly send too much garbage to GitHub’s gh-pages branch.

To fix this, we will instruct Jekyll to allow JaCoCo’s .resources directory through by creating a file called _config.yml at this location:-

myproject
├── pom.xml
├── src
│   ├── main
│   │   └── java
│   │       └── ...
│   ├── site
│   │   └── resources
│   │       └── _config.yml

In _config.yml, enter the following:-

# Allow JaCoCo's directory to bypass GitHub's Jekyll-powered pages 
# so that the web report renders properly
include: ['.resources']

OUTCOME

Either solution will produce a nicely rendered JaCoCo web report in GitHub pages.

Java: Builder for Immutable POJO

PROBLEM

Let’s assume we have an immutable Person object:-

public final class Person implements Serializable {
    private final String name;
    private final Collection<Car> cars;

    public Person(final String name, final Collection<Car> cars) {
        this.name = name;
        this.cars = MoreObjects.firstNonNull(cars, ImmutableList.<Car>of());
    }

    public String getName() {
        return name;
    }

    public Collection<Car> getCars() {
        return cars;
    }
}

… and an immutable Car object:-

public final class Car implements Serializable {
    private final String license;
    private final LocalDate boughtOn;

    public Car(final String license, final LocalDate boughtOn) {
        this.license = license;
        this.boughtOn = boughtOn;
    }

    public String getLicense() {
        return license;
    }

    public LocalDate getBoughtOn() {
        return boughtOn;
    }
}

To create the Person object, we need to write something like this:-

final Person person = new Person("Mike",
                                 Collections.singletonList(
                                     new Car("123", new LocalDate(2015, 1, 1))));

If the POJO has a lot of properties, it becomes very difficult to keep track all the constructor argument positions.

SOLUTION

@mkarneim wrote a POJO Builder that creates the builder class(es) at compilation time.

To pull this off, we need to add the following dependency with provided scope.

<dependency>
    <groupId>net.karneim</groupId>
    <artifactId>pojobuilder</artifactId>
    <version>3.4.0</version>
    <scope>provided</scope>
</dependency>

Next, annotate with the Person constructor with @GeneratePojoBuilder. Make the constructor visibility to protected so that no one can directly instantiate that object.

public final class Person implements Serializable {
    private final String name;
    private final Collection<Car> cars;

    @GeneratePojoBuilder
    protected Person(final String name, final Collection<Car> cars) {
        this.name = name;
        this.cars = MoreObjects.firstNonNull(cars, ImmutableList.<Car>of());
    }

    public String getName() {
        return name;
    }

    public Collection<Car> getCars() {
        return cars;
    }
}

Do the same for Car object:-

public final class Car implements Serializable {
    private final String license;
    private final LocalDate boughtOn;

    @GeneratePojoBuilder
    protected Car(final String license, final LocalDate boughtOn) {
        this.license = license;
        this.boughtOn = boughtOn;
    }

    public String getLicense() {
        return license;
    }

    public LocalDate getBoughtOn() {
        return boughtOn;
    }

Next, and this is probably the most important step… run mvn clean compile to generate the builder classes. This allows the IDE to help us with code completion when using the builders.

Now, we can create the Person object like this:-

final Person person = new PersonBuilder()
        .withCars(ImmutableList.of(
                new CarBuilder()
                        .withBoughtOn(new LocalDate(2015, 1, 1))
                        .withLicense("123")
                        .build()))
        .withName("Mike")
        .build();

If you are running the program directly from IntelliJ, we need to ensure the program is compiled using Maven. To do this, edit the configuration for the runner class:-

Remove the default Make task:-

Add Maven goals:-

Enter clean and compile:-

Now, when IntelliJ runs the program, the program will be compiled using Maven to ensure no compilation errors on the builder classes during execution.

IntelliJ IDEA 14.1: Better equals(), hashCode() and toString()

PROBLEM

Let’s assume we want to create the default equals(), hashCode() and toString() with the following bean:-

public final class Person {
    private final String name;
    private final Collection<Car> cars;

    public Person(final String name, final Collection<Car> cars) {
        this.name = name;
        this.cars = cars;
    }

    public String getName() {
        return name;
    }

    public Collection<Car> getCars() {
        return cars;
    }
}

Most IDEs, including older version of IntelliJ, have code generation features that would create something similar to this:-

public final class Person {
    ...

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }

        final Person person = (Person) o;

        if (name != null ? !name.equals(person.name) : person.name != null) {
            return false;
        }
        return !(cars != null ? !cars.equals(person.cars) : person.cars != null);
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + (cars != null ? cars.hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Person{" +
               "name='" + name + '\'' +
               ", cars=" + cars +
               '}';
    }
}

While it works, the generated code is usually crazy horrendous.

SOLUTION

With IntelliJ 14.x, it allows us to select templates from several proven libraries.

To generate equals() and hashCode(), select equals() and hashCode() option from the Generate pop-up dialog:-

There are several templates to choose from:-

Here’s an example of equals() and hashCode() using Guava and getter methods:-

public final class Person {
    ...

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        final Person person = (Person) o;
        return Objects.equal(getName(), person.getName()) &&
               Objects.equal(getCars(), person.getCars());
    }

    @Override
    public int hashCode() {
        return Objects.hashCode(getName(), getCars());
    }
}

To generate toString(), select toString() option from the Generate pop-up dialog:-

Again, there are several templates to choose from:-

Here’s an example of toString() using Guava:-

public final class Person {
    ...

    @Override
    public String toString() {
        return Objects.toStringHelper(this)
                .add("name", name)
                .add("cars", cars)
                .toString();
    }
}

Underscore.js: Introducing _.chain(…)

PROBLEM

Let’s assume we have the following JSON data:-

[
    {
        "date": "2015-07-30",
        "calendarAppointmentPtoJsonBeans": [
            {
                "basicEmployeeJsonBean": {
                    "id": 1,
                    "name": "Vrabel"
            	}
            }
        ]
    },
    {
        "date": "2015-07-31",
        "calendarAppointmentPtoJsonBeans": [
            {
                "basicEmployeeJsonBean": {
                    "id": 2,
                    "name": "Cray"
            	}
            },
            {
                "basicEmployeeJsonBean": {
                    "id": 1,
                    "name": "Vrabel"
            	}
            },
            {
                "basicEmployeeJsonBean": {
                    "id": 3,
                    "name": "Haeflinger"
            	}
            }
        ]
    }
]

What we want to do is to get all unique employees and ordered them by their names so that we get the following data:-

[
    {
        "id": 2,
        "name": "Cray"
    },
    {
        "id": 3,
        "name": "Haeflinger"
    },
    {
        "id": 1,
        "name": "Vrabel"
    }
]

SOLUTION 1: Less Elegant

Underscore.js provides various functions that allow us to pull this off.

var employees = _.sortBy( _.unique( _.pluck( _.flatten(
                _.pluck( jsonData, 'calendarAppointmentPtoJsonBeans' ) ),
                        'basicEmployeeJsonBean' ), function ( employee ) {
                    return employee.id;
                } ), function ( employee ) {
                    return employee.name;
                } );

While doable, the code is virtually not readable.

If you hate your peers and life, this is what you would write.

SOLUTION 2: More Elegant

The good news is Underscore.js also provides _.chain(..) that allows us to do the same thing through method chaining:-

var employees = _.chain( jsonData )
                .pluck( 'calendarAppointmentPtoJsonBeans' )
                .flatten()
                .pluck( 'basicEmployeeJsonBean' )
                .unique( function ( employee ) {
                    return employee.id;
                } )
                .sortBy( function ( employee ) {
                    return employee.name;
                } )
                .value();