How does Java initialize a JAXB / JAX-WS / etc implementation?

I am just a little versed in trying to figure out how Java can have the standard reference implementations included in the JRE (e.g. JAXB / JAX-WS in JRE6), while allowing third-party implementations to override this (e.g. CXF).

I got to where I found the javax.xml.ws.spi.FactoryFinder.find () method, which either detects the class specified in META-INF / services / java.xml.ws.spi.Provider or com.sun.xml. internal.ws.spi.ProviderImpl (for the JAX-WS case) and instantiate this.

What I cannot find is like / where /, at what stage the JRE calls the FactoryFinder.find () method.

Can anyone enlighten me?

[edit] I found the answer, but I’m not allowed to post it for another 3 hours ...

+6
source share
4 answers

Figured out the full logic. Nothing actually happens when the JVM starts. All this is based on lazy loading, for example, real JAX-WS / any provider is loaded / created only for the first time.

In case of loading the JAX-WS implementation:

Suppose we want to call a web service using the following code:

MyService service = new MyService_Service(); MyServiceSoap port = service.getMyServiceSoap(); port.mymethod(); 

then the JAX-WS implementation is initialized:

  • Any JAX-WS web service extends javax.xml.ws.Service, so MyService_Service extends the service
  • When you instantiate your web service, its superclass (javax.xml.ws.Service) is also initialized (constructor)
  • The constructor for the "Service" calls javax.xml.ws.spi.Provider.provider (), which is a static method that uses javax.xml.ws.spi.FactoryFinder.find () to find and instantiate the implementation as configured.

Suppose we want to publish a web service using the following code:

 @WebService(endpointInterface = "my.package.MyService") public class MyServiceImp implements MyService { ... } MyServiceImp service = new MyServiceImp(); InetSocketAddress addr = new InetSocketAddress(8080); Executor executor = Executors.newFixedThreadPool(16); HttpServer server = new HttpServer(addr); server.setExecutor(executor); HttpContext context = server.createContext("/MyService"); Endpoint endpoint = Endpoint.create(service); endpoint.publish(context); server.start(); 

then the JAX-WS implementation is initialized:

  • Endpoint.create () runs Provider.provider (). createEndpoint ()
  • Provider.provider () is a static method that uses javax.xml.ws.spi.FactoryFinder.find () to search and instantiate an implementation as it is configured.

The following links helped me figure this out:

+5
source

You can change the default behavior using the javax.xml.bind.context.factory system property. Its value must be the fully qualified name of the factory class.

By default, this property is com.sun.xml.internal.bind.v2.ContextFactory . For this factory, it is not required to implement any specific interface, it must implement the createContext(String, ClassLoader, Map) method createContext(String, ClassLoader, Map)

+3
source

There are several mechanisms that control which implementation you use. each jre / jdk has a built-in "standard" implementation, hard-coded into the initialization code. There are also some system properties that can be used to indicate a specific implementation (as mentioned in @AlexR). however, this is not a standard mechanism for specifying a different implementation. most alternative implementations include a special file in their META-INF directory (in the bank), which tells jre / jdk that they should be used instead of the default implementation (this works without setting any system properties, you just throw the banks into the classpath). these special files are located in ServiceLoader and allow you to automatically load an alternative implementation.

+2
source

I found that the working JAXB sample failed after it placed weblogicfullclient.jar in the classpath, since the jar contains the file META-INF / services / javax.xml.bind.JAXBContext but not the implementation. Unfortunately, JAXB cannot "just use PLATFORM_DEFAULT_FACTORY_CLASS", you have to put it in the System property (-Djavax.xml.bind.JAXBContext = com.sun.xml.internal.bind.v2.ContextFactory for 1.6 and -Djavax.xml. bind.context.factory = .. for 1.7), implementations of javax.xml.bind.ContextFinder.find (String, String, ClassLoader, Map) differ by 1.6 and 1.7

+1
source

Source: https://habr.com/ru/post/904835/


All Articles