Interoperabilidade na prática JEE 5(JBoss) com .NET (C# framework 3.5) parte 1
O desenvolvimento de software corporativo de hoje tem que suportar a interoperabilidade de serviços entre diversas plataformas, neste post vou mostrar como podemos fazer serviços/aplicações escritas em Java com JEE 5 no Jboss 5.1 conversar com uma aplicação C# com .net Framework 3.5.
Interoperabilidade de Webservices
Na prática webservices não são 100% interoperaveis, ainda existem diversos gaps para realizar a comunicação, mas existe uma organização que é a WS-I que define os padrões de comunicação para padronização de interoperabilidade de webservices. No total existem mais de 50 especificações de Webservices mantidas por 3 organizações(W3C, OASIS, WS-I).O WS-Basic profile 1.1 não cobre todas as especificações de webservices mas cobre especificações como SOAP, WSDL, UDDI, XML e HTTP.
Como vamos realizar a conversação de uma aplicação Java EE5 com uma aplicação .net fw 3.5 vamos ter algumas dependências são elas:
Em outro post vou mostrar o caminho inverso, uma aplicação Asp.net Webservice escrita com C# também e sendo consumida por uma aplicação Java com SOAP e com Jax-WS puro, sendo que a aplicação SOAP vai rodar no ORACLE OC4J 10.1.3.4 e Jax-Ws vai ser uma aplicação Plain Java sem Application Server.
Aplicação Java EE5 rodando no JBoss AS 5.1 com EJB3
Criei 3 projetos no eclipse utilizando o plugin do WTP. Os projetos e suas responsabilidades são as seguintes:
Vamos a definição da interface DateService.java
Este é um exemplo simples que costumo usar para simplificar a compreensão do cenário completo da solução, agora vamos a implementação deste EJB 3.
Vamos a definição da implementação do Serviço DateServiceImpl.java
Como o leitor pode ver é bem simples a implementação, apénas estou retornando a data de um objeto Date do Java. Estou definindo este EJB como sendo do tipo Stateless ou seja sem estado e estou dizendo que ele implementa a interface remota DateService que também é o nosso contrato.
Agora vamos voltar a aplicação web aonde vou criar um simples scriplet para consumir o nosso EJB3, confira o código:
index.jsp
Ao rodar fazer o deploy nesta aplicação no JBoss AS 5.1 e abrir a aplicação no browser você irá receber o seguinte resultado semelhante ao que segue a baixo:
Ok, agora vamos ver a implementação do EJB chamada de DateServiceImpl que também ira sofrer alterações, vamos adicionar as seguintes anotações:
Para testar a exposição do EJB3 como Webservice vou utilizar a ferramenta SoapUI a fim de testar se o Webservice esta no ar e funciona. Antes de ir para a ferramenta é necessário fazer o deploy desta solução no Jboss AS 5.1 e obter o WSDL que pode ser baixado neste endereço:
http://localhost:8080/java-ee-test-java-ee-test-ejb/DateServiceImpl?wsdl
A partir deste ponto é possível criar um projeto no SoapUI utilizando o WSDL salvo. Ao chamar o método getDate() você deve receber um retorno como o que segue a baixo:
Aplicação .net
Abra o seu Visual Studio 2008 e crie um projeto do tipo WindowsFormsApplication. Clique no menu Project e depois no sub-menu Add Service Reference... após isto ira abrir uma janela para você informa o endereço informe o endereço web do WSDL do Webservice que é o seguinte:
http://localhost:8080/java-ee-test-java-ee-test-ejb/DateServiceImpl?wsdl
Selecione o service DataServiceImplService e Depois DateService, ao mesmo tempo ira aparecer os métodos deste serviço na caixa de operações ao lado, modifique o namespace para DateServiceProxy e clique em ok conforme a figura a baixo:
Ao rodar a aplicação .net você receberá um retorno mais ou menos como o que segue a baixo:
Aplicação Java:
No próximo post vou mostrar o caminho inverso, irei criar um Webservice com Aspx e consumir o mesmo com SOAP em uma aplicação rodando no ORACLE OC4J/OAS e outra aplicação Jax-Ws plain Java rodando no console.
Abraços e até a próxima.
Vou realizar esta conversa usando Webservice, tanto a solução do lado do Java como a solução do lado do .Net precisam implementar WS-I Basic Profile 1.1, quando criamos um Webservice com C# no .net Framework 3.5 ele já implementa WS-I Basic profile 1.1 o mesmo acontece ao utilizarmos do lado do Java o Jax-WS 2.x. Como vou rodar a solução Java no JBoss AS 5.01GA vamos estar utilizando o JBoss WS.
Interoperabilidade de Webservices
Na prática webservices não são 100% interoperaveis, ainda existem diversos gaps para realizar a comunicação, mas existe uma organização que é a WS-I que define os padrões de comunicação para padronização de interoperabilidade de webservices. No total existem mais de 50 especificações de Webservices mantidas por 3 organizações(W3C, OASIS, WS-I).O WS-Basic profile 1.1 não cobre todas as especificações de webservices mas cobre especificações como SOAP, WSDL, UDDI, XML e HTTP.
Requisitos para a solução
Como vamos realizar a conversação de uma aplicação Java EE5 com uma aplicação .net fw 3.5 vamos ter algumas dependências são elas:
- Java JDK 6_16
- JBoss AS 5.1.0.GA
- eclipse 3.4.x + WTP
- Visual Studio 2008
- SoapUI
Em outro post vou mostrar o caminho inverso, uma aplicação Asp.net Webservice escrita com C# também e sendo consumida por uma aplicação Java com SOAP e com Jax-WS puro, sendo que a aplicação SOAP vai rodar no ORACLE OC4J 10.1.3.4 e Jax-Ws vai ser uma aplicação Plain Java sem Application Server.
Aplicação Java EE5 rodando no JBoss AS 5.1 com EJB3
Criei 3 projetos no eclipse utilizando o plugin do WTP. Os projetos e suas responsabilidades são as seguintes:
- java-ee-test-web: É um projeto web empacotado em um war que contém uma página que faz lookup JNDI para acessar o EJB3 que é um serviço.
- java-ee-test-ejb: É um projeto(módulo EJB3) que contém a implementação de um serviço do tipo stateless que é exposto como Webservice.
- java-ee-test: É um projeto(módulo EAR) que serve para empacotar toda esta solução e realizar o deploy no JBoss AS 5.1.
Vamos a definição da interface DateService.java
package com.blogspot.diegopacheco.eefive.ejb; import java.rmi.Remote; /** * Interface de contrato do serviço de datas. * * @author Diego Pacheco * @version 1.0 * @since 30/08/2009 * */ public interface DateService extends Remote { public String getDate(); }
Este é um exemplo simples que costumo usar para simplificar a compreensão do cenário completo da solução, agora vamos a implementação deste EJB 3.
Vamos a definição da implementação do Serviço DateServiceImpl.java
package com.blogspot.diegopacheco.eefive.ejb; import java.util.Date; import javax.ejb.Remote; import javax.ejb.Stateless; /** * Implementação do serviço de Datas através de um EJB3 Stateless. * * @author Diego Pacheco * @version 1.0 * @since 30/08/2009 * */ @Stateless @Remote(DateService.class) public class DateServiceImpl implements DateService { @Override public String getDate() { return new Date().toString(); } }
Como o leitor pode ver é bem simples a implementação, apénas estou retornando a data de um objeto Date do Java. Estou definindo este EJB como sendo do tipo Stateless ou seja sem estado e estou dizendo que ele implementa a interface remota DateService que também é o nosso contrato.
Agora vamos voltar a aplicação web aonde vou criar um simples scriplet para consumir o nosso EJB3, confira o código:
index.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ page import="javax.naming.*" %> <%@ page import="com.blogspot.diegopacheco.eefive.ejb.*" %>Teste Ola Mundo EE 5 ! Data: <% try{ InitialContext ic = new InitialContext(); DateService ds = (DateService)ic.lookup("java-ee-test/DateServiceImpl/remote"); String dt = ds.getDate(); out.print(dt); }catch(Exception e){ out.print(e.getMessage()); } %>
Ao rodar fazer o deploy nesta aplicação no JBoss AS 5.1 e abrir a aplicação no browser você irá receber o seguinte resultado semelhante ao que segue a baixo:
Agora vamos modificar a nossa aplicação para expor o EJB 3 como Webservice, para isto vamos utilizar anotações. Vamos adicionar duas anotações ao Contrato do Serviço chamado DataService, são as anotações:
- @WebService: Que indica que esta interface deve ser exposta como um Webservice.
- @SOAPBinding(style = Style.DOCUMENT): Que indica o estilo de formando da mensagem que será enviada. Estou usando o estilo de documento, se você quiser saber sobre as diferenças de Documento para RPC confirma este link.
package com.blogspot.diegopacheco.eefive.ejb; import java.rmi.Remote; import javax.jws.WebService; import javax.jws.soap.SOAPBinding; import javax.jws.soap.SOAPBinding.Style; /** * Interface de contrato do serviço de datas. * * @author Diego Pacheco * @version 1.0 * @since 30/08/2009 * */ @WebService @SOAPBinding(style = Style.DOCUMENT) public interface DateService extends Remote { public String getDate(); }
Ok, agora vamos ver a implementação do EJB chamada de DateServiceImpl que também ira sofrer alterações, vamos adicionar as seguintes anotações:
- @WebService(endpointInterface = "com.blogspot.diegopacheco.eefive.ejb.DateService"): Esta anotação de nível de classe indica que esta é a implementação do webservice de interface que esta sendo passado por parâmetro.
- @WebMethod: É uma interface a nível de métodos que indica que o método será exposto como uma operação do webservice.
package com.blogspot.diegopacheco.eefive.ejb; import java.util.Date; import javax.ejb.Remote; import javax.ejb.Stateless; import javax.jws.WebMethod; import javax.jws.WebService; /** * Implementação do serviço de Datas através de um EJB3 Stateless. * * @author Diego Pacheco * @version 1.0 * @since 30/08/2009 * */ @Stateless @Remote(DateService.class) @WebService(endpointInterface = "com.blogspot.diegopacheco.eefive.ejb.DateService") public class DateServiceImpl implements DateService { @Override @WebMethod public String getDate() { return new Date().toString(); } }
Para testar a exposição do EJB3 como Webservice vou utilizar a ferramenta SoapUI a fim de testar se o Webservice esta no ar e funciona. Antes de ir para a ferramenta é necessário fazer o deploy desta solução no Jboss AS 5.1 e obter o WSDL que pode ser baixado neste endereço:
http://localhost:8080/java-ee-test-java-ee-test-ejb/DateServiceImpl?wsdl
A partir deste ponto é possível criar um projeto no SoapUI utilizando o WSDL salvo. Ao chamar o método getDate() você deve receber um retorno como o que segue a baixo:
Consumo do WS no SoapUI 3
Aplicação .net
Abra o seu Visual Studio 2008 e crie um projeto do tipo WindowsFormsApplication. Clique no menu Project e depois no sub-menu Add Service Reference... após isto ira abrir uma janela para você informa o endereço informe o endereço web do WSDL do Webservice que é o seguinte:
http://localhost:8080/java-ee-test-java-ee-test-ejb/DateServiceImpl?wsdl
Selecione o service DataServiceImplService e Depois DateService, ao mesmo tempo ira aparecer os métodos deste serviço na caixa de operações ao lado, modifique o namespace para DateServiceProxy e clique em ok conforme a figura a baixo:
Com isso o Visual Studio ira criar as referências necessárias para você consumir o WS na sua aplicação. Eu criei um formulário bem simples apénas para mostrar qual é o endpoint a ser chamado e bem como um botão para o usuário consumir o WS e uma caixa de texto multi-linhas para mostrar o resultado do consumo.
Agora vamos ao que mais importa o código .net para consumir este Webservice escrito em Java, para isso confira o código escrito em C# que segue a baixo:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace ws_java_ee5_jboss_client { public partial class frmWsClient : Form { private DateServiceProxy.DateService ds; public frmWsClient() { InitializeComponent(); txtEndpoint.Text = "http://127.0.0.1:8080/java-ee-test-java-ee-test-ejb/DateServiceImpl"; try { ds = new DateServiceProxy.DateServiceClient(); } catch (Exception e) { txtWsResult.Text = e.Message; } } private void btnConsumir_Click(object sender, EventArgs e) { try { txtWsResult.Text = ds.getDate(); } catch (Exception ex) { txtWsResult.Text = ex.Message; } } } }
Explicando o código, eu criei uma variável de classe chamada 'ds' do tipo DateServiceProxy.DateService e no construtor do formulário eu instanciei este objeto da seguinte maneira: new DateServiceProxy.DateServiceClient(); Uma vez feito isso basta chamar o método getDate() que retorna um string.
Ao rodar a aplicação .net você receberá um retorno mais ou menos como o que segue a baixo:
Se você quiser pode baixar os fontes das duas aplicação a aplicação Java EE5 ou a aplicação C# no meu repositório do Subversion nos seguintes endereços.
Aplicação Java:
- http://diegopacheco.svn.beanstalkapp.com/sandbox/trunk/java-ee-test/
- http://diegopacheco.svn.beanstalkapp.com/sandbox/trunk/java-ee-test-web/
- http://diegopacheco.svn.beanstalkapp.com/sandbox/trunk/java-ee-test-ejb/
No próximo post vou mostrar o caminho inverso, irei criar um Webservice com Aspx e consumir o mesmo com SOAP em uma aplicação rodando no ORACLE OC4J/OAS e outra aplicação Jax-Ws plain Java rodando no console.
Abraços e até a próxima.