5

The Checker Framework's Nullness Checker generates an error when it encounters an uninitialised field.

[ERROR] /home/glts/src/example/src/main/java/BookRepositoryImpl.java:[39,7]
error: [initialization.fields.uninitialized] the constructor does not initialize fields: em

Now, it is a common pattern to have some fields injected via dependency injection:

@Repository
public class BookRepositoryImpl implements BookRepository {
    @PersistenceContext 
    private EntityManager em;

    @Override
    @Nullable
    public Book findById(int id) {
        return em.find(Book.class, id);
    }

    // ...
}

Here, the @javax.persistence.PersistenceContext annotation ensures that em will hold a reference to an EntityManager instance after the repository has been constructed.

More generally, in these cases the application framework guarantees that fields are initialised and non-null when they are used – but the Checker Framework can't know this.

So far, I've found that one remedy is to convert field injection to constructor injection (@Inject). This isn't an option in the above example, though.

Is there a way to tell the Checker Framework that a field is injected, and therefore properly initialised and non-null, without simply suppressing these errors?

mernst
  • 7,437
  • 30
  • 45
glts
  • 21,808
  • 12
  • 73
  • 94
  • Anything you do to tell the Checker Framework that the field is properly initialized will be suppressing the error, so there isn't really a distinction between the two. I think your question is either, "Can I suppress the error per-field instead of writing `@SuppressWarnings("initialization.fields.uninitialized")` on the whole class?", or "Can I make the Nullness Checker recognize `@PersistanceContext` as that per-field warning suppression without writing `@SuppressWarnings` explicitly?" Can you please clarify? – mernst Oct 30 '15 at 14:12
  • @mernst I see. Then I'm interested in answers to both of your questions. Note that `@PersistenceContext` is part of the Java Persistence API, so I will not be able to change its definition easily. – glts Oct 30 '15 at 14:18
  • In your case the persistence framework might always return a non-null value, but is that a guarantee? Is it possible for an application to persist a null value into the persistence framework? – mernst Oct 30 '15 at 18:33
  • @mernst I'm not sure I understand the question. I trust the dependency injection framework (think Spring, Guice, CDI, JPA, ...) to do the wiring: injected fields may not be null. My goal is to express this trust in a way the Checker Framework understands. – glts Oct 30 '15 at 19:52

1 Answers1

5

You can suppress the error for a single field by writing @SuppressWarnings("initialization.fields.uninitialized") on the field declaration.

You can suppress the error for all fields by writing @SuppressWarnings("initialization.fields.uninitialized") on the class.

There exist injection frameworks that can inject null as a value where a @PersistenceContext annotation exists, such as when the .xml file isn't present, the code isn't running in a transaction, etc. Writing the @SuppressWarnings("initialization.fields.uninitialized") annotation is your way of saying that you trust that the one you are using will always inject a non-null value for your code.

mernst
  • 7,437
  • 30
  • 45