Guia de Integração para Spring e EJB
1. Visão geral
Neste artigo, mostraremos comointegrate Spring and remote Enterprise Java Beans (EJB).
Para fazer isso, criaremos alguns EJBs e as interfaces remotas necessárias e, em seguida, os executaremos dentro de um contêiner JEE. Depois disso, iniciaremos nosso aplicativo Spring e, usando as interfaces remotas, instanciaremos nossos beans para que possam executar chamadas remotas.
Se houver alguma dúvida sobre o que são ou como funcionam os EJBs, já publicamos um artigo introdutório sobre o temahere.
2. Configuração EJB
Precisamos criar nossas interfaces remotas e nossas implementações EJB. Para torná-los utilizáveis, também precisaremos de um contêiner para armazenar e gerenciar os grãos.
2.1. Interfaces remotas EJB
Vamos começar definindo dois beans muito simples - um sem estado e outro com estado.
Começaremos com suas interfaces:
@Remote
public interface HelloStatefulWorld {
int howManyTimes();
String getHelloWorld();
}
@Remote
public interface HelloStatelessWorld {
String getHelloWorld();
}
2.2. Implementação EJB
Agora, vamos implementar nossas interfaces EJB remotas:
@Stateful(name = "HelloStatefulWorld")
public class HelloStatefulWorldBean implements HelloStatefulWorld {
private int howManyTimes = 0;
public int howManyTimes() {
return howManyTimes;
}
public String getHelloWorld() {
howManyTimes++;
return "Hello Stateful World";
}
}
@Stateless(name = "HelloStatelessWorld")
public class HelloStatelessWorldBean implements HelloStatelessWorld {
public String getHelloWorld() {
return "Hello Stateless World!";
}
}
Se os beans com e sem estado parecerem desconhecidos,this intro article pode ser útil.
2.3. Contêiner EJB
Podemos executar nosso código em qualquer contêiner JEE, mas para fins práticos, usaremos Wildfly e o plug-incargo Maven para fazer o trabalho pesado para nós:
org.codehaus.cargo
cargo-maven2-plugin
1.6.1
wildfly10x
http://download.jboss.org/wildfly/10.1.0.Final/wildfly-10.1.0.Final.zip
127.0.0.1
standalone-full
9990
testUser:admin1234!
2.4. Executando os EJBs
Com estes configurados, podemos executar o contêiner diretamente da linha de comando do Maven:
mvn clean package cargo:run -Pwildfly-standalone
Agora temos uma instância de trabalho do Wildfly hospedando nossos beans. Podemos confirmar isso pelas linhas de log:
java:global/ejb-remote-for-spring/HelloStatefulWorld!com.example.ejb.tutorial.HelloStatefulWorld
java:app/ejb-remote-for-spring/HelloStatefulWorld!com.example.ejb.tutorial.HelloStatefulWorld
java:module/HelloStatefulWorld!com.example.ejb.tutorial.HelloStatefulWorld
java:jboss/exported/ejb-remote-for-spring/HelloStatefulWorld!com.example.ejb.tutorial.HelloStatefulWorld
java:global/ejb-remote-for-spring/HelloStatefulWorld
java:app/ejb-remote-for-spring/HelloStatefulWorld
java:module/HelloStatefulWorld
java:global/ejb-remote-for-spring/HelloStatelessWorld!com.example.ejb.tutorial.HelloStatelessWorld
java:app/ejb-remote-for-spring/HelloStatelessWorld!com.example.ejb.tutorial.HelloStatelessWorld
java:module/HelloStatelessWorld!com.example.ejb.tutorial.HelloStatelessWorld
java:jboss/exported/ejb-remote-for-spring/HelloStatelessWorld!com.example.ejb.tutorial.HelloStatelessWorld
java:global/ejb-remote-for-spring/HelloStatelessWorld
java:app/ejb-remote-for-spring/HelloStatelessWorld
java:module/HelloStatelessWorld
3. Configuração da Primavera
Agora que temos nosso contêiner JEE em funcionamento e nossos EJBs implantados, podemos iniciar nosso aplicativo Spring. Usaremosspring-boot-web para facilitar o teste manualmente, mas não é obrigatório para a chamada remota.
3.1. Dependências do Maven
Para poder se conectar aos EJBs remotos, precisaremos da bibliotecaWildfly EJB Client e de nossa interface remota:
org.wildfly
wildfly-ejb-client-bom
10.1.0.Final
pom
com.example.spring.ejb
ejb-remote-for-spring
1.0.1
ejb
A última versão dewildfly-ejb-client-bom pode ser encontradahere.
3.2. Contexto da Estratégia de Nomenclatura
Com essas dependências no caminho de classe, podemosinstantiate a javax.naming.Context to do the lookup of our remote beans. Vamos criar isso como um Spring Bean para que possamos fazer o autowire quando precisarmos:
@Bean
public Context context() throws NamingException {
Properties jndiProps = new Properties();
jndiProps.put("java.naming.factory.initial",
"org.jboss.naming.remote.client.InitialContextFactory");
jndiProps.put("jboss.naming.client.ejb.context", true);
jndiProps.put("java.naming.provider.url",
"http-remoting://localhost:8080");
return new InitialContext(jndiProps);
}
As propriedades são necessárias parainform both the remote URL and the naming strategy context.
3.3. Padrão JNDI
Antes de conectarmos nossos beans remotos dentro do contêiner Spring, precisamos saber como alcançá-los. Para isso, usaremos suas ligações JNDI. Vamos ver o padrão padrão para essas ligações:
${appName}/${moduleName}/${distinctName}/${beanName}!${viewClassName}
Lembre-se de quesince we deployed a simple jar instead of an ear and didn’t explicitly set up a name, we don’t have an appName and a distinctName. Existem mais detalhes em nossoEJB Intro article caso algo pareça estranho.
Usaremos esse padrão para vincular nossos beans remotos aos do Spring.
3.4. Construindo nosso Spring Beans
To reach our EJBs, we’ll use the aforementioned JNDI. Lembra das linhas de log que usamos para verificar se nossos enterprise beans foram implantados?
Veremos essas informações em uso agora:
@Bean
public HelloStatelessWorld helloStatelessWorld(Context context)
throws NamingException {
return (HelloStatelessWorld)
context.lookup(this.getFullName(HelloStatelessWorld.class));
}
@Bean
public HelloStatefulWorld helloStatefulWorld(Context context)
throws NamingException {
return (HelloStatefulWorld)
context.lookup(this.getFullName(HelloStatefulWorld.class));
}
private String getFullName(Class classType) {
String moduleName = "ejb-remote-for-spring/";
String beanName = classType.getSimpleName();
String viewClassName = classType.getName();
return moduleName + beanName + "!" + viewClassName;
}
We need to be very careful about the correct full JNDI binding, ou o contexto não será capaz de alcançar o EJB remoto e criar a infraestrutura subjacente necessária.
Tenha em mente que o métodolookup deContext lançará umNamingException caso não encontre o bean que você está solicitando.
4. Integração
Com tudo no lugar, podemosinject our beans in a controller, para que possamos testar se a fiação está correta:
@RestController
public class HomeEndpoint {
// ...
@GetMapping("/stateless")
public String getStateless() {
return helloStatelessWorld.getHelloWorld();
}
@GetMapping("/stateful")
public String getStateful() {
return helloStatefulWorld.getHelloWorld()
+ " called " + helloStatefulWorld.howManyTimes() + " times";
}
}
Vamos iniciar nosso servidor Spring e verificar alguns logs. Veremos a seguinte linha, indicando que está tudo bem:
EJBCLIENT000013: Successful version handshake completed
Agora, vamos testar nosso bean sem estado. Podemos tentar alguns comandoscurl para verificar se eles estão operando conforme o esperado:
curl http://localhost:8081/stateless
Hello Stateless World!
E vamos verificar nosso estado:
curl http://localhost:8081/stateful
Hello Stateful World called 1 times
curl http://localhost:8081/stateful
Hello Stateful World called 2 times
5. Conclusão
Neste artigo, aprendemos como integrar o Spring ao EJB e fazer chamadas remotas para o contêiner JEE. Criamos duas interfaces EJB remotas e conseguimos chamar os usuários do Spring Beans de maneira transparente.
Mesmo que o Spring seja amplamente adotado, os EJBs ainda são populares em ambientes empresariais e, neste exemplo rápido, mostramos que é possível fazer uso dos ganhos distribuídos do JavaEE e da facilidade de uso dos aplicativos Spring.
Como sempre, o código pode ser encontradoover on GitHub.