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); JAXWSHelperjaxWSHelper = 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