0

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?

Abi
  • 1
  • 3

1 Answers1

0

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.

Christine
  • 5,617
  • 4
  • 38
  • 61
  • `Roboguice.setUseAnnotationDatabases(false)` is a quick fix, cause it switches from compile time to runtime reflection, slowing down your app a lot – Benoit Jadinon Apr 22 '16 at 08:21
  • I know, but when I tried, this was a long time ago, I couldn't get RoboBlender to work. Now I use 4.0. – Christine Apr 22 '16 at 08:23
  • yeah me neither, and I still had the AnnotationDatabaseImpl issue with 4.0 . but I found out `apply plugin: 'com.neenbedankt.android-apt'` was the culprit. – Benoit Jadinon Apr 22 '16 at 09:12
  • 4.0 is a lot faster, so I don't mind the quick fix. But if someone gets it to work, please post it here. – Christine Apr 22 '16 at 12:31
  • I haven't found benchmarks yet on this, do you know faster by how much ? thx – Benoit Jadinon Apr 22 '16 at 14:20
  • I haven't benchmarked it. Just my observation that my app got faster after upping roboguice to 4.0. You know that "neenbedankt" is Dutch for "no thanks"? – Christine Apr 22 '16 at 23:28