Immutables: Retention behaviour seems changed in 2.6.0-alpha3 → 2.6.0

Created on 22 May 2018  Â·  8Comments  Â·  Source: immutables/immutables

Hello!

It seems that by upgrading to 2.6.0 from 2.6.0-alpha3, my OSGi bundles are now getting unwanted references to the org.immutables.value package. It's almost as if the annotations are suddenly considered to have run-time retention.

I've created a repro case here with a rather long log in the README.md:

https://github.com/io7m/bnd-maven-plugin-20180522

Basically, what should happen (and what always did happen previously) is that the OSGi manifest generator (bnd) analyzes the bytecode and adds Import-Package directives into the jar manifest for each dependency that's required at run-time. Because immutables has annotations that don't have any run-time retention, there should never be an Import-Package directive that refers to the org.immutables.value package. However, I'm seeing org.immutables.value references in the jar manifests with 2.6.0.

I notice in the japicmp output that some retention annotations were removed. I realize that CLASS retention is already the default and so this shouldn't have had any effect, but it seems that it actually has, somehow.

I'm not sure if this is an Immutables problem or Bnd problem. I'm asking on their mailing list, but I said I'd file an issue here as well, just in case.

bug completed

Most helpful comment

OSGi users everywhere thank you! :smile:

All 8 comments

Think I've got it: The code now adds org.immutables.value.Generated annotations to generated classes unless the user suppresses those in some way (such as by whitelisting).
These have RUNTIME retention, so this results in the Bnd bytecode analyzer adding dependencies on the org.immutables.value package.

I thought of adding this is a separate artifact (value with classifier generated for example), ended up with the same artifact (if the value artifact is not present at runtime, annotations would silently (iirc) fail to parse and be ignored). Hope this does not cause many problems if you can work around it (?)

It's very easily worked around with whitelisting or other suppression of annotations. It's probably worth documenting somewhere though: It's a bit of an insidious problem in that you won't notice anything is wrong until you try to load your code in OSGi and find that there's this org.immutables.value dependency that can't be resolved.

In fact it's not so easy to workaround, at least not verbosely. I've been hit by this as well, in OSGi environment.

I have something like 20 projects in a workspace (like Gradle multi-project), each of which uses immutables. My options are:

  1. For each project, in top-level package define a style

    @org.immutables.value.Value.Style(allowedClasspathAnnotations = { java.lang.Override.class })
    package top.pkg;  
    

    I have to do this in at least every project, generally more often, in every @Value.Style, as styles are not merged anyhow.

  2. Make BND (the tool to make OSGi bundles' manifests) to treat Immutables as optional, like this in bnd.bnd file:

    Import-Package: org.immutables.value; resolution:=optional, *
    

    This also has to be done in every project.

  3. Make Immutables JAR a proper bundle. This requires no changes in build process, but requires changes to Immutables JAR manifest and the deployment environment (i.e. dropping the bundle into OSGi runtime). Also, the overhead of whole JAR (almost 3MB) is really high for such a small effect.

    Extracting only org.immutables.value package as e.g. *-api.jar would allow for very small overhead, but requires additional work.

I'm afraid, no simple solution here... I'd go with 3., but clearly I'm biased.

Extracting only org.immutables.value package as e.g. *-api.jar would allow for very small overhead, but requires additional work.

Sorry, just realized there is annotations artifact on Maven Central, which is just that, the single package. :)

I ended up creating a single @Style annotation that I depend on in all of my projects that use immutables:

https://github.com/io7m/immutables-style/blob/develop/src/main/java/com/io7m/immutables/styles/ImmutablesStyleType.java

I've verified that this eliminates dependencies on org.immutables.value at run-time:

$ bnd print com.io7m.jjacob.vanilla/target/com.io7m.jjacob.vanilla-0.0.1-SNAPSHOT.jar
[MANIFEST com.io7m.jjacob.vanilla-0.0.1-SNAPSHOT]
Bundle-Description                       JACK bindings                           
Bundle-DocURL                            https://www.io7m.com/software/jjacob    
Bundle-ManifestVersion                   2                                       
Bundle-Name                              com.io7m.jjacob 0.0.1-SNAPSHOT - JACK bindings
Bundle-SCM                               https://github.com/io7m/jjacob          
Bundle-SymbolicName                      com.io7m.jjacob.vanilla                 
Bundle-Vendor                            io7m.com                                
Bundle-Version                           0.0.1.201806070858                      
Export-Package                           com.io7m.jjacob.vanilla;uses:="com.io7m.jjacob.api,com.io7m.jjacob.jnr";version="0.0.1"
Implementation-Build                     9d67f46ba096b4123dbe7ec6b740fe7c8739de0e
Implementation-Title                     com.io7m.jjacob                         
Implementation-Vendor                    io7m.com                                
Implementation-Vendor-Id                 com.io7m.jjacob                         
Implementation-Version                   0.0.1-SNAPSHOT                          
Import-Package                           com.io7m.jjacob.api;version="[0.0,1)",com.io7m.jjacob.jnr;version="[0.0,1)",com.io7m.junreachable;version="[2.0,3)",jnr.constants.platform;version="[0.9,1)",jnr.ffi;version="[2.1,3)",org.slf4j;version="[1.8,2)"
Manifest-Version                         1.0                                     
Require-Capability                       osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=9.0))"
Sealed                                   true                                    
Specification-Title                      com.io7m.jjacob                         
Specification-Vendor                     io7m.com                                
Specification-Version                    0.0.1-SNAPSHOT                          

[IMPEXP]
Import-Package
  com.io7m.jjacob.api                    {version=[0.0,1)}
  com.io7m.jjacob.jnr                    {version=[0.0,1)}
  com.io7m.junreachable                  {version=[2.0,3)}
  jnr.constants.platform                 {version=[0.9,1)}
  jnr.ffi                                {version=[2.1,3)}
  org.slf4j                              {version=[1.8,2)}
Export-Package
  com.io7m.jjacob.vanilla                {version=0.0.1}

This can obviously only work well if all of your projects use a consistent style...

in 2.7.1 org.immutables.value.Generated is made class retained. So if someone want runtime generated annotation, will have to use InjectAnnotation facility to inject custom annotation on the generated type and builder.

OSGi users everywhere thank you! :smile:

Was this page helpful?
0 / 5 - 0 ratings