jsr294-modularity-observer Digest, Vol 14, Issue 7
Alex Buckley
Alex.Buckley at Sun.COM
Fri Apr 17 12:29:40 EDT 2009
Hi Evan,
Thanks for documenting your thoughts. The bootstrapping issues are hard
if the current clean design of annotation processors is to be kept.
By the way, If you didn't like my examples of @Requires and
@RequiresContainer, what did you make of Peter's @Bundle:
@Bundle(
require_bundle = "com.acme.foo; version='[2.1,3)',"
+ "com.acme.foo2,"
+ "com.aQute.bndlib; version='2.1'",
bundle_symbolicname = "biz.aQute.bnd",
bundle_name = "Bnd Annotations",
bundle_description = "Provides annotations to OSGi bundles",
bundle_docurl = "http://www.aQute.biz",
bundle_copyright = "Copyright aQute SARL (c) 2002-2009"
)
module aQute.bnd.annotation;
Alex
Evan Cowden wrote:
> I've spent some time a while ago creating a set of annotations and
> annotation processors to generate OSGi metadata. There are a few
> things I learned during the process that I think may be relevant to
> the current discussion:
>
> 1. Creating a good set of annotations is harder than it looks. Even
> with several tries, I was never able to create anything that was
> nearly as clean as a plain text file; after a while my teammates all
> abandoned the annotations. Most importantly, the no-duplicates
> limitation can create very convoluted and difficult to understand
> structures. Take a look at Peter's suggestions - they are quite
> similar to what I tried first, although mine went on a package-info:
>
> @Requires(module="com.foo.bar", version=">=4.0")
> module com.foo.app @ 1.0;
>
> @RequiresContainer({
> @Requires(module="com.foo.bar", version=">=4.0"),
> @Requires(module="com.foo.baz", version=">=5.0")
> })
> module com.foo.app @ 1.0;
>
> Not only is it a lot of typing, but there are two distinct ways to
> express a dependency: the @Requires and the @Requires nested in
> @RequiresContainer. It took a bizarrely long amount of time to
> explain this to junior developers (and even some senior developers).
> Moreover, when one starts with the former, as is often the case,
> adding a new dependency requires not just adding another line, but
> reformatting what already exists.
>
> I also strongly recommend against the following format for multiple
> dependencies, which I tried and found lead to more bugs than I can
> count:
>
> @Requires({ "com.foo.bar", "com.foo.baz" }, { ">=4.0", ">=5.0" })
> module com.foo.app @ 1.0;
>
> The separation of module names and versions invariably leads to
> erronous editing that put the names and versions out of whack.
>
> 2. It is significantly trickier to create tooling that manipulates
> annotations than a plain text file. For instance, take a look at
> tooling like the Eclipse PDE Manifest Editor. Most IDEs will want to
> provide something similar for a standard module system. The
> annotation syntax is not only more difficult, but you need to maintain
> the import statements for the annotations as well. It's not
> impossible, but it's not trivial either.
>
> 3. What about the extender pattern? With OSGi, it's both easy and
> common to stick extra metadata into the manifest. For instance, one
> might make a bundle that will deploy servlets in other bundles by
> examining all manifests for an ExportServlet attribute. With strongly
> typed annotations, there is no room to just add a line with an extra
> tag. For this kind of extender, it would be possible for the extender
> provider to create their own annotation - that may or may not be an
> improvement - but it complicates #4 below.
>
> There is another kind of extension, however, that is even more
> difficult. Eclipse Equinox, for instance, also adds extra attributes
> to existing elements, for instance:
>
> Export-Package:
> org.eclipse.pde.internal.ui;x-internal:=true
>
> The x-internal flag is (correct me if I'm wrong) an Equinox-specific
> extension to standard OSGi metadata. It works perfectly fine here,
> but how would annotations accommodate it? Do Equinox users need to
> use a specialized set of annotations to supplant the standard ones?
> With the status quo, a bundle with Equinox-specific information can
> still work in another container - the other container will just ignore
> the extra bits it doesn't understand. That won't work if Equinox
> developers start using custom annotations.
>
> 4. Annotations themselves create dependencies. This is, by far, the
> trickiest problem I encountered. Since annotations are class files,
> they create a binary dependency. Yet when annotations are used to
> express dependencies, it creates a chicken-and-egg problem. You need
> to resolve the dependency before you can get the information telling
> you what dependencies to resolve. The solution is invariably to
> bootstrap those annotations at a level below the module system, but if
> you ask me, a module system that doesn't work for itself is a sure
> sign of a poorly designed module system.
>
> I'm not trying to move the Expert Group towards or away from any one
> technology, but I did want to share my experience. I hope that these
> observations can help lead to a better specification.
>
> - Evan Cowden
More information about the jsr294-modularity-observer
mailing list