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...
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 ...
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.
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.
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:
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:
The following links helped me understand this:
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)
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With