Richard Zowalla created OPENNLP-1966:
----------------------------------------

             Summary: Resolve OpenNLP extensions through a generic provider SPI
                 Key: OPENNLP-1966
                 URL: https://issues.apache.org/jira/browse/OPENNLP-1966
             Project: OpenNLP
          Issue Type: Epic
            Reporter: Richard Zowalla
            Assignee: Richard Zowalla


OpenNLP loads extensions in two ways today. {{ExtensionLoader}} instantiates 
classes by name from model manifests, XML descriptors, training parameters and 
CLI arguments, guarded by a package allow\-list \(OPENNLP\-1820\). Service 
interfaces added in 3.0, such as {{TextEmbedder}} \(OPENNLP\-1937\), need 
discovery without a class name. Both needs are covered by one SPI.

This epic adds {{Provider}}, {{Providers}} and {{ProviderSpec}} to opennlp\-api 
and moves the {{ExtensionLoader}} call sites to them, one group of service 
interfaces per ticket. The resolution rules follow CDI:

||CDI||OpenNLP||
|bean type|SPI sub\-interface per service interface, for example 
{{TextEmbedderProvider extends Provider}}, registered in {{META\-INF/services}}|
|qualifiers|{{supports\(ProviderSpec\)}}|
|{{@Named}}|{{name\(\)}}, used by descriptors, manifests and the CLI|
|{{@Alternative}} \+ {{@Priority}}|{{priority\(\)}}, larger wins|
|{{@Vetoed}}|{{isAvailable\(\)}} for a provider that vetoes itself, plus the 
configuration key {{opennlp.provider..disabled}} for vetoing one from outside|
|{{Instance.get\(\)}} / iterating {{Instance}}|{{Providers.select\(spec\)}} / 
{{Providers.supporting\(spec\)}}|
|unsatisfied / ambiguous resolution|{{UnsatisfiedProviderException}} / 
{{AmbiguousProviderException}}|
|{{@Dependent}}|{{create\(spec\)}} returns an instance owned by the caller|
|{{openwebbeans.properties}} keyed by SPI name, ordered by 
{{configuration.ordinal}}|{{META\-INF/opennlp/providers.properties}} keyed by 
SPI FQN and ordered the same way, overridden by system properties, or a source 
the application passes to {{Providers.of\(spi, loader, configuration\)}}|
|{{DefaultLoaderService}} failing the deployment on a {{ServiceLoader}} error|a 
broken provider is skipped with a warning, an unreadable service file fails the 
lookup|

h3. Constraints for every ticket
\* Thread\-safe. {{Providers}} is immutable after {{of\(\)}}; providers are 
stateless and thread\-safe.
\* Application server compatible. No static caches of providers or class 
loaders; the thread context class loader is used, falling back to the SPI's 
class loader.
\* Native image friendly \(OPENNLP\-1954\). Providers have a public no\-arg 
constructor, lookup uses no reflection, availability is checked at call time.
\* Existing models and descriptors keep loading. The class name path stays as a 
fallback until the last ticket decides on its deprecation.
\* Adding a jar to the class path stays a code\-trust decision, so an operator 
can restrict which provider classes may be used at all 
\({{opennlp.provider..allowed}}\), and a provider that is not allowed or is 
disabled by class name is never instantiated.

h3. Tickets, in merge order
||Ticket||Scope||
|OPENNLP\-A|{{Provider}}, {{Providers}}, {{ProviderSpec}}, resolution 
exceptions, {{DocumentAnnotatorProvider}} with the stemmer as first provider|
|OPENNLP\-1937|{{TextEmbedder}} and {{TextEmbedderProvider}}, ONNX provider in 
opennlp\-dl|
|OPENNLP\-C|{{ExtensionLoader}} bridge and trainer providers|
|OPENNLP\-D|Feature generator providers and {{name}} in XML descriptors|
|OPENNLP\-E1|Data indexers, sequence codecs, string interners, doccat feature 
generators, entity linkers|
|OPENNLP\-E2|Tool factories and artifact serializers referenced from model 
manifests|
|OPENNLP\-E3|CLI format factories|



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to