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

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions