[RESOLVIDO]Enviar Nota Fiscal para várias empresas (keystore em cache da JVM)

Prezados, bom dia.

preciso da ajuda de vocês, fiz um sistema de envio de nota fiscal em Maker (gerador de código Java), funciona beleza, mas quando tento enviar uma NF diferente(ex: mandei a nf da matriz e tento enviar a nota fiscal para uma filial) da erro na autenticação, isso porque a JVM guarda o último keystore enviado… se eu reiniciar o tomcat eu consigo enviar normalmente. Existe uma forma de contornoar essa situação? alguma função em Java que consiga retirar o keystore guardado em cache sem que eu precise reiniciar o tomcat?
Desde já agradeço pela atenção!

Dê uma olhada no meu blog, eu coloquei uma resolução para este problema : http://alesaudate.com.

[]´s

Colega, Asaudade.

BLz, estou dando uma olhada qualquer dúvida espero poder contar com sua ajuda novamente.
desde já te agradeço pela dica.

para os que estão com o mesmo problema o link é: http://alesaudate.com/2010/08/09/how-to-dynamically-select-a-certificate-alias-when-invoking-web-services/
vou ver se resolvo meu problema e posto o resultado aqui

Asaudate,

Você utilizou Jboss, sabe dizer se isso é válido para o Tomcat? porque é nele que enfreto esse problema.

Basta que você coloque as libs do JAX-WS no diretório de lib´s do Tomcat. (eu usei a RI, que dá pra baixar em https://jax-ws.dev.java.net/2.1.1/index.html).

[]´s

Pessoal, alguém sabe como faço para limpar as propriedades da JVM? descobri o erro da minha aplicação, a função para remover na verdade não remove. estou fazendo da seguinte forma:

System.getProperties().remove(“key”);
e também usei System.clearProperty(“key”);

mas n removeram nada.

Asaudate, vc é a minha referência nessa parada, se puder dar uma força mais uma vez… hehehe

System.getProperties().remove(“key”); funciona pra mim. Que parâmetro você está querendo remover?? E como você seta, via parâmetro da VM, mesmo, ou via programação?

[]´s

Asaudate, Bom dia.

cara seguinte, ontem remexi nesse trem e percebi o seguinte… a função que estou utilizando aqui no Maker envia a NF da seguinte forma:

primeira ela da System.setProperty(“javax.net.ssl.keyStore”, MinhavariavelKeystore); para guardar os dados no sistema;
em seguida ela utiliza uma classe espicífica pra realizar o envio e depos limpa as propriedades do sistema com
System.getProperties().remove(key);

Quando vi isso pensei que a função n tivesse funcionando, mas coloquei uma série de labels no jsp e percebi que ele está limpando mesmo as propriedades do sistema.
Sendo assim a única solução que consigo pensar é mudar a função e tentar passar esses dados a partir de uma variável e não pegando do sistema, como está sendo feito atualmente.
O problema ainda maior é que a classe q a função importa para enviar os dados pra prefeitura, está num .class e não tenho acesso ao código. vou pesquisar por uma função que realize o envio da NF para o webservice, mas já pergunto se é obrigatório os dados estarem nas propriedades do sistema ou se eles podem ficar numa variável como penso em fazer?
No aguardo, e mais uma vez agradeço a ajuda que tem me dado.(desesperado aqui no trampo p resolver esse negócio, projeto no final e só dependendo desse pepino… affs)

alguém sabe me dizer onde encontro um material sobre as bibliotecas:
import org.apache.axis.client.Stub;
import org.apache.axis.wsdl.gen.NoopFactory;
import org.apache.axis.wsdl.symbolTable.;
import org.apache.axis.wsdl.toJava.
;

dei uma olhada no google mas n achei nada útil, preciso entender como isso funciona para tentar gerar uma classe que envie o XML para o webservice e me de um retorno.

Pessoal, estou tendo problemas para definir o serviço de envio da nota, no seguinte trecho do código

javax.xml.ws.Service service = javax.xml.ws.Service.create(new java.net.URL(url), new javax.xml.namespace.QName(namespace, serviceName));

apresenta o erro:
javax.xml.ws.WebServiceException: The following WSDL exception occurred: WSDLException: faultCode=WSDL4JWrapper : : WSDLException: faultCode=WSDL4JWrapper : : Received fatal alert: handshake_failure

alguém já passou por isso?

Código inteiro do erro:

Exceção Gerada:
javax.xml.ws.WebServiceException: The following WSDL exception occurred: WSDLException: faultCode=WSDL4JWrapper : : WSDLException: faultCode=WSDL4JWrapper : : Received fatal alert: handshake_failure at org.apache.axis2.jaxws.ExceptionFactory.createWebServiceException(ExceptionFactory.java:170) at org.apache.axis2.jaxws.ExceptionFactory.makeWebServiceException(ExceptionFactory.java:67) at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.setupWsdlDefinition(ServiceDescriptionImpl.java:507) at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.(ServiceDescriptionImpl.java:128) at org.apache.axis2.jaxws.description.impl.DescriptionFactoryImpl.createServiceDescription(DescriptionFactoryImpl.java:101) at org.apache.axis2.jaxws.description.DescriptionFactory.createServiceDescription(DescriptionFactory.java:67) at org.apache.axis2.jaxws.spi.ServiceDelegate.(ServiceDelegate.java:84) at org.apache.axis2.jaxws.spi.Provider.createServiceDelegate(Provider.java:45) at javax.xml.ws.Service.(Service.java:33) at javax.xml.ws.Service.create(Service.java:85) at wfr.com.systems.system_tif.rules.WebrunFunctions.ebfWSCallSSL(WebrunFunctions.java:11323) at wfr.com.systems.system_tif.rules.EnviaLoteNfseWs.run(EnviaLoteNfseWs.java:102) at wfr.rules.WFRRule.start(WFRRule.java:741) at wfr.rules.WFRRule.callRule(WFRRule.java:661) at wfr.com.systems.system_tif.rules.MontaXml.run(MontaXml.java:165) at wfr.rules.WFRRule.start(WFRRule.java:741) at wfr.rules.WFRRule.call(WFRRule.java:1779) at wfr.rules.WFRRule.call(WFRRule.java:53) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:269) at java.util.concurrent.FutureTask.run(FutureTask.java:123) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675) at java.lang.Thread.run(Thread.java:595) Caused by: WSDLException: faultCode=WSDL4JWrapper : : WSDLException: faultCode=WSDL4JWrapper : : Received fatal alert: handshake_failure: at org.apache.axis2.jaxws.util.WSDL4JWrapper.(WSDL4JWrapper.java:184) at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.setupWsdlDefinition(ServiceDescriptionImpl.java:489) … 20 more

