Seguramente te habrás encontrado la duplicidad de targetnamepsace:
- S="http://schemas.xmlsoap.org/soap/envelope/"
- SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/".
El posible origen del problema es que estas usando JAX-WS para generar el servicio web (bajo JAX-B) y posteriormente usas SoapHandler (bajo SAAJ) para manipular el mensaje SOAP.
¿Cómo lo sé? La respuesta es que el targetnamepsace S lo genera JAXB y el targetnamepsace SOAP-ENV lo genera SAAJ.
Al usar el SOAPHandler posiblemente estés obteniendo el mensaje de esta forma:
-
SOAPMessage msg = SOAPMessageContext.getMessage();
Al obtener el mensaje usando SOAPMessageContext.getMessage() automaticamente SAAJ intenta crear una cabecera por lo que agrega un header vacío. y en su defecto declara el nuevo targetnamespace SOAP-ENV.
Para resolver el problema, diseñe una clase Helper que te facilitará el trabajo de agregar en JAX-WS la cabecera sin manipular el mensaje. Además verás otras utilidades interesantes que se pueden incluir en el helper.
clase JAXWSHelper
package com.hek.ws.handler;
import java.util.Map;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.ws.BindingProvider;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.inetpsa.ped.core.PEDTechnicalException;
import com.sun.xml.ws.api.message.Header;
import com.sun.xml.ws.developer.WSBindingProvider;
import com.sun.xml.ws.message.DOMHeader;
/**
* Helper class only to use with JAX-WS and useful to obtain a reference to the binding provider and to append different WebServices operations:
* <p>
* <ul>
* <li>basic authentication</li>
* <li>security headers on paylaod</li>
* <li>add published url service</li>
* <li>among others</li>
* </ul>
* </p>
* You can downcast to WSBindingProvider which defines a few more methods provided only by the JAX-WS RI.
* <p />
* If you dont use JAX-WS, not use this helper class. You can use javax.xml.ws.handler.soap.SoapHandler to adding security headers
*
* @author E460165
* @param <S> the BindingProvider generic type
*/
public class JAXWSHelper<S extends BindingProvider> {
/** The Constant WS_SECEXT. */
public final static String WS_SECEXT = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
/** The Constant WS_USER_TOKEN_PROFILE. */
public final static String WS_USER_TOKEN_PROFILE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText";
/** The provider. */
private S provider;
/**
* Instantiates a new wss ws security helper.
*
* @param provider the provider
* @param username the username
* @param password the password
*/
public JAXWSHelper(S provider) {
this.provider = provider;
}
/**
* Adds the http basic authorization.
*/
public void addHttpBasicAuthorization(String username, String password) {
Map<String, Object> requestContext = provider.getRequestContext();
requestContext.put(BindingProvider.USERNAME_PROPERTY, username);
requestContext.put(BindingProvider.PASSWORD_PROPERTY, password);
}
/**
* Adds the wsse security relates to header and asigned username and password.
*/
public void addWsseSecurityHeader(String username, String password) {
try {
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Element root = document.createElementNS(WS_SECEXT, "wsse:Security");
document.appendChild(root);
Element usernameTokenEl = document.createElementNS(WS_SECEXT, "wsse:UsernameToken");
root.appendChild(usernameTokenEl);
Element usernameEl = document.createElementNS(WS_SECEXT, "wsse:Username");
usernameTokenEl.appendChild(usernameEl);
usernameEl.setTextContent(username);
Element passwordEl = document.createElementNS(WS_SECEXT, "wsse:Password");
usernameTokenEl.appendChild(passwordEl);
passwordEl.setTextContent(password);
passwordEl.setAttribute("Type", WS_USER_TOKEN_PROFILE);
Header securityHeader = new DOMHeader<Element>(document.getDocumentElement());
if (provider instanceof WSBindingProvider) {
((WSBindingProvider) provider).setOutboundHeaders(securityHeader);
}
} catch (ParserConfigurationException e) {
throw new PEDTechnicalException("Error adding ws-security header to the webservice", e);
}
}
/**
* Adds the http endpoint.
*
* @param url the url
*/
public void addHttpEndpoint(String url) {
Map<String, Object> requestContext = provider.getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, url);
}
}
Ejemplo de como utilizar la clase JAXWSHelper
/** The url service bps. */
private String URL_SERVICE_BPS;
/** The wsdl resource. */
private String WSDL_RESOURCE;
/** The username. */
private String USERNAME;
/** The password. */
private String PASSWORD;
private AccesBPSPortType createClientBps() {
URL wsdlURL = this.getClass().getClassLoader().getResource(WSDL_RESOURCE);
// call webservice
WebServiceClient webServiceClient = AccesBPS.class.getAnnotation(WebServiceClient.class);
AccesBPS accesBps = new AccesBPS(wsdlURL, new QName(webServiceClient.targetNamespace(), webServiceClient.name()));
AccesBPSPortType client = accesBps.getPort(AccesBPSPortType.class);
JAXWSHelper jaxWSHelper = new JAXWSHelper(((BindingProvider) client));
// adding http basic authorization
jaxWSHelper.addHttpBasicAuthorization(USERNAME, PASSWORD);
// adding wsse security headers
jaxWSHelper.addWsseSecurityHeader(USERNAME, PASSWORD);
// adding httpEndpoint
jaxWSHelper.addHttpEndpoint(URL_SERVICE_BPS);
return client;
}
Saludos me parece u muy buen articulo, estoy en una situación similar,,, no se tal vez me podrías hechar una mano,, no se como contactarte me ayudarías muchísimo mi correo electrónico es jhonnyjgc@yahoo.com saludos espero respondas mi comentario
ResponderEliminar