I'm trying consume a webservice that uses two namespaces in soap request, but it doesn't accept any prefix. I'm using cxf to generate the client and the data-binding. When using JAXB as default data-binding this is the message sent to the web service's server:
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<nfeCabecMsg xmlns:ns2="http://www.portalfiscal.inf.br/nfe"
xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2">
<cUF>31</cUF>
<versaoDados>2.00</versaoDados>
</nfeCabecMsg>
</soap:Header>
<soap:Body>
<nfeDadosMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2"
xmlns:ns2="http://www.portalfiscal.inf.br/nfe">
<ns2:consStatServ versao="2.00">
<ns2:tpAmb>2</ns2:tpAmb>
<ns2:cUF>31</ns2:cUF>
<ns2:xServ>STATUS</ns2:xServ>
</ns2:consStatServ>
</nfeDadosMsg>
</soap:Body>
</soap:Envelope>
But this isn't the format that the server expects. Using XmlBean as default data-binding I can generate correctly the message (as the server expects):
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Header>
<nfeCabecMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2">
<cUF>31</cUF>
<versaoDados>2.00</versaoDados>
</nfeCabecMsg>
</soap:Header>
<soap:Body>
<nfeDadosMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2">
<consStatServ xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.00">
<tpAmb>2</tpAmb>
<cUF>31</cUF>
<xServ>STATUS</xServ>
</consStatServ>
</nfeDadosMsg>
</soap:Body>
</soap:Envelope>
However, I'm really affraid about using XmlBeans, as another important part of my software was developed using JAXB, I probably will need change this to XmlBeans. After I've saw that the last release of XmlBeans was in 2012 I'm not confident that XmlBeans will be supported in future. Is there a way I can generate the message correctly using JAXB??
UPDATE
This is the wsdl of the web service:
<?xml version="1.0" encoding="utf-8"?>
<wsdl:definitions xmlns:s="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
xmlns:tns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2"
xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
targetNamespace="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<s:schema elementFormDefault="qualified"
targetNamespace="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2">
<s:element name="nfeDadosMsg">
<s:complexType mixed="true">
<s:sequence>
<s:any/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="nfeStatusServicoNF2Result">
<s:complexType mixed="true">
<s:sequence>
<s:any/>
</s:sequence>
</s:complexType>
</s:element>
<s:element name="nfeCabecMsg" type="tns:nfeCabecMsg"/>
<s:complexType name="nfeCabecMsg">
<s:sequence>
<s:element minOccurs="0" maxOccurs="1" name="cUF" type="s:string"/>
<s:element minOccurs="0" maxOccurs="1" name="versaoDados" type="s:string"/>
</s:sequence>
<s:anyAttribute/>
</s:complexType>
</s:schema>
</wsdl:types>
<wsdl:message name="nfeStatusServicoNF2Soap12In">
<wsdl:part name="nfeDadosMsg" element="tns:nfeDadosMsg"/>
</wsdl:message>
<wsdl:message name="nfeStatusServicoNF2Soap12Out">
<wsdl:part name="nfeStatusServicoNF2Result" element="tns:nfeStatusServicoNF2Result"/>
</wsdl:message>
<wsdl:message name="nfeStatusServicoNF2nfeCabecMsg">
<wsdl:part name="nfeCabecMsg" element="tns:nfeCabecMsg"/>
</wsdl:message>
<wsdl:portType name="NfeStatusServico2Soap12">
<wsdl:operation name="nfeStatusServicoNF2">
<wsdl:input message="tns:nfeStatusServicoNF2Soap12In"/>
<wsdl:output message="tns:nfeStatusServicoNF2Soap12Out"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="NfeStatusServico2Soap12" type="tns:NfeStatusServico2Soap12">
<soap12:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="nfeStatusServicoNF2">
<soap12:operation soapAction="http://www.portalfiscal.inf.br/nfe/wsdl/NfeStatusServico2/nfeStatusServicoNF2"
style="document"/>
<wsdl:input>
<soap12:body use="literal"/>
<soap12:header message="tns:nfeStatusServicoNF2nfeCabecMsg" part="nfeCabecMsg" use="literal"/>
</wsdl:input>
<wsdl:output>
<soap12:body use="literal"/>
<soap12:header message="tns:nfeStatusServicoNF2nfeCabecMsg" part="nfeCabecMsg" use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="NfeStatusServico2">
<wsdl:port name="NfeStatusServico2Soap12" binding="tns:NfeStatusServico2Soap12">
<soap12:address location="https://nfe.sefazvirtual.rs.gov.br/ws/NfeStatusServico/NfeStatusServico2.asmx"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
these are the most relevant schemas that are used to create consStatServ tag:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="http://www.portalfiscal.inf.br/nfe" xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.portalfiscal.inf.br/nfe" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:include schemaLocation="leiauteConsStatServ_v2.00.xsd"/>
<xs:element name="consStatServ" type="TConsStatServ">
<xs:annotation>
<xs:documentation>Schema XML de validação do Pedido de Consulta do Status do Serviço</xs:documentation>
</xs:annotation>
</xs:element>
</xs:schema>
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns="http://www.portalfiscal.inf.br/nfe" xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.portalfiscal.inf.br/nfe" elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:include schemaLocation="tiposBasico_v1.03.xsd"/>
<xs:complexType name="TConsStatServ">
<xs:annotation>
<xs:documentation>Tipo Pedido de Consulta do Status do Serviço</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="tpAmb" type="TAmb">
<xs:annotation>
<xs:documentation>Identificação do Ambiente:
1 - Produção
2 - Homologação
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="cUF" type="TCodUfIBGE">
<xs:annotation>
<xs:documentation>Sigla da UF consultada</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="xServ">
<xs:annotation>
<xs:documentation>Serviço Solicitado</xs:documentation>
</xs:annotation>
<xs:simpleType>
<xs:restriction base="TServ">
<xs:enumeration value="STATUS"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
<xs:attribute name="versao" type="TVerConsStatServ" use="required"/>
</xs:complexType>
<xs:complexType name="TRetConsStatServ">
<xs:annotation>
<xs:documentation>Tipo Resultado da Consulta do Status do Serviço</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="tpAmb" type="TAmb">
<xs:annotation>
<xs:documentation>Identificação do Ambiente:
1 - Produção
2 - Homologação
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="verAplic" type="TVerAplic">
<xs:annotation>
<xs:documentation>Versão do Aplicativo que processou a NF-e</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="cStat" type="TStat">
<xs:annotation>
<xs:documentation>Código do status da mensagem enviada.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="xMotivo" type="TMotivo">
<xs:annotation>
<xs:documentation>Descrição literal do status do serviço solicitado.</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="cUF" type="TCodUfIBGE">
<xs:annotation>
<xs:documentation>Código da UF responsável pelo serviço</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="dhRecbto" type="xs:dateTime">
<xs:annotation>
<xs:documentation>AAAA-MM-DDTHH:MM:SS</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="tMed" type="TMed" minOccurs="0">
<xs:annotation>
<xs:documentation>Tempo médio de resposta do serviço (em segundos) dos últimos 5 minutos
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="dhRetorno" type="xs:dateTime" minOccurs="0">
<xs:annotation>
<xs:documentation>AAAA-MM-DDTHH:MM:SSDeve ser preenchida com data e hora previstas para o retorno
dos serviços prestados.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="xObs" type="TMotivo" minOccurs="0">
<xs:annotation>
<xs:documentation>Campo observação utilizado para incluir informações ao contribuinte
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:attribute name="versao" type="TVerConsStatServ" use="required"/>
</xs:complexType>
<xs:simpleType name="TVerConsStatServ">
<xs:annotation>
<xs:documentation>Tipo versão do leiuate da Consulta Status do Serviço 2.00</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:token">
<xs:pattern value="2\.00"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
I finally solved the problem. As this is a 3rd party web service, the only choice I had was edit the classes generated by JAXB. The first thing I've done was remove the namespace attribute from package-info.java file. Then I did the same in ObjectFactory class, here I just changed the QName constructor from:
QName(String namespaceURI, String localPart)
to
QName(String localPart)
Unfortunately these modifications didn't removed the prefix, so I've implemented my own CXF interceptor:
public class NamespacePrefixInterceptor extends AbstractPhaseInterceptor<Message> {
public NamespacePrefixInterceptor() {
super(Phase.PRE_STREAM);
addBefore(SoapPreProtocolOutInterceptor.class.getName());
}
@Override
public void handleMessage(Message message) throws Fault {
if (isOutbound(message)) {
OutputStream outputStream = message.getContent(OutputStream.class);
CachedOutputStream cachedOutputStream = new CachedOutputStream();
message.setContent(OutputStream.class, cachedOutputStream);
message.getInterceptorChain().doIntercept(message);
try {
cachedOutputStream.flush();
CachedOutputStream messageStream = (CachedOutputStream) message.getContent(OutputStream.class);
String currentEnvelopeMessage = IOUtils.toString(messageStream.getInputStream(), "UTF-8");
currentEnvelopeMessage = currentEnvelopeMessage.replaceAll("ns2:", "");
currentEnvelopeMessage = currentEnvelopeMessage.replaceAll(":ns2", "");
messageStream.flush();
messageStream.close();
InputStream replaceInStream = new ByteArrayInputStream(currentEnvelopeMessage.getBytes(StandardCharsets.UTF_8));
IOUtils.copy(replaceInStream, outputStream);
replaceInStream.close();
outputStream.flush();
message.setContent(OutputStream.class, outputStream);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
private boolean isOutbound(Message message){
return message == message.getExchange().getOutMessage()
|| message == message.getExchange().getOutFaultMessage();
}
}
With this interceptor I could finally remove the namespaces. The last problem was the namespace xmlns="http://www.portalfiscal.inf.br/nfe" should appear in consStatServ element. As all unecessary namespaces was removed after the modifications in JAXB generated classes, the workaround I did was simply create a xmln attribute in ConsStatServ class:
public class ConsStatServ {
.
.
.
@XmlAttribute(name = "xmlns", required = true)
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
protected String xmlns = "http://www.portalfiscal.inf.br/nfe";
public String getXmlns() {
return xmlns;
}
}
I know this solution is a huge kludge, but I couldn't find another option.