2015-05-08 13 views
7

Sto sviluppando un servizio Web Java. In questo momento posso ottenere richieste di intestazione Http. Ma voglio aggiungere altre richieste di intestazione.Aggiungere le intestazioni HTTP alla risposta del servizio JAX-WS

Attualmente sto facendo questo in un filtro servlet.

@WebFilter(urlPatterns = {"/*"}) 
public class AddHeader implements Filter { 

    @Resource 
    private WebServiceContext context; 

    public AddHeader() { 
    } 

    @Override 
    public void init(FilterConfig fConfig) throws ServletException { 
    } 

    @Override 
    public void destroy() { 
    } 

    @Override 
    public void doFilter(
      ServletRequest request, ServletResponse response, 
      FilterChain chain) throws IOException, ServletException { 
     if (request.getContentLength() != -1 && context != null) { 
      MessageContext mc = context.getMessageContext(); 
      ((HttpServletResponse) response).addHeader(
        "Operation", "something" 
      ); 
     } 

     chain.doFilter(request, response); 
    } 
} 

Il problema con questa strategia è che l'intestazione aggiunta è statica.

Con classe SOAPHandler posso ottenere un messaggio SOAP - dinamica:

public class SoapClass implements SOAPHandler<SOAPMessageContext> { 


    @Override 
    public boolean handleMessage(SOAPMessageContext messageContext) { 
     log(messageContext); 
     return true; 
    } 

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

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

    @Override 
    public void close(MessageContext context) { 
    } 


    public static String getMsgAsString(SOAPMessage message) { 
     String msg = null; 
     try { 
      ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
      message.writeTo(baos); 
      msg = baos.toString(); 
     } catch (SOAPException | IOException soape) { 
     } 
     return msg; 
    } 


    private String soapToString(SOAPMessage message, boolean indent) { 
     final StringWriter sw = new StringWriter(); 

     try { 
      TransformerFactory.newInstance().newTransformer().transform(
        new DOMSource(message.getSOAPPart()), 
        new StreamResult(sw)); 
     } catch (TransformerException e) { 
      throw new RuntimeException(e); 
     } 

     return (indent ? sw.toString() : sw.toString().replaceAll("[\\r\\n]", "")); 
    } 

Quindi, quello che volevo era quello di unire messaggio SOAP dinamica con filtro. Come posso raggiungere questo obiettivo?

+0

Cosa si intende per "l'intestazione è statico"? Che cos'è un'intestazione statica rispetto a un'intestazione dinamica? – kolossus

+0

"Operazione", "qualcosa" è un valore statico che ho definito. Voglio avere diversi contenuti di sapone per ogni richiesta – Goldbones

+0

Non riesco ancora a capirlo: cos'è un "valore statico" rispetto a un "contenuto di sapone"? Stai cercando di impostare un'intestazione HTTP in base a una condizione? O stai cercando di impostare un'intestazione SOAP? * Voglio essere in grado di trovare diversi contenuti di sapone per ogni richiesta * in realtà non si traduce molto bene. Puoi pubblicare un'illustrazione o qualcosa del genere? – kolossus

risposta

6

Mentre non sono ancora del tutto chiaro su ciò che si desidera realmente, descriverò come aggiungere intestazioni HTTP in una risposta del servizio Web SOAP. Il posto più pulito per farlo è in un gestore JAX-WS, non diversamente da quello che hai già nel formato SoapClass.

Per fare ciò nel vostro SOAPHandler, è necessario prima ottenere l'accesso all'elenco delle intestazioni nel sottostante HttpServletResponse. Questo elenco è fornito dal SOAPMessageContext:

@Override 
    public boolean handleMessage(SOAPMessageContext context) { 
     //This property checks whether the handler is being invoked for a service response 
     boolean response= ((Boolean) context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue(); 

     if (response) { 
      //this is a JAX-WS-provided map of HTTP headers 
      Map<String, List<String>> headers = (Map<String, List<String>>) context.get(MessageContext.HTTP_RESPONSE_HEADERS); 
      if (null == headers) { 
       //create a new map of HTTP headers if there isn't already one 
       headers = new HashMap<String, List<String>>(); 
      } 
      //add your desired header 
      headers.put("Operation",Collections.singletonList("something"); 
     } 
     return true; 
    } 

Un approccio alternativo è quello di accedere al HttpServletResponse che sta alla base della risposta del servizio web:

 @Override 
    public boolean handleMessage(SOAPMessageContext context) { 
     //This property checks whether the handler is being invoked for a service response 
     boolean response= ((Boolean) context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue(); 

     if (response) { 
      //this is underlying http response object 
      HttpServletResponse response = (HttpServletResponse) context.get(MessageContext.SERVLET_RESPONSE); 

      //add your desired header 
      response.addHeader("Operation", "something"); 
      } 
     return true; 
    } 
+0

Ho provato questo approccio prima. Ricevo un'eccezione: request.headers è una proprietà di sola lettura. – Goldbones

+0

Il mio errore @Goldbones; dovrebbe essere 'HTTP_RESPONSE_HEADERS' non' HTTP_REQUEST_HEADERS'. Ho pubblicato anche un approccio alternativo. L'approccio che hai già provato dovrebbe essere sempre parte della tua domanda: salva tutto il tempo e fa una domanda migliore. – kolossus

+0

Perfetto! Questo esattamente quello che volevo. L'ho fatto in un altro post, ma nessuno ha potuto dare una risposta appropriata. Nel codice che fornisci, invece del contenuto statico ("qualcosa" sarà sempre la stessa risposta in richieste diverse) Ho un contenuto dinamico (per contesto Soap Message), che è ottimo perché ora ho messaggi diversi per richieste diverse. Grazie! – Goldbones

Problemi correlati