-
Notifications
You must be signed in to change notification settings - Fork 5
First run
After kicking off the compile job with mvn -Pchecker compile expect a fair bit
of output. Here comes the first batch of diagnostics.
Scroll 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 initialise 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 this.name;
}
public void setName(String name) {
this.name = name;
}
}Recall that the Checker Framework assumes unannotated references to be non-null
by default. We saw that this is a sane assumption in light of what I called
null-safe programming. Here, name is definitely null when we instantiate
NamedEntity. 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).
Again, we make explicit that these references may be null.
@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.
Even on a small project like this one running the Checker takes time. When there are many similar errors, addressing them as a batch speeds things up.
Try annotating all the entities in org.springframework.samples.petclinic.model
in the same way. This amounts to annotating
- fields
- getters
- setters
as @Nullable. I have committed my changes in commit HASH.
As a side note on good design, When designing value classes like these it is usually best to make them immutable.
Moving on. The annotation work we had to do on the entities was quite big, but
relax: this was already the bulk of @Nullable annotations in this tutorial.
Run the checker again – mvn -Pchecker compile – ...