Causa:
WSDLException: faultCode=WSDL4JWrapper : : WSDLException: faultCode=WSDL4JWrapper : : Received fatal alert: handshake_failure: at org.apache.axis2.jaxws.util.WSDL4JWrapper.(WSDL4JWrapper.java:184) at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.setupWsdlDefinition(ServiceDescriptionImpl.java:489) at org.apache.axis2.jaxws.description.impl.ServiceDescriptionImpl.(ServiceDescriptionImpl.java:128) at org.apache.axis2.jaxws.description.impl.DescriptionFactoryImpl.createServiceDescription(DescriptionFactoryImpl.java:101) at org.apache.axis2.jaxws.description.DescriptionFactory.createServiceDescription(DescriptionFactory.java:67) at org.apache.axis2.jaxws.spi.ServiceDelegate.(ServiceDelegate.java:84) at org.apache.axis2.jaxws.spi.Provider.createServiceDelegate(Provider.java:45) at javax.xml.ws.Service.(Service.java:33) at javax.xml.ws.Service.create(Service.java:85) at wfr.com.systems.system_tif.rules.WebrunFunctions.ebfWSCallSSL(WebrunFunctions.java:11323) at wfr.com.systems.system_tif.rules.EnviaLoteNfseWs.run(EnviaLoteNfseWs.java:102) at wfr.rules.WFRRule.start(WFRRule.java:741) at wfr.rules.WFRRule.callRule(WFRRule.java:661) at wfr.com.systems.system_tif.rules.MontaXml.run(MontaXml.java:165) at wfr.rules.WFRRule.start(WFRRule.java:741) at wfr.rules.WFRRule.call(WFRRule.java:1779) at wfr.rules.WFRRule.call(WFRRule.java:53) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:269) at java.util.concurrent.FutureTask.run(FutureTask.java:123) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675) at java.lang.Thread.run(Thread.java:595)

estou há dois dias tentando encontrar a causa, mas não identifico, já olhei na documentação do Service.create e ele recebe de fato dois parametros, a URL e o QName com nome do servico e namespace. o engraçado é que tirando a URL e passando apenas o QName ele para de dar erro, mas não posso deixar assim porque sem a url do wsdl as funções de envio não funcionarão.

