Consumir webservice SOAP da Microsiga em JSF

Olá turma!

Estou iniciando meus estudos para mudar o front de um portal da Microsiga, hoje em Advpl-ASP, para java server faces. Tal portal consome webservices feitos também em Advpl-asp, os quais ainda serão mantidos.

Portanto, venho lhes pedir auxílio neste assunto. Fucei na web em tudo que é canto e não encontrei um “how to” de consumir um webservice SOAP em JSF.

De início, preciso consumir o webservice SOAP que trata do login no portal. O form terá dois inputs ( login e senha ) que deverão ser passados para o webservice. Resta saber agora como.

Já consegui criar o client deste webservice SOAP de login. Agora, que passos devo seguir ?

Se tiverem algo semelhante ao caso, JSF consumindo um webservice SOAP qualquer c/passagem de parâmetros, será de grande ajuda para entender a lógica.

Ou se tiverem/souberem de um tutorial descrevendo claramente JSF + webservice SOAP

Desde já agradeço a atenção,

Apache CXF + JSF 2 / RichFaces 4 + JBoss AS 6.1

— Client

[code]package ws.client;

import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;

public class ClientFactory {

Class<T> klass;

public ClientFactory(Class<T> klass){
	this.klass = klass;
}

@SuppressWarnings("unchecked")
public T createFactory(String urlService){
	
	JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
	factory.getInInterceptors().add(new LoggingInInterceptor());
	factory.getOutInterceptors().add(new LoggingOutInterceptor());
	factory.setServiceClass(klass);
	//factory.setUsername(username);
	//factory.setPassword(password);
	factory.setAddress(urlService);
	T client = (T) factory.create();
	
	return client;
}

}[/code]

–Serviço

[code]
package ws.services.validausuario;

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

import ws.bean.ValidaUsuario;

@WebService
public interface ValidaUsuarioService {

@WebMethod
public ValidaUsuario retornoValidaUsuario(
		@WebParam(name = "idParceiro") Long idParceiro,
		@WebParam(name = "usuario") String usuario,
		@WebParam(name = "senha") String senha,
		@WebParam(name = "seguranca") String seguranca		
		);

}[/code]

–Bean

package ws.bean;

public class ValidaUsuario {

	private Integer situacaoRetorno;
	private String 	mensagemRetorno;
	private Long idUsuario;
	private String nome;
	private String docFederal;
	
	public ValidaUsuario() {
		
	}
	public ValidaUsuario(Integer tipo, String texto, Long idUsuario,
			String nome, String docFederal) {
		super();
		this.situacaoRetorno = tipo;
		this.mensagemRetorno = texto;
		this.idUsuario = idUsuario;
		this.nome = nome;
		this.docFederal = docFederal;
	}

Get and Set...[/code]

--Controller

[code]package ws.control;

import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.faces.bean.ManagedBean;

import ws.bean.ValidaUsuario;
import ws.client.ClientFactory;
import ws.services.validausuario.ValidaUsuarioService;
import ws.util.SecurityData;

@ManagedBean(name = "acessoUsuario")
public class ControllerValidaUsuario {

	public ControllerValidaUsuario() {
		this.clientFactory = new ClientFactory<ValidaUsuarioService>(ValidaUsuarioService.class);
	}

	private ClientFactory<ValidaUsuarioService> clientFactory;
	private ValidaUsuario usuario;
	private ValidaUsuarioService usuarioService;
	private Long idParceiro;
	private String login;
	private String senha;
	private String seguranca;
	private String urlService;

	public String validaAcesso() throws InvalidKeyException, BadPaddingException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, InvalidAlgorithmParameterException {

		usuarioService = clientFactory.createFactory(urlService);
		usuario = usuarioService.retornoValidaUsuario(idParceiro, SecurityData.encrypt(login), SecurityData.encrypt(senha), seguranca);

		return "retorno_valida_usuario";
	}
	public String inicio(){
		return "valida_usuario";
	} 
Get and Set...[/code]

--Pagina

[code]<ui:composition xmlns="http://www.w3.org/1999/xhtml"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:f="http://java.sun.com/jsf/core"
 xmlns:ui="http://java.sun.com/jsf/facelets"
 xmlns:a4j="http://richfaces.org/a4j"
 xmlns:rich="http://richfaces.org/rich">
<ui:include src="/menu.xhtml"></ui:include>
 <f:view>
 <h:head></h:head>
 <h:body>
    <rich:panel header="Valida Usuario Service - Dados Enviados para o Web Service">
      
      <h:form>
      
      <h:panelGrid columns="2">
      
