2012-01-01 6 views
6

Estoy buscando un poco tratando de entender cómo Java puede tener implementaciones de referencia estándar incluidas en el JRE (por ejemplo, JAXB/JAX-WS en JRE6), al tiempo que permite que las implementaciones de terceros anulen (por ejemplo, CXF).¿Cómo inicializa Java la implementación de JAXB/JAX-WS/etc?

He llegado al lugar en el que encontré el método javax.xml.ws.spi.FactoryFinder.find() que localiza la clase especificada en META-INF/services/java.xml.ws.spi. Provider o com.sun.xml.internal.ws.spi.ProviderImpl (para el caso JAX-WS) y crea una instancia de eso.

Lo que no puedo encontrar es cómo/dónde/en qué etapa el JRE llama a ese método FactoryFinder.find().

¿Alguien me puede aclarar?

[editar] He encontrado la respuesta, pero no se me permite publicar yo mismo durante otras 3 horas ...

Respuesta

3

Puede cambiar el comportamiento predeterminado utilizando la propiedad del sistema javax.xml.bind.context.factory. Su valor debe ser el nombre de clase completamente calificado de la fábrica.

El valor predeterminado de esta propiedad es com.sun.xml.internal.bind.v2.ContextFactory. Esta fábrica no está obligada a implementar ninguna interfaz específica ya que debe implementar el método createContext(String, ClassLoader, Map)

+0

Pero, ¿eso significa que el La lógica detrás de estos métodos de fábrica está básicamente codificada en la versión específica de JRE. Por ejemplo, JRE 6 ** sabe ** específicamente sobre JAX-WS/JSR224 (?) Y tiene algún gancho "onStartup" dentro que explícitamente llama a FactoryFinder.find() para aquellos estándares que conoce. –

+0

Por lo que yo entiendo, "sabe" una implementación predeterminada. Pero uno puede anularlo implementando su propia ContextFactory y configurándola usando la propiedad del sistema mencionada. – AlexR

2

Existen algunos mecanismos que controlan qué implementación utiliza. cada jre/jdk tiene una implementación "predeterminada" integrada codificada en el código de inicio. También hay algunas propiedades del sistema que puede usar para especificar una implementación específica (como se menciona @AlexR). sin embargo, ese no es el mecanismo estándar para especificar una implementación diferente. la mayoría de las implementaciones alternativas incluyen un archivo especial en su directorio META-INF (dentro del contenedor) que indica a jre/jdk que se deben usar en lugar de la implementación predeterminada (esto funciona sin establecer ninguna propiedad del sistema, simplemente se dejan caer los archivos el classpath). estos archivos especiales se encuentran en la utilidad ServiceLoader y permiten que la implementación alternativa se cargue automáticamente.

5

Resolvió la lógica completa. En realidad, no ocurre nada en el arranque de JVM. Todo se basa en la carga diferida, por ejemplo, el JAX-WS real/cualquier proveedor solo se carga/instancia la primera vez que se necesita.

En el caso de la carga de la aplicación JAX-WS:

Supongamos que queremos llamada un servicio web, utilizando código como:

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

port.mymethod(); 

ocurre lo siguiente para inicializar el JAX- aplicación WS:

  • Cualquier servicio web JAX-WS se extiende javax.xml.ws.Service, por lo que se extiende MyService_Service Servicio
  • Cuando crea una instancia de su servicio web, su superclase (javax.xml.ws.Service) también se inicializa (constructor)
  • El constructor para las llamadas de "servicio" javax.xml.ws.spi.Provider.provider(), que es un método estático que usa javax.xml.ws.spi.FactoryFinder.find() para encontrar y crear instancias de la implementación tal como está configurada.

Supongamos que queremos publicar un servicio web utilizando un código como:

@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(); 

ocurre lo siguiente para inicializar la aplicación JAX-WS:

  • Endpoint.create() ejecuta Provider.provider(). createEndpoint()
  • Provider.provider() es un método estático que utiliza javax.xml.ws.spi.FactoryFinder.find() para buscar un y crear una instancia de la implementación tal como está configurada.

Los siguientes enlaces ayudaron a entender esto:

1

Descubrí que un ejemplo de JAXB que funcionaba falla después de colocar un weblogicfullclient.jar en classpath, porque el contenedor contiene un META-INF/services/javax.xml.bind.JAXBContext pero no la implementación. Desafortunadamente, uno no puede decirle a JAXB que "solo use PLATFORM_DEFAULT_FACTORY_CLASS", tiene que ponerlo en una propiedad del sistema (-Djavax.xml.bind.JAXBContext = com.sun.xml.internal.bind.v2.ContextFactory para 1.6 y - Djavax.xml.bind.context.factory = .. para 1.7), las implementaciones javax.xml.bind.ContextFinder.find (String, String, ClassLoader, Map) difieren para 1.6 y 1.7

Cuestiones relacionadas