Andei pesquisando sobre o erro acima e me parece que no momento do service.create é feita uma requisicao com o wsdl e em webservices que exigem autenticacao é necessário que seja informado o keystore.
Bem assim é a programação, resolvendo um problema e aparecendo outro, a saga da NF parece n ter fim.

Amigos, o erro agora é : java.io.IOException: Keystore was tampered with, or password was incorrect

ele ocorre nessa parte do codigo:

SSLSocketFactoryGenerator sslFactory = new SSLSocketFactoryGenerator(alias.toString(), fileKeyStore.toString(), filepfx.toString(), passKeyStore.toString(), passpfx.toString());

javax.net.ssl.SSLSocketFactory socketFactory = null;

try{
socketFactory = sslFactory.getSSLSocketFactory();
}catch (Exception e){
return new Variant(e.toString());
}

O código do SSLSocketFactoryGenerator me foi cedido pelo nosso amigo Alexandre(que tem me ajudado ate aqui).
segue código:

[code]
package raneves.generator;

import incode.tifs.AliasSelectorKeyManager;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.logging.Logger;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509KeyManager;

public class SSLSocketFactoryGenerator {

private String alias = null;
private String keyStore = null;
private String trustStore = null;

public SSLSocketFactoryGenerator (String alias, String keyStore, String trustStore, String keyStorePass, String trustStorePass) {
	if (alias == null)
		throw new IllegalArgumentException("The alias may not be null");
	this.alias = alias;
	this.keyStore = keyStore;
	this.trustStore = trustStore;

}

public SSLSocketFactory getSSLSocketFactory() throws IOException, GeneralSecurityException {

	KeyManager[] keyManagers = getKeyManagers();
	TrustManager[] trustManagers =getTrustManagers();

	//For each key manager, check if it is a X509KeyManager (because we will override its 		//functionality
	for (int i=0; i<keyManagers.length; i++) {
		if (keyManagers[i] instanceof X509KeyManager) {
			keyManagers[i]=new AliasSelectorKeyManager((X509KeyManager)keyManagers[i], alias);
		}
  		}

	SSLContext context=SSLContext.getInstance("SSL");
	context.init(keyManagers, trustManagers, null);

	SSLSocketFactory ssf=context.getSocketFactory();
		return ssf;
}	

public String getKeyStorePassword() {
	return "keyStorePassword";
}

public String getTrustStorePassword() {
	return "trustStorePassword";
}

public String getKeyStore() {
	return keyStore;
}

public String getTrustStore() {

	return trustStore;
}

private KeyManager[] getKeyManagers()
throws IOException, GeneralSecurityException
{

	//Init a key store with the given file.

	String alg=KeyManagerFactory.getDefaultAlgorithm();
	KeyManagerFactory kmFact=KeyManagerFactory.getInstance(alg);

	FileInputStream fis=new FileInputStream(getKeyStore());
	KeyStore ks=KeyStore.getInstance("jks");
	ks.load(fis, getKeyStorePassword().toCharArray());
	fis.close();

	//Init the key manager factory with the loaded key store
	kmFact.init(ks,  getKeyStorePassword().toCharArray());

	KeyManager[] kms=kmFact.getKeyManagers();
	return kms;
}

protected TrustManager[] getTrustManagers() throws IOException, GeneralSecurityException
{

	String alg=TrustManagerFactory.getDefaultAlgorithm();
	TrustManagerFactory tmFact=TrustManagerFactory.getInstance(alg);

	FileInputStream fis=new FileInputStream(getTrustStore());
	KeyStore ks=KeyStore.getInstance("jks");
	ks.load(fis, getTrustStorePassword().toCharArray());
	fis.close();

	tmFact.init(ks);

	TrustManager[] tms=tmFact.getTrustManagers();
	return tms;
}

}[/code]
olhando o código uma coisa que n entendi foi porque vc(alexandre) pega a senha como parametro mas n seta ela na construtora.

Prezados,

Creio que o erro está neste trecho:


		FileInputStream fis=new FileInputStream("C:\\Program Files\\emp.keystore");
		KeyStore ks=KeyStore.getInstance("jks");
		ks.load(fis, getKeyStorePassword().toCharArray());
		fis.close();

por alguma razão ele n consegue carregar o ks.load

Prezados,

