Etnão como o AGAraujo comentou… vou postar aqui um código feito por ele,
que corrige o problema de namespace que muitos estão tendo com o WS, acho que principalmento com o PR.
1 - Criar um novo projeto
2- Criar uma interface SefazServiceConfig
[code]package br.com.mysoft.mynfe.ws.application;
public interface SefazServiceConfig {
void setProperties();
String getWebServiceURL();
String getDefinitionsTargetNamespaceURI();
String getSchemaTargetNamespaceURI();
String getSoapActionURI();
String getServiceName();
String getPortName();
}[/code]3- Criar uma classe abstrata que implemente a interface acima[code]
package br.com.mysoft.mynfe.ws.application.impl;
/**
-
Classe abstrata responsável por setar as propriedades dos certificados
-
Arquivo: AbstractSefazServiceConfig.java
-
Data : 16/02/2011
-
Hora : 13:34:43
*/
public abstract class AbstractSefazServiceConfig implements SefazServiceConfig
{@SuppressWarnings(“unused”)
private void setPropertiesA3(){
Provider p = new SunPKCS11("{config for SUNPKCS 11 in config.cfg}");
Security.addProvider§;
Properties properties = System.getProperties();
properties.setProperty(“java.protocol.handler.pkgs”, “com.sun.net.ssl.internal.www.protocol”);
properties.setProperty(“javax.net.ssl.keyStoreType”, “PKCS11”);
properties.setProperty(“javax.net.ssl.keyStore”,“NONE”);
properties.setProperty(“javax.net.ssl.keyStoreProvider”, “SunPKCS11-SCR3310”);
properties.setProperty(“javax.net.ssl.keyStorePassword”, “1234”);
properties.setProperty(“javax.net.ssl.trustStoreType”, “JKS”);
properties.setProperty(“javax.net.ssl.trustStore”, “{seu key store path}”);
//
try{
KeyStore ks = KeyStore.getInstance(“PKCS11”);
ks.load(null, “1234”.toCharArray()); //TODO password for keystore
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}private void setPropertiesA1(){
//preparar as propriedades
Properties properties = System.getProperties();
properties.setProperty(“java.protocol.handler.pkgs”, “com.sun.net.ssl.internal.www.protocol”);
properties.setProperty(“javax.net.ssl.keyStoreType”, “PKCS12”);
properties.setProperty(“javax.net.ssl.keyStore”,“cliente.pfx”);//Aqui vem o arquivo do certificado do seu cliente
properties.setProperty(“javax.net.ssl.keyStorePassword”, “123456”);//Aqui a senha deste certificado
properties.setProperty(“javax.net.ssl.trustStoreType”, “JKS”);
properties.setProperty(“javax.net.ssl.trustStore”, “nfe.keystore”);//Aqui vem o arquivo criado através do comando keytool no passo 3
properties.setProperty(“javax.net.ssl.trustStorePassword”, “123456”);
properties.setProperty(“com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump”, “true”);
//properties.setProperty(“javax.net.debug”, “all”); - for debug
}@Override
public final void setProperties() { setPropertiesA1();}
[/code]4- Criar uma classe concreta que herde a classe abstrata AbstractSefazServiceConfig e implemente os métodos da interface SefazServiceConfig [code]
package br.com.mysoft.mynfe.ws.application.impl;
/**
-
Classe concreta que implementa os métodos da interface SefazServiceConfig
-
Os dados de retorno de cada método, pode ser obtido do WSDL de cada WS.
-
Neste caso, estou usando o serviço NfeRecepcao2 (Enviar Lote) do WS do PR
-
Arquivo: SefazServiceReceptionConfig.java
-
Data : 16/02/2011
-
Hora : 13:55:03
*/
public class SefazServiceReceptionConfig extends AbstractSefazServiceConfig {@Override
public String getWebServiceURL() {return “https://homologacao.nfe2.fazenda.pr.gov.br/nfe/NFeRecepcao2”;}@Override
public String getDefinitionsTargetNamespaceURI() {return “http://www.portalfiscal.inf.br/nfe/wsdl/NfeRecepcao2”;}@Override
public String getSchemaTargetNamespaceURI() { return “http://www.portalfiscal.inf.br/nfe/wsdl/NfeRecepcao2”;}@Override
public String getSoapActionURI() {return “http://www.portalfiscal.inf.br/nfe/wsdl/NfeRecepcao2/nfeRecepcaoLote2”;}@Override
public String getServiceName() { return “NfeRecepcao2”;}@Override
public String getPortName() {return “NfeRecepcaoServicePort”;}
}
[/code]5- Agora a classe mais importante, criar a classe que vai consumir o WS[code]
package br.com.mysoft.mynfe.ws.application;
/**
-
Classe responsável por criar um Message e consumir o Web Service.
-
Arquivo: SefazService.java
-
Data : 16/02/2011
-
Hora : 14:01:27
*/
public class SefazService
{
private final String webServiceURL;
private String definitionsTargetNamespaceURI;
private String schemaTargetNamespaceURI;
private String soapActionURI;
private String serviceName;
private String portName;/**
- Construtor que recebe a interface SefazServiceConfig como parametro
-
@param config
*/
public SefazService(SefazServiceConfig config)
{
if (config == null) throw new IllegalArgumentException();
config.setProperties();
webServiceURL = config.getWebServiceURL();
definitionsTargetNamespaceURI = config.getDefinitionsTargetNamespaceURI();
schemaTargetNamespaceURI = config.getSchemaTargetNamespaceURI();
soapActionURI = config.getSoapActionURI();
serviceName = config.getServiceName();
portName = config.getPortName();
}
/**
-
Método que envia o xml para o WS
-
@param xml
-
@return
*/
public OutputStream sendXML(InputStream xml,String uf)throws SOAPException,Exception {
//preparar as propriedades
Provider provider = new Provider();
Security.addProvider(provider);
//Cria um serviço a partir do endereço do WS
Service service = Service.create(new URL(webServiceURL+"?wsdl"),new QName(definitionsTargetNamespaceURI, serviceName));//Cria um Dispatch, que é responsável por invocar o serviço Dispatch<SOAPMessage> dispatch = service.createDispatch(new QName(schemaTargetNamespaceURI, portName),SOAPMessage.class,Service.Mode.MESSAGE); //Configura o RequestContext para a Message solicitada Map<String, Object> rc = dispatch.getRequestContext(); rc.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE); rc.put(BindingProvider.SOAPACTION_URI_PROPERTY, soapActionURI); rc.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, webServiceURL); // Cria um SOAPMessage Request, passando a especificação SOAP 1.2 MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL); SOAPMessage soapMessage = factory.createMessage(); // Optional soapMessage.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "false"); soapMessage.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "utf-8"); // Cria o Header da mensagem SOAPHeader header = soapMessage.getSOAPHeader(); SOAPElement nfeCabecMsg = header.addChildElement("nfeCabecMsg", XMLConstants.DEFAULT_NS_PREFIX, definitionsTargetNamespaceURI); nfeCabecMsg.addChildElement("versaoDados").setValue("2.00"); nfeCabecMsg.addChildElement("cUF").setValue(uf); // Cria o Body SOAPBody body = soapMessage.getSOAPBody(); // Cria um elemento que vai ter os dados do XML SOAPBodyElement nfeDadosMsg = body.addBodyElement(new QName(schemaTargetNamespaceURI, "nfeDadosMsg", XMLConstants.DEFAULT_NS_PREFIX)); // Converte o stream (seu xml) para um Objeto DOM DOMResult domResult = new DOMResult(); XMLReader reader = XMLReaderFactory.createXMLReader(); InputSource inputSource = new InputSource(xml); SAXSource saxSource = new SAXSource(reader, inputSource); TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.transform(saxSource, domResult); //obtém o Document Document document = (Document) domResult.getNode(); //cria um elemento a partir o Document SOAPElement soapElement = SOAPFactory.newInstance().createElement(document.getDocumentElement()); //adiciona no Body nfeDadosMsg.addChildElement(soapElement); //imprime o envelope soapMessage.writeTo(System.out); // invoca o WS e obtém o retorno SOAPMessage reply = dispatch.invoke(soapMessage); // Retorno OutputStream out = new ByteArrayOutputStream(); reply.writeTo(out); return out;
}
}[/code]6- E por fim, a classe de teste. Neste exemplo vou apenas consumir o serviço de enviar lote (NFeRecepcao2)[code]
package br.com.mysoft.mynfe.ws.application;
public class SefazServiceReceptionTest
{
public static void main(String[] args) throws SOAPException, Exception {
//Cria a classe de configuração
SefazServiceConfig config = new SefazServiceReceptionConfig();
//carrega o xml, aqui deve ter apenas o xml, (…)
InputStream xml = new FileInputStream(“test/br/com/mysoft/mynfe/ws/application/000000000025534-env-lot.xml”);
//instância a classe de service
SefazService sefazService = new SefazService(config);
//chama o método para enviar o xml
ByteArrayOutputStream result = (ByteArrayOutputStream) sefazService.sendXML(xml,“41”);
if (result != null)
result.writeTo(System.out);//imprime o retorno da Sefaz
}
}
[/code]
Mas ainda não acabou… agora que vem o pulo do gato…o XALAN.
7- Entrar no site do Xalan e baixar o bendito.
8- Então adicionar no class path, ou seja, importar a lib no seu projeto.
Pois segundo o AGAraujo, há relatos que existe um BUG na versão que vem com o JDK 1.6.
9- Isso ai, agora é só rodar o exemplo e correr pro abraço…
10- Print
envelope que foi mandado
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"><env:Header><nfeCabecMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeRecepcao2">
<versaoDados>2.00</versaoDados><cUF>41</cUF></nfeCabecMsg></env:Header>
<env:Body><nfeDadosMsg xmlns="http://www.portalfiscal.inf.br/nfe/wsdl/NfeRecepcao2">
<enviNFe xmlns="http://www.portalfiscal.inf.br/nfe" versao="2.00">
<idLote>000000000025534</idLote><NFe xmlns="http://www.portalfiscal.inf.br/nfe">...//esta ai o bendito namespace
Foi feito um exemplo apenas de consumir o serviço NfeRecepcao2, mas é a mesma coisa para qualquer outro serviço.
O que você precisa fazer é apenas criar as classes para cada serviço conforme a classe SefazServiceReceptionConfig mostrada acima.