Skip to content

How to migrate @Nullable provider method to jspecify #5165

@leonardehrenfried

Description

@leonardehrenfried

Since we recently upgraded to Java 25 we wanted to migrate our project to jspecify and stop using javax.annotations.Nullable:

We have run into problems with our nullable provider methods, which look like this:

import dagger.Module;
import dagger.Provides;
import jakarta.inject.Singleton;
import javax.annotation.Nullable;
import org.opentripplanner.datastore.api.GoogleStorageDSRepository;
import org.opentripplanner.datastore.api.OtpDataStoreConfig;
import org.opentripplanner.datastore.base.DataSourceRepository;
import org.opentripplanner.framework.application.OTPFeature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Module
public class GsDataSourceModule {

  private static final Logger LOG = LoggerFactory.getLogger(GsDataSourceModule.class);

  @Provides
  @Singleton
  @Nullable
  @GoogleStorageDSRepository
  DataSourceRepository provideGoogleStorageDataSourceRepository(OtpDataStoreConfig config) {
    if (OTPFeature.GoogleCloudStorage.isOff()) {
      return null;
    }
    return new GsDataSourceRepository(config.gsParameters());
  }
}

They cause runtime exceptions when I swap javax.annotation.Nullable with org.jspecify.annotations.Nullable:

java.lang.NullPointerException: Cannot return null from a non-@Nullable @Provides method
	at dagger.internal.Preconditions.checkNotNullFromProvides(Preconditions.java:64)
	at org.opentripplanner.ext.datastore.gs.GsDataSourceModule_ProvideGoogleStorageDataSourceRepositoryFactory.provideGoogleStorageDataSourceRepository(GsDataSourceModule_ProvideGoogleStorageDataSourceRepositoryFactory.java:52)
	at org.opentripplanner.ext.datastore.gs.GsDataSourceModule_ProvideGoogleStorageDataSourceRepositoryFactory.get(GsDataSourceModule_ProvideGoogleStorageDataSourceRepositoryFactory.java:42)
	at org.opentripplanner.ext.datastore.gs.GsDataSourceModule_ProvideGoogleStorageDataSourceRepositoryFactory.get(GsDataSourceModule_ProvideGoogleStorageDataSourceRepositoryFactory.java:13)
	at dagger.internal.DoubleCheck.getSynchronized(DoubleCheck.java:54)
	at dagger.internal.DoubleCheck.get(DoubleCheck.java:45)
	at org.opentripplanner.datastore.configure.DataStoreModule_ProvideDataStoreFactory.get(DataStoreModule_ProvideDataStoreFactory.java:51)
	at org.opentripplanner.datastore.configure.DataStoreModule_ProvideDataStoreFactory.get(DataStoreModule_ProvideDataStoreFactory.java:15)
	at dagger.internal.DoubleCheck.getSynchronized(DoubleCheck.java:54)
	at dagger.internal.DoubleCheck.get(DoubleCheck.java:45)
	at org.opentripplanner.graph_builder.GraphBuilderDataSources_Factory.get(GraphBuilderDataSources_Factory.java:50)
	at org.opentripplanner.graph_builder.GraphBuilderDataSources_Factory.get(GraphBuilderDataSources_Factory.java:14)
	at dagger.internal.DoubleCheck.getSynchronized(DoubleCheck.java:54)
	at dagger.internal.DoubleCheck.get(DoubleCheck.java:45)
	at org.opentripplanner.standalone.configure.DaggerLoadApplicationFactory$LoadApplicationFactoryImpl.graphBuilderDataSources(DaggerLoadApplicationFactory.java:225)
	at org.opentripplanner.standalone.configure.LoadApplication.validateConfigAndDataSources(LoadApplication.java:51)
	at org.opentripplanner.standalone.OTPMain.startOTPServer(OTPMain.java:120)
	at org.opentripplanner.standalone.OTPMain.main(OTPMain.java:55)

I debugged this with Claude and I found the suggestions not all that convincing.

Therefore I would like to hear it straight from the source: are Jspecify-Nullable-annotation provider methods supported or should I keep using javax.annotation.Nullable for that?

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions