1

In a past question I asked how to design a system where:

  • A class contains one or more optional methods.
  • Optional methods are implemented by plugins that may or not may be present at compile-time.
  • If a user invokes a method whose associated plugin is not present at compile-time, they will get a compile-time error.

I provided one possible solution that works in Java 8.

Unfortunately, this solution depends on the use of split packages (two modules exporting the same package) which are disallowed by the Java 9 Module System.

How can this be implemented in Java 9?

Naman
  • 27,789
  • 26
  • 218
  • 353
Gili
  • 86,244
  • 97
  • 390
  • 689

1 Answers1

0

Services

If I have understood the question correctly what you're looking forward to using are Services from the module system.

Java has long supported services via the java.util.ServiceLoader class, which locates service providers at run time by searching the classpath.

The module system could identify uses of services by scanning the class files in module artifacts for invocations of the ServiceLoader::load method.

With your current project structure, you should define an abstract class or an interface that can be a extended of implemented in the guava, coremodule classes and is provided by them.


A module uses a particular service is an important aspect of that module’s definition, so for both efficiency and clarity its expressed in the module’s declaration with a uses clause:

module com.foo.bar.sql {
    uses com.foo.Verifiers;
}

A module provides an implementation of a particular service is equally fundamental, however, this is put in the module’s declaration with a provides clause:

module guava {
    provides com.foo.Verifiers with com.guava. GuavaVerifier;
}

module core {
    provides com.foo.CoreVerifier with com.guava. GuavaVerifier;
}
Naman
  • 27,789
  • 26
  • 218
  • 353
  • I don't think your post answers my question. I am expecting `core` and `guava` modules to export an implementation for `GuavaVerifier`. I am expecting `core` to export a no-op implementation and `guava` to export an implementation that does something. I want `guava`'s implementation to override `core`'s implementation if both are imported. – Gili Oct 08 '17 at 03:10
  • @Gili Could you help me understand how do you want one implementation to override another implementation? Are they related? Is any of them a subclass of the other? – Naman Oct 08 '17 at 03:25
  • See the past question mentioned above for a detailed explanation. Briefly: `core` defines an interface with optional methods. It exports a (default) implementation that does nothing when those methods are invoked. `guava` exports an implementation with the same class name/package that does something else when those methods are invoked. Users "enable" optional functionality by importing optional modules. The classes implement the same interface but they are not related in any other way. – Gili Oct 08 '17 at 04:27
  • 1
    Once you are able to obtain references to the providers, the caller can decide which provider to invoke and under which conditions. In SLF4J, we assume a single provider. If that is not the case, we emit a warning and pick the first provider in the list of providers. However, other policies are possible. – Ceki Dec 03 '17 at 08:46