2

I've been wanting to adopt Dagger 2 in conjugation with Retrofit 2. All seems to work nicely except for GET requests; they doesn't seem to have any headers attached with them.

Below is my NetworkModule which provides all networking-related dependencies for the whole app (note the @ForApplication scope annotation sprinkled there):

@Module
public class NetworkModule {

    // …

    @ForApplication
    @Provides
    OkHttpClient provideOkHttp(
            HttpLoggingInterceptor loggingInterceptor,
            @Named(PREFERENCE_CUR_LOGIN_SESSION) Preference<LoginSession> loginSessionPreference,
            DeviceCredentials deviceCredentials
    ) {
        final OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
        builder.addNetworkInterceptor(chain -> {
            if (loginSessionPreference.isSet()) {
                return chain.proceed(
                        chain.request().newBuilder()
                                .addHeader("token", loginSessionPreference.get().getTokenId())
                                .addHeader("device-id", deviceCredentials.getDeviceId())
                                .addHeader("Content-Type", "application/json")
                                .build()
                );
            } else {
                return chain.proceed(
                        chain.request().newBuilder().build()
                );
            }
        });
        return builder.build();
    }

    @ForApplication
    @Provides
    Retrofit provideRetrofit(Gson gson, OkHttpClient client) {
        return new Retrofit.Builder()
                .baseUrl("http://xxx.xxx.xxx/api/1.0/")
                .client(client)
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
    }

    @ForApplication
    @Provides
    XxxApi provideApi(Retrofit retrofit) {
        return retrofit.create(XxxApi.class);
    }
}

This module is supplied as a dependency for my ApplicationComponent (among other modules):

@ForApplication
@Component(
        modules = {
                ApplicationModule.class,
                RuntimeModule.class,
                DateFormatModule.class,
                PreferenceModule.class,
                NetworkModule.class
        }
)
public interface ApplicationComponent {

    // …
}

I've ran a debug session and confirmed that loginSessionPreference.isSet() is evaluated as true but nevertheless my request still showed up without any headers:

11-16 16:55:22.748 21747-22569/xxx.xxx.xxx D/OkHttp: --> GET http://xxx.xxx.xxx/api/1.0/public/get-all-data/site http/1.1
11-16 16:55:22.748 21747-22569/xxx.xxx.xxx D/OkHttp: --> END GET

Did I miss something?

Hadi Satrio
  • 428
  • 2
  • 8

2 Answers2

0

Use .addInterceptor instead of .addNetworkInterceptor()

Alex Shutov
  • 3,217
  • 2
  • 13
  • 11
0

First of all use addInterceptor() like Alex Shutov suggested.

Secondly, ensure in debug mode that methods addHeader() are called. If you use the same Retrofit instance (same injection) it could not be used because loginSessionPreference.isSet() always returns false.

Your method provideOkHttp() is called while OkHttpClient is necessary to provide Retrofit instance. Method provideOkHttp() requires Preference and it is injected while object OkHttpClient is created. You can treat it as a final variable (compiler even makes it final I think).

Please delete loginSessionPreference logic and hardcode some headers - it will gonna tell us if it is the issue.

In my opinion you will need to change this architecture a little.

Marcin W
  • 353
  • 4
  • 7