2011-07-12 28 views
12

Al haber creado un cliente del servicio web java usando wsimport en un wsdl, necesito configurar el encabezado Authorization para cada mensaje soap incrustado en una solicitud http. Habiendo generado una subclase de javax.xml.ws.Service, ¿cómo puedo agregar un encabezado http a cada solicitud saliente?cliente del servicio web java, agregando encabezados http

+0

[Esta entrada del blog] (http: // vangjee. wordpress.com/2009/02/25/how-to-modify-request-headers-in-a-j2ee-web-application/) muestra cómo modificar HttpRequestHeaders. Supone que estás escribiendo una aplicación J2EE. – Davidann

Respuesta

9

Puede pasar un mapa con encabezados personalizados a BindingProvider (creo que puede establecer la propiedad MessageContext.HTTP_REQUEST_HEADERS). Intente crear un encabezado de Autorización y pasarlo.

12

Aquí está el código, basado en la respuesta de Femi.

Puede ser un poco difícil de entender. Funciona muy bien!

Service jaxwsService = Service.create(wsdlURL, serviceName); 
Dispatch<SOAPMessage> disp = jaxwsService.createDispatch(portName, SOAPMessage.class, Service.Mode.MESSAGE); 

//Add HTTP request Headers 
Map<String, List<String>> requestHeaders = new HashMap<>(); 
requestHeaders.put("Auth-User", Arrays.asList("BILL_GATES")); 
disp.getRequestContext().put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders); 
+0

Tengo problemas con la llamada createDispatch: Despacho disp = jaxwsService.createDispatch (portName, SOAPMessage.class, Service.Mode.MENSAJE); Se queja de que no se ha encontrado un método adecuado. ¿Hay algo obvio que me he perdido? Importación de import javax.xml.soap.SOAPMessage; import javax.xml.ws.Dispatch; import javax.xml.ws.Service; import javax.xml.ws.handler.MessageContext; –

+0

¡Gracias! Si eres tan tonto como yo, podrías intentar usar un 'Map ' porque lees la respuesta demasiado rápido. No seas como yo Use un 'Map >' y guarde las cuatro horas que pasé tratando de depurar el 'error de transporte HTTP: java.lang.ClassCastException: java.lang.String no se puede convertir a java.util.List'. – L42

3

En aras de la exhaustividad y para ayudar a otros en situaciones similares, me gustaría ilustrar la solución más limpia en mi humilde opinión utilizando el manejador-WS-JAX-cadena:

1) Sub-clase de su service-class (no la clase port) en un paquete diferente (no generado). Debido a que es probable que la clase de servicio (y todo su paquete) se haya generado a partir de un WSDL, sus cambios en la subclase no se pierden cuando actualiza su clase de servicio después de un cambio WSDL.

2) Anotar su servicio-sub-clase como esta (importación javax.jws.HandlerChain):

@HandlerChain(file="HandlerChain.xml") 
public class MyService extends GeneratedService { 

3) Crear un archivo llamado HandlerChain.xml en el mismo paquete que el servicio de sub-clase, es decir, junto a MyService con el siguiente contenido:

<?xml version="1.0" encoding="UTF-8"?> 
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee"> 
    <handler-chain> 
     <handler> 
      <handler-name>co.codewizards.example.HttpHeaderExtensionSOAPHandler</handler-name> 
      <handler-class>co.codewizards.example.HttpHeaderExtensionSOAPHandler</handler-class> 
     </handler> 
    </handler-chain> 
</handler-chains> 

Usted puede agregar varios elementos <handler>, por cierto.

¡Y asegúrese de que este archivo realmente termine en su JAR! Por ejemplo, cuando usa Maven, debe colocarlo en ${project}/src/main/resources/ (en lugar de ${project}/src/main/java/) o tiene que cambiar su configuración de compilación para incluir recursos de la carpeta java. Recomiendo este último, porque es engorroso tener una estructura de paquete paralela en la carpeta resources, que a menudo se olvida durante las refactorizaciones.

4) Poner en práctica su HttpHeaderExtensionSOAPHandler - similar a esto:

import static com.google.common.base.Preconditions.*; 

import java.util.*; 

import javax.xml.namespace.QName; 
import javax.xml.ws.handler.MessageContext; 
import javax.xml.ws.handler.soap.SOAPHandler; 
import javax.xml.ws.handler.soap.SOAPMessageContext; 

import co.codewizards.webservice.WebserviceContext; 

public class HttpHeaderExtensionSOAPHandler implements SOAPHandler<SOAPMessageContext> { 

    @Override 
    public boolean handleMessage(SOAPMessageContext context) { 
     checkNotNull(context, "context"); 

     Boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); 
     checkNotNull(outboundProperty, "outboundProperty"); 

     if (outboundProperty.booleanValue()) { 
      WebserviceContext<?, ?> webserviceContext = WebserviceContext.getThreadWebserviceContextOrFail(); 
      String something = (String) webserviceContext.___(); // my API method ;-) 

      @SuppressWarnings("unchecked") 
      Map<String, List<String>> requestHeaders = (Map<String, List<String>>) context.get(MessageContext.HTTP_REQUEST_HEADERS); 
      if (requestHeaders == null) { 
       requestHeaders = new HashMap<String, List<String>>(); 
       context.put(MessageContext.HTTP_REQUEST_HEADERS, requestHeaders); 
      } 
      requestHeaders.put(MyService.MY_CONSTANT, Collections.singletonList(something)); 
     } 
     return true; 
    } 

    @Override 
    public boolean handleFault(SOAPMessageContext context) { return true; } 

    @Override 
    public void close(MessageContext context) { } 

    @Override 
    public Set<QName> getHeaders() { return Collections.emptySet(); } 
} 

En mi ejemplo anterior (y en mi código productivo) I obtener los datos para ser introducidos en las cabeceras de petición HTTP de una ThreadLocale, es decir, el contexto de mi hilo actual. Dado que este WebserviceContext es mi clase personalizada, deberá implementar su propia forma de acceder a sus datos.

1

cuando se está enviando en el modo de mensaje, también puede pasar en MimeHeaders mensaje SOAP, lo que eventualmente se traducirán en las cabeceras HTTP, es decir:

soapMessage.getMimeHeaders().addHeader("Authorization","Basic [md5]") 
Cuestiones relacionadas