Roboguice throws ClassNotFoundException: AnnotationDatabaseImpl

317 views Asked by At

I have a multi module project which has a class derived from RoboActivity with some injected pojo fields.

Those fields' classes also have injected fields which in turn also have injected fields. Some of those classes live in different modules so what I need is cross module injection.

I followed the directions in the Robo Blenders wiki (supposedly) but when trying to run the app I get 'ClassNotFoundException: AnnotationDatabaseImpl' and the app stops.

These are the classes (interfaces not shown):

@ContentView(R.layout.activity_about)
public class AboutActivityImpl extends AbstractActivityImpl implements AbstractActivity, AboutActivity {

    @InjectView(R.id.app_name) private TextView app_name;
    @InjectView(R.id.app_copyright) private TextView app_copyright;
    @InjectView(R.id.app_version) private TextView app_version;

    // MVP 
    @Inject
    AboutPresenter presenter;  //IS INJECTED

    // MVP 
    @Override
    protected MvpEvent setPresenter() {
        setPresenter(presenter);
        return new AboutActivityInitEvent();
    }
.
.
.
}

public class AboutPresenterImpl extends AbstractPresenterImpl implements AboutPresenter {
    @Inject
    AppInfo appInfo;  //IS INJECTED

    @SuppressWarnings("unused")
    @Inject @Config(Property.APP_COPYRIGHT) //IS INJECTED
    private String appCopyright;
.
.
.
}

public class AppInfoImpl implements AppInfo {
    @Inject
    AppInfoApi appInfoApi;  //IS NOT INJECTED!!

    public AppInfoImpl() {
    }
.
.
.
}

public class AppInfoApiImpl implements AppInfoApi {
    @Inject
    Application application;  //IS NOT INJECTED!!

    public AppInfoApiImpl() {
    }
.
.
.
}

Roboguice modules are as follows:

public class AppModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(AboutPresenter.class).to(AboutPresenterImpl.class);
    }
}

public class DomainModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(AppInfo.class).to(AppInfoImpl.class);
    }
}

public class PlatformModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(AppInfoApi.class).to(AppInfoApiImpl.class);
    }
}

Manifest is as follows:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="ar.com.abimobileapps.androidapp">
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <meta-data android:name="roboguice.modules"
                android:value="ar.com.abimobileapps.platform.config.PlatformModule,
ar.com.abimobileapps.androidapp.configuration.ConfigurationModule,
ar.com.abimobileapps.androidapp.persistence.config.PersistenceModule,
ar.com.abimobileapps.androidapp.domain.config.DomainModule,
ar.com.abimobileapps.androidapp.config.AppModule" />
            <meta-data android:name="roboguice.annotations.packages"
                android:value="ar.com.abimobileapps.androidapp,
                               ar.com.abimobileapps.androidapp.domain,
                               ar.com.abimobileapps.androidapp.persistence,
                               ar.com.abimobileapps.platform" />
            <activity
                android:name=".ui.AboutActivityImpl">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
    .
    .
    .
        </application>
    </manifest>

These are the modules build.gradle files (snippets):

build.gradle(app module):

dependencies {
.
.
.
    // Roboguice
    compile 'org.roboguice:roboguice:3.0.1'
    provided 'org.roboguice:roboblender:3.0.1'
    // Modules
    compile project(':domain')
    compile project(':platform')
    compile project(':configuration')
}

project.tasks.withType(JavaCompile) { task ->
    options.compilerArgs << "-AguiceAnnotationDatabasePackageName=ar.com.abimobileapps.androidapp"
}

build.gradle (domain module):

dependencies {
.
.
.
    // Roboguice
    compile 'org.roboguice:roboguice:3.0.1'
    provided 'org.roboguice:roboblender:3.0.1'
    // Modules
    compile project(':persistence')
    compile project(':platform')
}

project.tasks.withType(JavaCompile) { task ->
    options.compilerArgs << "-AguiceAnnotationDatabasePackageName=ar.com.abimobileapps.androidapp.domain"
}

build.gradle (persistence module):

dependencies {
.
.
.
    // Roboguice
    compile 'org.roboguice:roboguice:3.0.1'
    provided 'org.roboguice:roboblender:3.0.1'
}

project.tasks.withType(JavaCompile) { task ->
    options.compilerArgs << "-AguiceAnnotationDatabasePackageName=ar.com.abimobileapps.androidapp.persistence"
}

build.gradle (platform module):

dependencies {
.
.
.
    // Roboguice
    compile 'org.roboguice:roboguice:3.0.1'
    provided 'org.roboguice:roboblender:3.0.1'
}

project.tasks.withType(JavaCompile) { task ->
    options.compilerArgs << "-AguiceAnnotationDatabasePackageName=ar.com.abimobileapps.platform"
}

AnnotationDatabaseImpl.class files are generated for packages ar.com.abimobileapps.androidapp, ar.com.abimobileapps.androidapp.domain, ar.com.abimobileapps.androidapp.persistence and ar.com.abimobileapps.platform. Inspecting its source code I see that all injected and 'to inject' classes are referenced.

So I cannot understand why I get 'ClassNotFoundException: AnnotationDatabaseImpl' when running the app.

The classes that are correctly injected (AboutActivityImpl, AboutPresenterImpl and AppModule) are in the same project module while the other 2 classes (the failed classes) are in two different project modules (AppInfo/DomainModule in one module, AppInfoApi/PlatformModule in other module).

Roboguice is version 3.0.1.

Any idea?

1

There are 1 answers

6
Christine On

You can set Roboguice.setUseAnnotationDatabases(false) to prevent the Exception. Also, I'd advise you to move to Roboguice 4.0. You can find Roboguice 4.0 in the Roboguice project on Github as branch rg-4-final. Rg 4.0 is more lightweight, hence it has a much better performance.