Eliminate silent dependencies was: Mandatory service requirement

Jaroslav Tulach jaroslav.tulach at oracle.com
Mon Feb 20 01:49:42 PST 2012


Jesse,
is your suggestion to force the my.corp.app module to always have a direct 
dependency on explicit implementation of a parser (e.g. saxon)? If so, I 
believe it would be unfortunate.

It may be valid for my.corp.app to select and prefer one implementation of a 
parser. If the whole application is tested with saxon parser, it is perfectly 
OK, to request that the saxon parser is used when my.corp.wsparser needs SAX.

However it is important for jaxp module or my.corp.wsparser module (as a 
reusable units) to properly indicate the need for implementation of a SAX 
parser too. Otherwise others, reusing jaxp or my.corp.wsparser will find out 
only during runtime that the execution environment is insufficient. 

Dependencies are here to statically describe the runtime environment of a 
module. When turning my.corp.wsparser on, the system needs to realize some SAX 
parser needs to be around (but it is OK, if my.corp.app narrows the selection 
or even changes it[1]). 

Services often act like singletons. Properly used singletons need to be 
"inherently initialized" (discussed at [2] and [3]). As such the jaxp module 
either:
- needs to declare that it requires service implementation of its parser(s)
- it can "requires service optional" and provide default fallback 
implementation(s)

Letting the jaxp module be silent about its dependencies is the worst 
solution. It sort of reminds me the time when every user of NetBeans 
org.netbeans.projectuiapi module had to also declare a requires dependency on 
its implementation module org.netbeans.projectui. It was a mess and we 
simplified the usage of that API a lot by replacing this with 

module org.netbeans.projectuiapi {
  requires service optional org.netbeans.project.uiapi.ActionsFactory;
  requires service optional org.netbeans.project.uiapi.OpenProjectsTrampoline;
  requires service optional org.netbeans.project.uiapi.ProjectChooserFactory;
}

In the NetBeans case the "requires service optional" style is more unit test 
friendly. But with a little tweaks mandatory "requires service" would work 
well too. 

The only wrong case is when the API module (jaxp or org.netbeans.projectuiapi) 
is silent about its dependencies.
-jt

[1] my.corp.app could somehow express that the DOM parser is not need, but 
that gets too complicated and if that is a frequent situation then there 
should be independent module for SAX and for DOM parser API anyway...
[2] http://wiki.apidesign.org/wiki/Singleton
[3] http://wiki.apidesign.org/wiki/Injectable_Singleton
	

>## 17. 2. 2012 17:15:50 ##<
> On 02/17/2012 10:23 AM, Alan Bateman wrote:
> >> drop the need to declare that a service is used at all: if and when
> >> ServiceLoader is called, determine the providers
> > 
> > the modules that are providing the service need to involved when
> > generating the configuration.
> 
> My point is that the providing modules could be added to the configuration
> in other ways. For example:
> 
> module jaxp {
>    exports javax.xml.parsers;
> }
> module xerces {
>    requires jaxp;
>    provides service javax.xml.parsers.SAXParserFactory with ...;
> }
> module saxon {
>    requires jaxp;
>    provides service javax.xml.parsers.SAXParserFactory with ...;
> }
> module my.corp.wsparser {
>    requires jaxp;
> }
> package my.corp.wsparser;
> class Parser {
>    void parse(my.corp.WebServiceInput input) {
>      SAXParser = SAXParserFactory.newInstance().newSAXParser();
>      // ...
>    }
> }
> module my.corp.app {
>    requires my.corp.wsparser;
>    requires saxon; // I have tested with this
> }
> 
> Here the call to SAXParserFactory.newInstance() would succeed so long as
> the application ultimately includes some XML parser, without the need for
> any "requires service javax.xml.parsers.SAXParserFactory" declaration. If
> you forgot to include one, this would probably be obvious (unless the
> parsing were on a rare and untested code path). The application module
> hardcodes a particular parser implementation which is known to work well,
> but this does not seem onerous: the wsparser module could be reused with
> other parsers, and offering a version of the app based on Xerces would be
> trivial. Conversely, quietly substituting Xerces at installation time
> might well lead to a host of subtle bugs.
> 
> Even if you wanted to support "requires service
> javax.xml.parsers.SAXParserFactory" for the hypothetical case of an
> application whose author optimistically believes that any XML parser would
> work equally well, there is no obvious reason why this declaration must be
> in the wsparser module and not in the app module - or should it be in the
> jaxp module which would actually be calling ServiceLoader? So long as the
> xerces and/or saxon modules are *somewhere* in the configuration, it
> should not matter which module(s) requested the service: the "provides
> service ..." declarations suffice for the module system to create an index
> of service -> providers, maintained during installation.



More information about the jigsaw-dev mailing list