Annotation processing in bnd workspace build

55 views
Skip to first unread message

Fr Jeremy Krieg (Home)

unread,
Oct 21, 2020, 10:24:20 AM10/21/20
to bndtools-users
Hi all,

I pray you're all well.

I want to write an annotation processor that produces a synthetic lookup factory class based on annotated classes within the bundle. For example:

@MyAnnotation
public class A {}

@MyAnnotation
public class B {}

// Generated factory
public class SyntheticFactory {
    public Class<?> lookup(String tag) {
        switch (tag) {
        case "ATag":
           return A.class;
        case "BTag":
           return B.class;
        }
    }
}

Any suggestions on good ways to do this?

I considered using the Java annotation processor API but it doesn't play nice in an incremental build scenario. The problem is that the processor needs to know all of the annotated classes in the bundle in order to produce the correct synthetic class; however in an incremental build it may only be given access to one or none. Eg, if I make a change to A, then when it is recompiled B won't be in the compilation set and the annotation processor will produce a class that contains B but not A. 

The Bnd analyzer plugin model seems to be too late, as the compilation phase will have already finished by then. If I try to generate the source file at this point, the builder could either skip its compilation or get stuck in an endless loop.

One alternative is to define a custom Requirement namespace using the annotation, and then a custom extender to process the custom requirements in the running framework. This would work but adds runtime overhead and makes the users of my bundles have to install yet another bundle.

So I can see a few ways around the problem, but none of them are 100% ideal. I'm wondering if anyone has faced this issue before, and how they have solved it?

Blessings,
Fr Jeremy

Peter Kriens

unread,
Oct 22, 2020, 5:29:23 AM10/22/20
to via bndtools-users
I think the analyzer plugin is the way to go. You then have relatively easy access to the annotations. You can then create the Java code with something like JavaAssist so you do not have to use the standard compiler. 

Kind regards,

Peter Kriens



--
You received this message because you are subscribed to the Google Groups "bndtools-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bndtools-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bndtools-users/CAO6F8YzCxfCpL8SZAOX_%2B4YfO%2BraY2aBpZWQUA3Qq%3D%3D77wx0xQ%40mail.gmail.com.

Fr Jeremy Krieg (Home)

unread,
Oct 22, 2020, 10:17:05 AM10/22/20
to bndtools-users
Thanks Peter - I had a quick go at this but Bnd doesn't seem to be running my analyzer plugin. I've added it using a -plugin directive to build.bnd, using the path attribute to specify the path to the jar, but no joy. Any examples or tutorials for this anywhere? The docs are a bit sparse.

Blessings,
Fr J

Peter Kriens

unread,
Oct 23, 2020, 3:55:34 AM10/23/20
to via bndtools-users
You should use the -pluginpath.

cnf/build.bnd:

mavencentral: https://repo.maven.apache.org/maven2
ossrh: https://oss.sonatype.org/content/repositories/snapshots

-plugin:\
aQute.bnd.repository.maven.provider.MavenBndRepository;\
name="Maven Central";\
releaseUrl="${mavencentral}";\
snapshotUrl="${ossrh}";\
index="${.}/central.mvn";\
readOnly=true

cnf/central.mvn:
...
biz.aQute.bnd:biz.aQute.bndlib:5.2.0


foobar/src/foobar/Plugin.java

package foobar;

import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.EmbeddedResource;
import aQute.bnd.service.AnalyzerPlugin;

public class Plugin implements AnalyzerPlugin {

@Override
public boolean analyzeJar(Analyzer analyzer) throws Exception {
analyzer.getJar().putResource("hello", new EmbeddedResource("world", 0));
return false;
}

}

foobar/bnd.bnd
-buildpath: biz.aQute.bndlib;version='5.2.0'


Copy the JAR foobar.jar from generated to cnf/foobar.jar

cnf/build.bnd:

mavencentral: https://repo.maven.apache.org/maven2
ossrh: https://oss.sonatype.org/content/repositories/snapshots

-plugin:\
aQute.bnd.repository.maven.provider.MavenBndRepository;\
name="Maven Central";\
releaseUrl="${mavencentral}";\
snapshotUrl="${ossrh}";\
index="${.}/central.mvn";\
readOnly=true,\
foobar.Plugin

-pluginpath: ${.}/foobar.jar

If you rebuild foobar, you will see a 'hello' resource with 'world' as content. Remember to copy the JAR when you make changes tp the plugin.

You can put a project's generated jar on the -pluginpath but you tend to run quickly into problems that crater the build. Sounds convenient, but I remember that it wasn't.

We really need the External Plugins to be able to provide an AnalyzerPlugin ...

Hope this helps. Kind regards,

Peter Kriens
> To view this discussion on the web visit https://groups.google.com/d/msgid/bndtools-users/CAO6F8YzHoxi6tj4_KTkDyLQdU%3DCF0hMQ8Xq00ODtyke%2BNDZVbg%40mail.gmail.com.

Fr Jeremy Krieg (Home)

unread,
Oct 23, 2020, 5:31:06 AM10/23/20
to bndtools-users
Thanks a bunch Peter! That should get me started.

Is the problem with generated with that particular directory? Or with the fact that it's auto updated? If the former i could deploy it to a local repo and set the path there. I could imagine it being a problem on Windows especially though b due to file locking...

Peter Kriens

unread,
Oct 23, 2020, 5:53:58 AM10/23/20
to via bndtools-users
On 23 Oct 2020, at 11:32, Fr Jeremy Krieg (Home) <jezzy...@gmail.com> wrote:
Thanks a bunch Peter! That should get me started.

Is the problem with generated with that particular directory? Or with the fact that it's auto updated?
No, the update works fine. However, if it somehow gets deleted then the build fails and the project cannot be build again until you remove -pluginpath.

And yes, windows probably makes it even worse :-)

Kind regards,

Peter Kriens

Reply all
Reply to author
Forward
0 new messages