javacdidaggerjsr330

Is it possible to share common JSR 330 code between Dagger and CDI?


I'm tech lead on Agorava, a Framework that helps consuming social network data.

Today Agorava is build on CDI to ease its usage in Java EE stack, but we want to provide an implementation with Dagger to have a lighter solution working for Android.

My question is: can we share common JSR 330 compliant code between CDI and Dagger implementations? In other words, is it possible with Dagger to have compiled code in jar bearing JSR 330 annotation and source code extending or using this code in a Dagger specific Jar (with @Provides,@Modules and other Dagger specific items)?

If the answer is no is there any issue to compile my common JSR 330 jar with Dagger compiler and use it in my CDI implementation? More precisely will @Inject, qualifiers and other JSR 330 specifics will be still available at runtime and will the classes bearing these annotations code stay untouched by Dagger compiler? Finally is there a kind of tracker on Dagger generated code (classname, annotation) to allow CDI to detect it and ignore it?


Solution

  • You can share client code between Dagger and any other JSR-330 implementation, so long as your code does not implement behaviours that are not compatible with Dagger. Dagger 1.0, for instance, does not support method injection. Dagger 2.0 uses component interfaces instead of injectors, so your code would have to not care about that.

    @Inject and other JSR-330 API elements will still appear at runtime. Dagger does not access them at run time, creating generated code at compile time to interpret these annotations at run time. But these classes will still be valid JSR-330 compliant injectable classes for any JSR-330 app.

    What might be problematic is that Dagger will generate these extra classes and you would have to post-process the jar, or re-configure your build system in order to strip out the generated code, and move them to a supplementary jar. But that is a build-system configuration issue, and dagger is agnostic to it, so long as the generated code is available to it at runtime in the dagger-using application.

    One build-time option is to run the compiler with -proc:none, and in a second configuration with -proc:only, and pipe the output of the latter into another output folder, and jar that up. This can be done in maven by making different executions of the maven-compiler-plugin.

    Dagger generated classes should all have @Generated on them (coming soon), but also all descend from dagger.internal.ModuleAdapter, dagger.internal.Binding, or dagger.internal.StaticInjection. Subclasses of these are all safely ignorable by a non-dagger framework. In fact, they could be pro-guarded away.