Skip to content

Dealing with libraries

David Bürgin edited this page Nov 14, 2015 · 18 revisions

Dealing with libraries

We have eliminated two errors and with that two bugs, but there are still 35 more to go. But there’s a realisation to be had in the next few error messages, and it will cut down our work considerably.

Unannotated libraries

The topmost errors are again in Owner. The Checker reports an error on almost every call to ToStringCreator.append in the following code.

    @Override
    public String toString() {
        return new ToStringCreator(this)
            .append("id", this.getId())
            .append("new", this.isNew())
            .append("lastName", this.getLastName())       // line 151
            .append("firstName", this.getFirstName())
            .append("address", this.address)
            .append("city", this.city)
            .append("telephone", this.telephone)
            .toString();
    }

For example, on the line with the last name the error is:

[151,49] [argument.type.incompatible] incompatible types in argument.
  found   : @Initialized @Nullable String
  required: @Initialized @NonNull Object

The Checker seems to assume that the signature of ToStringCreator.append is

public @NonNull ToStringCreator append(@NonNull String fieldName, @NonNull Object value)

The assumption that all references are non-null by default makes an other appearance, but this time in code that we don’t control. org.springframework.core.style.ToStringCreator is a class from the Spring Framework library. This library is unannotated, and yet the Checker Framework adheres to its non-null default interpretation.

What to do?

We haven't talked about the correctness/convenience trade-off yet. Here I'm going to choose convenience, and we will talk about the implications of this choice later. Convenience in this case means simply ignoring these errors.

Ignoring library usage

The Checker Framework's annotation processors can be configured with standard javac -A command-line flags. Two of the more useful flags are

  • -Alint, which turns on additional optional safety checks; and
  • -Awarns, which turns errors into warnings, so that compilation succeeds notwithstanding any errors found.

The flag most useful for our current task is -AskipUses. With -AskipUses we can instruct the Checker Framework to ignore problems with usage of code below a certain package. For now, let’s simply ignore all errors to do with Spring Framework usage, package org.springframework.

One complication here is that our project, the Pet Clinic, is in the package org.springframework.samples, which is inside the package for the Spring Framework itself. We’ll have to exclude all Spring packages that are not org.springframework.samples. A bit tedious, so do feel free to copy and paste the list of packages I’ve prepared here. This goes in the compiler configuration in the POM, just after the other <arg> element.

<arg>-AskipUses=org\.springframework\.beans\.|org\.springframework\.core\.|org\.springframework\.dao\.|org\.springframework\.data\.|org\.springframework\.format\.|org\.springframework\.jdbc\.|org\.springframework\.orm\.|org\.springframework\.stereotype\.|org\.springframework\.ui\.|org\.springframework\.util\.|org\.springframework\.validation\.|org\.springframework\.web\.</arg>

I’ve committed this flag in my seventh commit 1209ed3. I ask you to also ignore the Joda-Time library, use of which is responsible for two more errors. See the small follow-up commit 76f2ac6.

With this configuration-only change we’ve managed to cut the number of errors in half. See for yourself by running mvn -Pchecker compile and turn the page.

Clone this wiki locally