quarta-feira, julho 04, 2012

Hello World Cliente remoto com EJB 3.1 e JBoss AS 7.1


EJB ou Enterprise JavaBeans é um dos principais componentes da plataforma J2EE (Java 2 Enterprise Edition). É um componente do tipo servidor que executa no container do servidor de aplicação. Os principais objectivos da tecnologia EJB são fornecer um rápido e simplificado desenvolvimento de aplicações Java baseado em componentes distribuídos, transacionais, seguros e portáveis [1].

Um dos principais componentes do EJB é o Session Bean, atuando na camada de negócio, é o elemento responsável pela distribuição da aplicação. Invocando seus métodos, outras aplicações, estando na mesma máquina ou não, podem  executar tarefas de negócios dentro do servidor de aplicações [2].

JBoss Application Server (ou JBoss AS) é um servidor de aplicações J2EE open-source, ele foi desenvolvido pela JBoss, atualmente uma divisão da Red Hat. Encontra-se na versão 7.1.1 e implementa a especificação java EJB 3.1 ( JSR 318)

Através da implementação de um Hello World vamos demonstrar como pode ser feita a comunicação client/server usando acesso remonto com EJB.

1 - Pré-requisitos
  • JBoss AS 7 (Download);
  • JDK (Download) (Quando for criar os projetos escolha sempre JDK e não JRE)
  • Eclipse, versão indigo ou superior (Eclipse Juno);
  • Plugin Jboss Tools (Instala através do Eclipse MarketPlace);
2 - Definindo JBoss 7.1  Runtime  Server 
Crie um novo server conforme tela abaixo, nossa aplicação servidora será implantada nele. Para isto navegue "File" > "New" > "Other" > "Server".

3 - Criando a aplicação servidora
Crie um novo projeto do tipo "EJB Project";

Na tela que se seguir desmarque a opção EJB Cliente e marque a opção gerar ejb-jar.xml , veja como fica;

4 - Adicionando um componente EJB
No menu do eclipse escolha "New" > "Session Bean". Marque as opções Local e Remote, veja como fica;

5 - Programação do componente
Crie o método sayHello na interface remota do componente e faça a sua implementação, veja como fica o código fonte;

HelloworldRemote.java
package tads.ifrn.edgar.ejbteste;
import javax.ejb.Remote;

@Remote
public interface HelloworldRemote {
 public String sayHello();
}

Helloworld.java
package tads.ifrn.edgar.ejbteste;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
@Stateless
@LocalBean
public class Helloworld implements HelloworldRemote, HelloworldLocal {
    public Helloworld() {

    }
 @Override
 public String sayHello() {
  return "Alo Mundo!";
 }
}

6 - Execute o Helloworld como Server

7 - Aplicação Cliente
Em um ambiente real o cliente, provavelmente, será uma aplicação web, contudo, para fins de demonstração faremos uma aplicação java normal.
No menu escolha "File" > "New" > "Project" > "Java Project", 

Para esta aplicação estar preparada para se comunicar com o servidor faremos as seguintes configurações;

7.1 - Adicionar uma referência ao projeto do servidor
Nas propriedades do projeto, selecione  " Java Build Path ", na Aba " Projects ", clique no botão " Add ", e marque o projeto servidor, veja como fica;

7.2 - Adicionar a biblioteca cliente do JBoss
É necessário incorporar ao projeto o cliente do JBoss ( jboss-client.jar ), que se encontra na pasta de instalação em ..\bin\client\
Nas propriedades do projeto, selecione  "Java Build Path", na Aba "Libraries", clique no botão "Add External JARs", abra o arquivo jboss-client.jar;

7.3 - Criar uma pasta para recursos e adicione ao classpath do projeto
Na raiz do seu projeto, ou outro local que prefira, crie uma pasta chamada  resources (Pode ser outro nome), adicione esta pasta ao classpath, da seguinte forma;
Nas  propriedades  do projeto, selecione  "Java Build Path", na Aba "Source", clique no botão "Add Folder" e selecione a pasta resources criada anteriormente;

7.4 - Na pasta criada anteriormente, adicionar o arquivo de configuração de conexão
É necessário criar o arquivo  jboss-ejb-client.properties, que deve  conter informações para permitir chamada a EJBs remotos, no mínimo as seguintes linhas;
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port = 4447
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

7.5 - Código fonte do cliente

HelloWordClient.java
import java.util.Properties;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import tads.ifrn.edgar.ejbteste.HelloworldRemote;

public class HelloWorldClient {
 public static void main(String[] args) {
  final HelloworldRemote remoto = carregarStatlessBean();
  System.out.println("Mostrando remoto: " + remoto.sayHello());
 }
 public static HelloworldRemote carregarStatlessBean() {
  final Properties propriedades = new Properties();
  propriedades.put(Context.URL_PKG_PREFIXES,"org.jboss.ejb.client.naming");
  Context context;
  try {
   context = new InitialContext(propriedades);
   // O padrão para o comando lookup é ejb:nome do EAR/nome do projeto servidor/nome classe do modulo!nome completo da classe remota
   // Dentro da janela de console do servidor esta informação pode ser percebida, veja o que vem logo após java:jboss/exported
   return (HelloworldRemote) context.lookup("ejb:HelloWorldEAR/HelloWorld/Helloworld!tads.ifrn.edgar.ejbteste.HelloworldRemote");
  } catch (NamingException e1) {
   e1.printStackTrace();
  }
  return null;
 }
}

