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