0

I have an Android library module where a public class uses some annotations from an external library. The annotations are purely used internally, so I don't want to expose it as an API Gradle dependency, leaking that dependency to clients, but keep it as an implementation one.

However, the presence of the annotation causes warnings for applications using my library, since the annotation class can not be resolved. This is actually quite understandable - a public class contains a symbol which is not on the compile path of the client - but is there a way to have annotations kept internal when packaging a library - or somehow ignored by the calling application? The annotations are RUNTIME retention ones, so they cannot be completely stripped out in a build step or similar.

Setup for illustrative purposes:

my-library:

  • build.gradle has implementation com.example.foobar which contains @Example annotation
  • Foo.java is a public class annotated with @Example:
@Example(foo = "bar")
public class Foo {
   ...
}
  • Other classes in my-library itself require the annotation to be present in runtime

some-client:

  • build.gradle has implementation com.example.mylibrary which contains the class Foo
  • This application uses Foo objects, but doesn't need to know about the annotation, however when building it will get:
classes.jar(com/example/Foo.class): warning: Cannot find annotation method 'foo()' in type 'Example': class file for com.example.Example not found

If I change implementation to API for com.example.foobar, the warning is eliminated, but the application will now get the @Example annotation on its build path, which is an internal implementation detail. Is there another way?

herman
  • 11,740
  • 5
  • 47
  • 58
JHH
  • 8,567
  • 8
  • 47
  • 91
  • If you don't want the annotations to be present at runtime, then why mark them as `RUNTIME` retention? If you don't want them to be visible in the build artifact, turn them into a `SOURCE` retention annotation instead. If that's not an option you can do what Android itself does: have two different build artifacts, one which is the actual code that you build and run, and another one that serves as the API that others compile against (except in your case the second one could also be a fully-working, but different artifact). – Joachim Sauer Feb 24 '20 at 16:00
  • I need them to be runtime. They're for serialization of objects. Yes, I can invent something that creates separate stripped artifacts but it seems a bit excessive. But thanks. – JHH Feb 24 '20 at 17:01
  • if you need the classes to be present at runtime, then there's really no way around requiring them on the classpath of your users at runtime. Or are the annotations only needed by your library when not running within the context of some-client (i.e. only within some internal tool, but not when loaded by user code)? – Joachim Sauer Feb 24 '20 at 17:03

0 Answers0