		<h:outputText value="Id Paceiro" />
		<h:inputText size="30" id="idParceiro" value="#{acessoUsuario.idParceiro}"></h:inputText>
		
		<h:outputText value="Login" />
		<h:inputText size="30"  id="login" value="#{acessoUsuario.login}"></h:inputText>
		
		<h:outputText value="Senha" />
		<h:inputText size="30"  id="senha" value="#{acessoUsuario.senha}"></h:inputText>
		
		<h:outputText value="Segurança ( IP )" />
		<h:inputText size="30"  id="ip" value="#{acessoUsuario.seguranca}"></h:inputText>
	
	    <h:outputText value="End Point ( Sem o ?wsdl )" />
		<h:inputText size="30" id="endpoint" value="#{acessoUsuario.urlService}"></h:inputText>
	    
	    <br />
	    <br />
	    
		<h:commandButton action="#{acessoUsuario.validaAcesso}" value="Realizar Login"/>
		<h:outputText value=""/>
		
	  </h:panelGrid>	
	   </h:form>
    </rich:panel>
  </h:body>
 </f:view>
</ui:composition>

Foi só pra vc ter um idéia de como dá pra fazer… não sei se é adequado no so seu caso… a estrutura é meio engessada mas quebra o galho…

abraço!

Olá jmag e Pessoal,

jmag: Agradeço imensamente a rápida resposta!

Com base no código que enviastes, tive uma melhor visão do horizonte e estou chegando bem perto do sucesso. Fiz o seguinte:

Ambiente: Netbeans 7.0.1 usando JSF 2.0

  1. Adicionado uma nova aplicação web, usando framework JavaServer Faces, Biblioeteca JSF 2.0, idioma das páginas: Facelets;
  2. Adicionado ao projeto um bean gerenciado JSF, escopo: Session;
  3. Adicionado Cliente para serviço web, baseado na url do WSDL;
  4. No index.xhtml, adicionado formulário do JSF, com dois inputs para login e senha;
  5. Adicionadas duas variáveis, cLogin e cPass, no ManagedBean.java;
  6. No ManagedBean.java, fui no menu Inserir código > Operação de Chamada ao serviço web e selecionei o método do WS para o qual devem ser passados o login, senha e mais dois parâmetros que terão valores fixos (por enquanto). Foram incluídas automaticamente linhas no arquivo, ficando no final assim :
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pacote;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.xml.ws.WebServiceRef;

/**
 *
 * @author Vicente de Paula
 */
@ManagedBean
@SessionScoped
public class NewJSFManagedBean {
    @WebServiceRef(wsdlLocation = &quot;WEB-INF/wsdl/192.168.0.101/ws/USERPORTAL.apw.wsdl&quot;)
    private USERPORTAL service;
    
    private String cLogin;
    private String cPass;
    
    /** Creates a new instance of NewJSFManagedBean */
    public NewJSFManagedBean() {
    }

    public void setcLogin(String cLogin) {
        this.cLogin = cLogin;
    }

    public void setcPass(String cPass) {
        this.cPass = cPass;
    }

    private LOGINUSERSTRUCT prtlogin(java.lang.String userlogin, java.lang.String userpassword, java.lang.String usertype, java.lang.String portalaccess) {
        pacote.USERPORTALSOAP port = service.getUSERPORTALSOAP();
        return port.prtlogin(userlogin, userpassword, usertype, portalaccess);
    }
        
}

Parei aqui. Estou ciente de que devo amarrar os inputs ao serviço web, mas como ? Que me, além desta amarração ?

Grato,

Vicente de Paula :slight_smile:

Olá…

O Método

private LOGINUSERSTRUCT prtlogin(java.lang.String userlogin, java.lang.String userpassword, java.lang.String usertype, java.lang.String portalaccess) { pacote.USERPORTALSOAP port = service.getUSERPORTALSOAP(); return port.prtlogin(userlogin, userpassword, usertype, portalaccess); }

Deve ser alterado para:

[code]public LOGINUSERSTRUCT prtlogin() {
pacote.USERPORTALSOAP port = service.getUSERPORTALSOAP();
//return port.prtlogin(cLogin, cPass, usertype, portalaccess);
// Aqui voce pode realizar a validação e já retornar para outra página

         port.prtlogin(cLogin, cPass, usertype, portalaccess); 

   return "pagina_principal"; 
}

[/code]

A Página fica:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:f="http://java.sun.com/jsf/core"
 xmlns:ui="http://java.sun.com/jsf/facelets"
 xmlns:a4j="http://richfaces.org/a4j"
 xmlns:rich="http://richfaces.org/rich">