Referências:
[2] http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/EJBConcepts3.html
[3] https://docs.jboss.org/author/display/AS71/EJB+invocations+from+a+remote+client+using+JNDI

8 comentários:

Bruno Serqueira disse...

Olá,
Muito bacana seu tutorial , porém
mesmo seguindo todos os passos me retornou um erro na hora de retornar o objeto via lookup

"javax.naming.NameNotFoundException: sistemaEspecialistaEAR/sistemaEspecialista/sistemaEspecialista!service.sistemaEspecialistaRemote -- service jboss.naming.context.java.sistemaEspecialistaEAR.sistemaEspecialista. "sistemaEspecialista!service.sistemaEspecialistaRemote"

Poderia me ajudar? obrigado.

Edgar Dantas disse...

Bruno,

O problema pode estar no nome que você usou, tente seguir o tutorial sem alterar os nomes e veja funciona.

Unknown disse...

Perfeito!!!
Apanhei por muito tempo rsrsr.
Thanks!!!

Unknown disse...

Perfeito!!!
Apanhei por muito tempo rsrsr.
Thanks!!!

Anônimo disse...

Eu estou querendo saber agora se podemos falar sobre as suas estatísticas de sites - o volume de pesquisa, etc, eu estou tentando sites eu posso comprar através adspace - deixe-me saber se podemos conversar sobre preços e outros enfeites. Cheers mate você está fazendo um ótimo trabalho embora.

Marcelo Honorato disse...

Amigo, segui seu tutorial à risca. No entanto ocorreu o seguinte erro:

Mar 23, 2013 2:21:55 AM org.jboss.ejb.client.EJBClient
INFO: JBoss EJB Client version 1.0.5.Final
Mar 23, 2013 2:21:56 AM org.xnio.Xnio
INFO: XNIO Version 3.0.3.GA
Mar 23, 2013 2:21:56 AM org.xnio.nio.NioXnio
INFO: XNIO NIO Implementation Version 3.0.3.GA
Mar 23, 2013 2:21:56 AM org.jboss.remoting3.EndpointImpl
INFO: JBoss Remoting version 3.2.3.GA
Mar 23, 2013 2:21:57 AM org.jboss.ejb.client.remoting.VersionReceiver handleMessage
INFO: Received server version 1 and marshalling strategies [river]
Mar 23, 2013 2:21:57 AM org.jboss.ejb.client.remoting.RemotingConnectionEJBReceiver associate
INFO: Successful version handshake completed for receiver context EJBReceiverContext{clientContext=org.jboss.ejb.client.EJBClientContext@18023558, receiver=Remoting connection EJB receiver [connection=Remoting connection ,channel=jboss.ejb,nodename=honoratonote]} on channel Channel ID f29b4b3f (outbound) of Remoting connection 2e56553e to localhost/127.0.0.1:4447
Mar 23, 2013 2:21:57 AM org.jboss.ejb.client.remoting.ChannelAssociation$ResponseReceiver handleMessage
WARN: Unsupported message received with header 0xffffffff
Exception in thread "main" java.lang.IllegalStateException: No EJB receiver available for handling [appName:HelloWorldEAR,modulename:HelloWorld,distinctname:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@4f25445a
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:584)
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:119)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:181)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:136)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:121)
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:104)
at com.sun.proxy.$Proxy0.sayHello(Unknown Source)
at HelloWorldClient.main(HelloWorldClient.java:14)

Alguma ideia?

Marcelo Honorato disse...

Amigo, segui seu tutorial à risca. No entanto ocorreu o seguinte erro:

Mar 23, 2013 2:21:55 AM org.jboss.ejb.client.EJBClient
INFO: JBoss EJB Client version 1.0.5.Final
Mar 23, 2013 2:21:56 AM org.xnio.Xnio
INFO: XNIO Version 3.0.3.GA
Mar 23, 2013 2:21:56 AM org.xnio.nio.NioXnio
INFO: XNIO NIO Implementation Version 3.0.3.GA
Mar 23, 2013 2:21:56 AM org.jboss.remoting3.EndpointImpl
INFO: JBoss Remoting version 3.2.3.GA
Mar 23, 2013 2:21:57 AM org.jboss.ejb.client.remoting.VersionReceiver handleMessage
INFO: Received server version 1 and marshalling strategies [river]
Mar 23, 2013 2:21:57 AM org.jboss.ejb.client.remoting.RemotingConnectionEJBReceiver associate
INFO: Successful version handshake completed for receiver context EJBReceiverContext{clientContext=org.jboss.ejb.client.EJBClientContext@18023558, receiver=Remoting connection EJB receiver [connection=Remoting connection ,channel=jboss.ejb,nodename=honoratonote]} on channel Channel ID f29b4b3f (outbound) of Remoting connection 2e56553e to localhost/127.0.0.1:4447
Mar 23, 2013 2:21:57 AM org.jboss.ejb.client.remoting.ChannelAssociation$ResponseReceiver handleMessage
WARN: Unsupported message received with header 0xffffffff
Exception in thread "main" java.lang.IllegalStateException: No EJB receiver available for handling [appName:HelloWorldEAR,modulename:HelloWorld,distinctname:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@4f25445a
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:584)
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:119)
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:181)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:136)
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:121)
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:104)
at com.sun.proxy.$Proxy0.sayHello(Unknown Source)
at HelloWorldClient.main(HelloWorldClient.java:14)

Alguma ideia?

Edgar Dantas disse...

Marcelo,

O problema pode ter relação com os nomes, veja o que vem logo após java:jboss/exported na janela do console, então reveja o passo 7.5