Avoiding same-package conflicts

Jochen Theodorou blackdrag at gmx.org
Tue Nov 3 09:56:56 UTC 2015

On 02.11.2015 22:03, Alex Buckley wrote:
> The initial modularization of JavaFX had a similar pattern: more split
> packages than you would think, due to a "horizontal" module wanting to
> share packages with numerous "vertical" domain modules. There, the
> "horizontal" module was a 'builder' module which hoped to add
> $COMPONENTBuilder classes to the packages of various 'component'
> modules; eventually the $COMPONENTBuilder classes were deemed
> unnecessary and the 'builder' module deleted. For Groovy, I suggest that
> your "base module" has the greatest claim to the
> org.codehaus.groovy.runtime package, and that the
> groovy-{nio,sql,swing,xml} modules should export
> org.codehaus.groovy.runtime.* subpackages to the base module only.
> It doesn't seem great that the groovy-ant and groovy-test modules try to
> augment the important groovy.util package owned by your base module.
> Speaking generally, it makes no sense to allow a module to protect its
> internals if at the same time its API can be augmented by unrelated
> modules -- it can't be the "same" API because it doesn't have access to
> the same internals.

Oh, I am not talking about internal API here.

The conflicts in org.codehaus.groovy.runtime are due to historic 
reasons. They are mostly extension methods, which could be in any 
package. But traditionally they had been part of DefaultGroovyMethods, 
from which we factored out a lot of methods over time to modularize the 
codebase more. And they tended to stay in the same package, since there 
was in the past no reason to choose a different one... looks strange to 
put a single class in a package that could be somewhere else perfectly 
fine after all. If we move those classes to new packages, then we will 
get into trouble with static compiled code. After all we did that 
modularization before Groovy had an optional static compiler, and we did 
a major version change for that (from 1.8 to 2.0) as well.

For groovy.util the case is more problematic. Moving GroovyTestCase into 
a new package would for example break an estimated 95% of our test 
cases. What will most likely happen is, that the test module merges with 
the base module thus pulling in "optional" dependencies like JUnit 3... 
which is in conflict with us trying to slim down the base runtime even 
more, to for example give the android version an easier standing. We 
have been thinking about for example moving the compiler into a separate 
jar. But splitting something something as tightly coupled as that will 
cause numerous same-package conflicts... Just to give an example... Eval 
is a class in groovy.util and used for example like this:

  assert 10 == Eval.me(' 2 * 4 + 2')
  assert 10 == Eval.x(2, ' x * 4 + 2')

Of course this will call the compiler.. but what use is there to make a 
groovy-base and a groovy compiler jigsaw style module, if they strongly 
depend on each other anyway?

Anyway... my intension was to give an example of how some people divide 
a broad library into "modules" and how it does not fit the "one module 
per jar, no exported name space duplication" idea. And you just 
confirmed it with the initial modularization of JavaFX.

Just to clarify... hiding parts of API is out of scope for groovy 
modules atm. A first step for us would be to get some kind of mapping of 
our current multi jar system to jigsaw modules that fits our needs.

>> also... there is a automated meta class lookup system, that is based on
>> the package name with a prefix. So someone could provide a meta class
>> for java.util.ArrayList, while another does this for LinkedList. If they
>> are using modules, they cannot be loaded at the same time. Granted, I
>> don't like this mechanism, and I am looking for ways to deprecate it in
>> the near future, but it is another example of same-package conflicts.
> Does this mean a Groovy meta class can currently be defined as a class
> in the java.* run-time package of the bootstrap loader?

The class would be groovy.runtime.metaclass.java.util.ArrayListMetaClass 
and doesn't have need the bootsrap loader for this of course. We 
actually always avoided implementing logic that depends on being in the 
bootstrap loader.

bye Jochen

More information about the jigsaw-dev mailing list