Skip to content

First run

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

First run

Scrolling upwards through the verbose output for a bit, and there's this:

...
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] src/main/java/org/springframework/samples/petclinic/model/NamedEntity.java:
[30,8] [initialization.fields.uninitialized] the constructor does not initialize fields: name
[ERROR] src/main/java/org/springframework/samples/petclinic/model/BaseEntity.java:
[30,8] [initialization.fields.uninitialized] the constructor does not initialize fields: id
[ERROR] src/main/java/org/springframework/samples/petclinic/model/Pet.java:
[49,8] [initialization.fields.uninitialized] the constructor does not initialize fields: birthDate, type, owner, visits
[ERROR] src/main/java/org/springframework/samples/petclinic/model/Owner.java:
[46,8] [initialization.fields.uninitialized] the constructor does not initialize fields: address, city, telephone, pets
[ERROR] src/main/java/org/springframework/samples/petclinic/model/Owner.java:
[137,16] [return.type.incompatible] incompatible types in return.
  found   : null
  required: @Initialized @NonNull Pet
...
...
[INFO] 18 errors
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------

The checker found 18 errors.

The ones at the top seem quite similar. 'Named entity', 'pet', 'owner' ... these are the entities from the domain model of the Pet Clinic.

Open the class in the first error message, NamedEntity LINK. The message says that the constructor doesn't initialize the field, name. That is true, but why is this a problem?

@MappedSuperclass
public class NamedEntity extends BaseEntity {
    @Column(name = "name")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

... The reason is in the assumptions made in what I called 'null-safe programming': That assumption was nothing is ever null. But name is definitely null when we instantiate NamedEntity. therefore we must make the nullability explicit (nullable is the marked case).

    @Column(name = "name")
    @Nullable
    private String name;

Mutable fields like this one often come with getters and setters. @Nullable will propagate outwards. If the field may be null, the getter may return null, and the setter may accept null (run the checker again to see if this reasoning is right).

    @Nullable public String getName() {
        return name;
    }

    public void setName(@Nullable String name) {
        this.name = name;
    }

By the way, for very short one-line methods like these I like putting the annotation inline. This is just a matter of taste.

Proceeding this way with the other entities.

...

[A word on good design.] When designing value classes like these it is usually best to make them immutable.

...

Try annotating the entities yourself. I have committed my changes in commit HASH. It is quite a diff, but relax: this was already the bulk of @Nullable annotations in this tutorial.

While I run the checker on this annotated code, turn the page to ... LINK.

Clone this wiki locally