WebService avec Apache CXF et en-têtes personnalisés
Question
J'ai créé un service Web en utilisant Apache cfx et en ressort, et fonctionne, mais j'ai besoin que la réponse inclure cet en-tête
<?xml version="1.0" encoding="UTF-8"?>
À l'heure actuelle, la réponse est la suivante.
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:postEncuestaResponse xmlns:ns2="http://webservice.atomsfat.com/">
<respuestaEncuesta>
<dn>12315643154</dn>
<encuestaPosted>true</encuestaPosted>
<fecha>2009-09-30T16:32:33.163-05:00</fecha>
</respuestaEncuesta>
</ns2:postEncuestaResponse>
</soap:Body>
</soap:Envelope>
Mais devrait être comme ça
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:postEncuestaResponse xmlns:ns2="http://webservice.atomsfat.com/">
<respuestaEncuesta>
<dn>12315643154</dn>
<encuestaPosted>true</encuestaPosted>
<fecha>2009-09-30T16:32:33.163-05:00</fecha>
</respuestaEncuesta>
</ns2:postEncuestaResponse>
</soap:Body>
</soap:Envelope>
C'est la configuration des grains de printemps qui expose le service.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint
id="encuestas"
implementor="webservice.serviceImpl"
address="/Encuestas" >
</jaxws:endpoint>
</beans>
c'est l'interface
import java.util.List;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
@WebService
public interface Encuestas {
@WebResult(name= "respuestaEncuesta")
RespuestaEncuestaMsg postEncuesta
(@WebParam(name = "encuestaMsg") EncuestaMsg message);
}
Des idées?
La solution 3
J'ai implémenté un gestionnaire, tout d'abord j'ai téléchargé les exemples à partir de CXF et modifié le gestionnaire de journalisation, et cela fonctionne.
La configuration du ressort:
http://www.springframework.org/schema/beans http: // www .springframework.org / schema / beans / spring-beans.xsd http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd " >
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<jaxws:endpoint
id="encuestas"
implementor="com.webservice.EncuestasImpl"
address="/Encuestas">
<jaxws:handlers>
<bean class="com.webservice.HeaderHandler"/>
</jaxws:handlers>
</jaxws:endpoint>
Et le code c'est le code du gestionnaire.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.webservice;
import java.io.PrintStream;
import java.util.Map;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/*
* This simple logical Handler will output the payload of incoming
* and outgoing messages.
*/
public class HeaderHandler implements SOAPHandler<SOAPMessageContext> {
private PrintStream out;
public HeaderHandler() {
setLogStream(System.out);
}
protected final void setLogStream(PrintStream ps) {
out = ps;
}
public void init(Map c) {
System.out.println("LoggingHandler : init() Called....");
}
public Set<QName> getHeaders() {
return null;
}
public boolean handleMessage(SOAPMessageContext smc) {
System.out.println("LoggingHandler : handleMessage Called....");
logToSystemOut(smc);
return true;
}
public boolean handleFault(SOAPMessageContext smc) {
System.out.println("LoggingHandler : handleFault Called....");
logToSystemOut(smc);
return true;
}
// nothing to clean up
public void close(MessageContext messageContext) {
System.out.println("LoggingHandler : close() Called....");
}
// nothing to clean up
public void destroy() {
System.out.println("LoggingHandler : destroy() Called....");
}
/*
* Check the MESSAGE_OUTBOUND_PROPERTY in the context
* to see if this is an outgoing or incoming message.
* Write a brief message to the print stream and
* output the message. The writeTo() method can throw
* SOAPException or IOException
*/
protected void logToSystemOut(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean)
smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (outboundProperty.booleanValue()) {
out.println("\nOutbound message:");
} else {
out.println("\nInbound message:");
}
SOAPMessage message = smc.getMessage();
try {
message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
message.writeTo(out);
out.println();
} catch (Exception e) {
out.println("Exception in handler: " + e);
}
}
}
Remarque: dans l'essai, j'utilise MessageContext.MESSAGE_OUTBOUND_PROPERTY
comme suggéré par Justin.
Autres conseils
Ou utilisez les fonctionnalités de configuration intégrées de CXF. Ajoutez simplement ceci dans votre configuration CXF Spring:
<jaxws:properties>
<entry key="org.apache.cxf.stax.force-start-document">
<bean class="java.lang.Boolean">
<constructor-arg value="true"/>
</bean>
</entry>
</jaxws:properties>
Vérifiez les éléments suivants
Comment puis-je ajouter des en-têtes de soap à la demande / réponse?
Ajout de gestionnaires JAX-WS aux services Web
Conversion des gestionnaires JAX-WS en intercepteurs Apache CXF
puis choisissez l'une des options et implémentez un gestionnaire / intercepteur qui ajoute ce dont vous avez besoin.
En suivant les liens fournis par la gigue, je suis allé sur http: // cxf.apache.org/faq.html#FAQ-HowcanIaddsoapheaderstotherequest%252Fresponse%253F et a trouvé la solution suivante:
// My object of the custom header
AuthenticationHeader aut = new AuthenticationHeader();
aut.setUserName("ws");
aut.setPassword("ws123");
IntegrationWS integration = new IntegrationWS();
List<Header> headers = new ArrayList<Header>();
Header dummyHeader;
try {
dummyHeader = new Header(new QName("http://www.company.com/ws/", "AuthenticationHeader"), auth, new JAXBDataBinding(AuthenticationHeader.class));
} catch (JAXBException e) {
throw new IllegalStateException(e);
}
headers.add(dummyHeader);
IntegrationWSSoap soapPort = integration.getIntegrationWSSoap12();
//client side:
((BindingProvider)soapPort).getRequestContext().put(Header.HEADER_LIST, headers);
ArrayOfBrand arrayBrand = soapPort.syncBrands();
Je n'ai pas de connaissances spécifiques à Apache CXF, mais la méthode jax-ws pour ajouter la déclaration xml semble être de créer un gestionnaire et d'utiliser SOAPMessage.setProperty () pour activer cette fonctionnalité sur:
message.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
Vous devriez pouvoir ajouter un gestionnaire jax-ws à votre noeud final en ajoutant un élément jaxws: handlers dans cette configuration de printemps.