 <f:view>
 <h:head></h:head>
 <h:body>
    <rich:panel header="Valida Usuario Service - Dados Enviados para o Web Service">
      
      <h:form>
      
      <h:panelGrid columns="2">

	
		<h:outputText value="Login" />
		<h:inputText size="30"  id="login" value="#{newJSFManagedBean.cLogin}"></h:inputText>
		
		<h:outputText value="Senha" />
		<h:inputText size="30"  id="senha" value="#{newJSFManagedBean.cPass}"></h:inputText>
		
	    
		<h:commandButton action="#{newJSFManagedBean.prtlogin}" value="Realizar Login"/>
		<h:outputText value=""/>
		
	  </h:panelGrid>	
	   </h:form>
    </rich:panel>
  </h:body>
 </f:view>
</ui:composition>

Aqui tem um exemplo de JSF/ Login bem básico: http://www.roseindia.net/jsf/JSFLoginApplication.shtml

Acho que é isso ai…
Abraço!

Obrigado pela ajuda!

Está dando um erro aqui mas vou ver onde está ocorrendo a bronca.

Vicente :slight_smile:

OK… se precisar posta ai…

:slight_smile:

Olá jmag,

No netbeans 7.0.1, usando JAX-WS e JSF 2.0, consegui fazer um projeto básico e realizar a comunicação com o webservice microsiga.

Contudo, está ocorrendo o seguinte problema, visto no console do servidor webservice Microsiga:
WEBSERVICE ERROR : Soap Prefix Missing : USERPORTAL : PRTLOGIN : Formato do Pacote Soap DESCONHECIDO.

Este mesmo servidor webservice padrão microsiga é consumido hoje via Advpl-Asp, sem problemas. Este mesmo serviço/método USERPORTAL, no projeto supracitado, ocasiona o erro acima.

Vê só a diferença do XML entre os dois consumos:

–Consumo via Advpl-Asp (funcionando):

&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;&lt;soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"&gt;&lt;soap:Body&gt;&lt;PRTLOGIN xmlns="http://webservices.microsiga.com.br/userportal.apw"&gt;&lt;USERLOGIN&gt;usuario&lt;/USERLOGIN&gt;&lt;USERPASSWORD&gt;senha&lt;/USERPASSWORD&gt;&lt;USERTYPE&gt;1&lt;/USERTYPE&gt;&lt;PORTALACCESS&gt;&lt;/PORTALACCESS&gt;&lt;/PRTLOGIN&gt;&lt;/soap:Body&gt;&lt;/soap:Envelope&gt;

–Consumo via JAX-WS / JSF 2.0 (com o problema de Formato do Pacote Soap DESCONHECIDO):

&lt;?xml version='1.0' encoding='UTF-8'?&gt;&lt;S:   Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"&gt;                                                                                                         &lt;S:Body&gt;&lt;PRTLOGIN xmlns="http://webservices.microsiga.com.br/userportal.apw"&gt;&lt;USERLOGIN&gt;usuario&lt;/USERLOGIN&gt;&lt;USERPASSWORD&gt;senha&lt;/USERPASSWORD&gt;&lt;USERTYPE&gt;&lt;/USERTYPE&gt;&lt;PORTALACCESS&gt;&lt;/PORTALACCESS&gt;&lt;/PRTLOGIN&gt;&lt;/S:Body&gt;&lt;/S:Envelope&gt;

Tens idéia de como reparar isto no JAX-WS ?

Grato,

Vicente de Paula :slight_smile:

Oi,

Vicente, você por acaso trabalha em uma filial TOTVS?
Já que cita Microsiga e ADVPL.

Sobre o seu questionamento, me parece problema na conversão e não no WSDL que está sendo consumido.
Eu sempre usei o JAX-WS para lidar com objetos passados e/ou requisitados por um WS, já que o JAVA se encarrega de todas as devidas conversões.

Se o WSDL que está consumido for estatico, o wsimport vai lhe ser extremamente útil!
Dê uma olhada no link e veja o que acha.

Sobre o seu erro talvez possa ser algo relacionado ao seu código, pois, se em ADVPL ele compreende o WSDL em JAVA também deveria.
Estou supondo que o WSDL esteja bem formado, sem erros e/ou algo especifico (duvido) para ADVPL.

Aqui tem um exemplo de utilização: http://blog.caelum.com.br/webservices-sem-servidor-de-aplicacao-no-java-6/

Abraços!

Olá Nel,

Não trabalho na Totvs, mas sim em um cliente que possui o ERP Protheus 10.

Pois então… este wsimport já é incluso no Netbeans 7.0.1 ? Pergunto isto pois gerei o client do serviço conforme descrevo no assentamento de 06/10/2011 13:21:37.

Vicente :slight_smile:

[quote=vicentedepaula]Olá Nel,

Não trabalho na Totvs, mas sim em um cliente que possui o ERP Protheus 10.

Pois então… este wsimport já é incluso no Netbeans 7.0.1 ? Pergunto isto pois gerei o client do serviço conforme descrevo no assentamento de 06/10/2011 13:21:37.

Vicente :)[/quote]

Imaginei.

Na realidade não sei lhe responder, mas o wsimport é um comando interno do Java 6 (não sei se existe em versões anteriores).
Assim como tem o javac você tem o wsimport. Ele é bem intuitivo e fácil de utilizar e pode ser gerado diretamente no seu prompt de comando.

Se eu rodar no prompt aqui do Windows 7 esse comando:

wsimport -keep -p br.com.caelum.cliente http://localhost:8080/oi?wsdl

Ele vai me gerar o pacote (-p …) no diretorio corrente. Simples não? :slight_smile:

Galera,

Fiz um teste para o serviço/método mencionados aqui, usando o aplicativo soapUI 4.0.1. Obtive sucesso!

Vejam como o xml é diferente no soapUI 4.0.1:

&lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:user="http://webservices.microsiga.com.br/userportal.apw"&gt; &lt;soapenv:Header/&gt; &lt;soapenv:Body&gt; &lt;user:PRTLOGIN&gt; &lt;user:USERLOGIN&gt;usuario&lt;/user:USERLOGIN&gt; &lt;user:USERPASSWORD&gt;senha&lt;/user:USERPASSWORD&gt; &lt;!--Optional:--&gt; &lt;user:USERTYPE&gt;1&lt;/user:USERTYPE&gt; &lt;!--Optional:--&gt; &lt;user:PORTALACCESS&gt;&lt;/user:PORTALACCESS&gt; &lt;/user:PRTLOGIN&gt; &lt;/soapenv:Body&gt; &lt;/soapenv:Envelope&gt;

Suspeito que devo modificar as tags geradas pelo JAX-WS, de s:… para soap:… e s=… para soap=…
Aguardo o auxílio de vocês para saber como, pois fucei no projeto em busca destas tags e não encontrei :frowning:

Vicente :slight_smile:

[quote=vicentedepaula]Galera,

Fiz um teste para o serviço/método mencionados aqui, usando o aplicativo soapUI 4.0.1. Obtive sucesso!

Vejam como o xml é diferente no soapUI 4.0.1:

&lt;soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:user="http://webservices.microsiga.com.br/userportal.apw"&gt; &lt;soapenv:Header/&gt; &lt;soapenv:Body&gt; &lt;user:PRTLOGIN&gt; &lt;user:USERLOGIN&gt;usuario&lt;/user:USERLOGIN&gt; &lt;user:USERPASSWORD&gt;senha&lt;/user:USERPASSWORD&gt; &lt;!--Optional:--&gt; &lt;user:USERTYPE&gt;1&lt;/user:USERTYPE&gt; &lt;!--Optional:--&gt; &lt;user:PORTALACCESS&gt;&lt;/user:PORTALACCESS&gt; &lt;/user:PRTLOGIN&gt; &lt;/soapenv:Body&gt; &lt;/soapenv:Envelope&gt;

Suspeito que devo modificar as tags geradas pelo JAX-WS, de s:… para soap:… e s=… para soap=…
Aguardo o auxílio de vocês para saber como, pois fucei no projeto em busca destas tags e não encontrei :frowning:

Vicente :)[/quote]

O soapUI normalmente adiciona tags em XML de retorno. Já executei vários testes com ele e via que os resultados diferem daquilo que era esperado.
Todavia, prova que o Webservice está no ar e com um WSDL padrão. Acredito que o problema esteja da forma como está realizando a conexão ao WS e trabalhando com o retorno e não na API do JAVA.

Tentou utilizar o wsimport conforme eu havia lhe citado ? :slight_smile:
Se sim, quais resultados obteve?

Olá turma!

Segue url contendo a solução para o problema relatado neste tópico:

http://oslunaticos.com.br/2011/10/consumindo-web-service-do-protheus-com-jax-ws/

Agradeço ao jmag e nel pela atenção e auxílio em solucionar o caso e também ao Eduardo (EDUFOLLY) pelo apoio e disponibilidade das instruções no blog em que participa.

Vicente de Paula :slight_smile: