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.

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.

Visão geral dos padrões de Webservices




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
Vamos começar com a o seguinte cenário, uma aplicação Java EE5 rodando no JBoss AS 5.1.0.GA com EJB3 sendo exposto como um Webservice através de anotações, esta aplicação vai ser consumida por uma aplicação Windows Forms usando .net 3.5 com C#.

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 do EJB3 focando primeiramente na sua implementação. Em um segundo momento vou mostrar as modificações neste EJB3 para expor o mesmo como um Webservice.

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:

Aplicação Web Consumindo o EJB3


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.
Vamos ver como fica a interface depois destas modificações.


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.
Agora vou mostrar como fica a classe completa depois destas alterações:

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:

Adicionando Referência de Webservice no Visual Studio 2008


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.


Formulário feito para consumir o WS feito escrito em Java


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:

Aplicação em Execução.


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:
Aplicação .net:

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.

Popular posts from this blog

Kafka Streams with Java 15

Rust and Java Interoperability

HMAC in Java