Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

java

jaxb

jax-ws

I'm just digging around a bit trying to understand how Java can have standard reference implementations included in the JRE (eg JAXB/JAX-WS in JRE6), while still allowing 3rd-party implementations to override that (eg CXF).

I've gotten to the place that I found the javax.xml.ws.spi.FactoryFinder.find() method which either locates 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 creates an instance of that.

What I can't find is how/where/at which stage the JRE calls that FactoryFinder.find() method.

Can anybody enlighten me?

[edit] I've found the answer but am not allowed to post it myself for another 3 hours...

like image 649
Maarten Boekhold Avatar asked Jan 01 '12 11:01

Maarten Boekhold


People also ask

What is JAX-WS used for?

JAX-WS is a fundamental technology for developing SOAP (Simple Object Access Protocol) and RESTful (Web services that use representational state transfer, or REST, tools) Java Web services, where JAX-WS is designed to take the place of the JAVA-RPC (Remote Procedure Call) interface in Web services and Web-based ...

What is the use of JAXB in web service?

Java Architecture for XML Binding (JAXB) is an XML-to-Java binding technology that simplifies the development of web services by enabling transformations between schema and Java objects and between XML instance documents and Java object instances.

Is JAX-WS a framework?

JAX-WS RI 2.3. 1 is a Web Services framework that provides tools and infrastructure to develop Web Services solutions for the end users and middleware developers. With JAX-WS RI 2.3. 1, clients and web services have a big advantage: the platform independence of the Java programming language.


4 Answers

Figured out the complete logic. Actually nothing happens on JVM startup. It's all based on lazy loading, eg the real JAX-WS/whatever provider is only loaded/instantiated the first time it's needed.

In the case of loading the JAX-WS implementation:

Assume we want to call a web service, using code like:

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

port.mymethod(); 

then the following happens to initialize the JAX-WS implementation:

  • Any JAX-WS webservice extends javax.xml.ws.Service, so MyService_Service extends Service
  • When you create an instance of your web service, its superclass (javax.xml.ws.Service) is also initialized (constructor)
  • The constructor for "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.

Assume we want to publish a web service using code like:

@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 following happens to initialize the JAX-WS implementation:

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

The following links helped me understand this:

  • http://kickjava.com/src/javax/xml/ws/Service.java.htm
  • http://kickjava.com/src/javax/xml/ws/spi/Provider.java.htm
  • http://kickjava.com/src/javax/xml/ws/Endpoint.java.htm
  • (in addition to studying the source files as generated by wsdl2java from Apache CXF)
like image 66
Maarten Boekhold Avatar answered Oct 17 '22 01:10

Maarten Boekhold


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

The default value of this property is com.sun.xml.internal.bind.v2.ContextFactory. This factory is not required to implement any specific interface by it must implement method createContext(String, ClassLoader, Map)

like image 30
AlexR Avatar answered Oct 17 '22 01:10

AlexR


There are a few mechanisms which control which implementation you use. each jre/jdk has a built in "default" implementation hardcoded into the init code. There are also some system properties you can use to specify a specific implementation (as @AlexR mentioned). however, that is not the standard mechanism for specifying a different implementation. most alternate implementations include a special file in their META-INF directory (within the jar) which indicate to the jre/jdk that they should be used instead of the default implementation (this works without setting any system properties, you just drop the jars into the classpath). these special files are found by ServiceLoader utility and enable the alternate implementation to be automatically loaded.

like image 37
jtahlborn Avatar answered Oct 17 '22 01:10

jtahlborn


I found that a working JAXB sample fails after putting a weblogicfullclient.jar onto the classpath, because the jar contains a META-INF/services/javax.xml.bind.JAXBContext but not the implementation. Unfortunately, one cannot tell JAXB to "just use PLATFORM_DEFAULT_FACTORY_CLASS", you have to put it on a 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), the javax.xml.bind.ContextFinder.find(String, String, ClassLoader, Map) implementations differ for 1.6 and 1.7

like image 21
weberjn Avatar answered Oct 17 '22 01:10

weberjn