identifiquei o problema, era a instancia que estava setando errado. ali deve-se passar o .pfx e a minha instancia que é PKCS12.

O problema agora é pra converter uma string para o tipo SOAPMessage:

[code]
java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(arguments.getBytes());

javax.xml.soap.SOAPMessage messageInput = null;

try {

messageInput = javax.xml.soap.MessageFactory.newInstance().createMessage(new javax.xml.soap.MimeHeaders(), bais);

}catch (Exception e){
return new Variant(e.toString());
}[/code]

o alerta da exceção diz:

org.apache.axiom.soap.SOAPProcessingException: First Element must contain the local name, Envelope , but found cabecalho
:shock: :shock: :shock: :?:

Prezados, ao que parece é necessário inserir uma tag(algumas na verdade) no XML. googlando encontrei algo assim:

<?xml version="1.0" encoding="UTF-8"?>
 <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:mh="http://www.Monson-Haefel.com/jwsbook/BookQuote">
<soap:Body>
 <mh:getBookPrice>
 <isbn xsi:type="xsd:string">0321146182 </isbn>
</mh:getBookPrice>
</soap:Body></soap:Envelope>

todo o conteudo do meu XML deve ir dentro da soap:body?

:roll: :roll: :roll: :roll: :roll:

coloquei o conteúdo do xml dentro da tag soap:Body e me retorna o erro:

avax.xml.soap.SOAPException: org.apache.axiom.om.OMException: com.ctc.wstx.exc.WstxParsingException: Illegal processing instruction target (“xml”); xml (case insensitive) is reserved by the specs.
at [row,col {unknown-source}]: [2,86]

alguém sabe como preparar o XML para esse formato SOAPMessage :?: :?: :?: :?: :?: :?: :?:

o problema estava na tag <?xml version="1.0" encoding="UTF-8"?> que era declarada duas vezes.

agora, quando tento enviar uzando:

javax.xml.soap.SOAPMessage response = message.invoke(messageInput); me vem o erro:

javax.xml.ws.soap.SOAPFaultException: Cannot find dispatch method for {http://www.abrasf.org.br/nfse.xsd}GerarNfseEnvio

hoje é meu ultimo dia para finalizar essa NF, caso contrário no mínimo tomarei uma bronca do patrão e no máximo serei demitido :frowning: se alguém puder me ajudar eu serei eternamente grato, venho buscando solução no google, mas ainda n compreende o motivo do erro, parece ser algo relacionado ao targetNameSpace do wsdl da prefeitura, mas ainda n sei como definir esse parametro no meu XML.

Graças a dica do Saudate consegui gerar meu XML corretamente.
Agora só me falta verificar o retorno, alguém sabe como faço para converter a variável response em uma string? ou mesmo ler o retorno do xml com ela? [code]
javax.xml.ws.Dispatch<javax.xml.soap.SOAPMessage> message = service.createDispatch(new javax.xml.namespace.QName(namespace.toString(), portName.toString()), javax.xml.soap.SOAPMessage.class, javax.xml.ws.Service.Mode.MESSAGE);

javax.xml.soap.SOAPMessage response = message.invoke(messageInput);
[/code]

:?: :?: :?:

Alexandre,

Quando vou definir o servico me vinha o erro de Received fatal alert: handshake_failure

lendo diversos foruns me lembro que encontrei um falando que no momento em que o serviço é criado se o servidor exigir autenticação como é o caso da NFSe da prefeitura é necessário informar o keystore, daí eu setei na system e parou o erro, agora consegui enviar o XML sem problemas, mas quando mudo de empresa e keystore me vem o mesmo erro que dava na função que usava anteriormente “Erro na Autenticação”

qual a forma de contornar esse Received fatal alert: handshake_failure? sem ter de setar o keystore na system?

o problema está nessa linha javax.xml.ws.Service.create(new java.net.URL(url.toString()), new javax.xml.namespace.QName(namespace.toString(), serviceName.toString()));

quando o service.create é criado nessa construtora ele já faz o acesso com webservice, e como o da prefeitura requer o PFX eu preciso passar ele de alguma maneira, só consegui via system.
se eu jogar o link no browser ele vai me pedir o PFX tambem e se n informar ele me da o mesmo erro
[b]O sistema remoto SSL não conseguiu negociar um conjunto aceitável de parâmetros de segurança.

(Código do erro: ssl_error_handshake_failure_alert)
[/b]

deve haver uma forma de informar esse pfx sem ter de setar na system…