Руководство по интеграции для Spring и EJB

Руководство по интеграции для Spring и EJB

1. обзор

В этой статье мы покажем, какintegrate Spring and remote Enterprise Java Beans (EJB).

Для этого мы создадим несколько EJB-компонентов и необходимые удаленные интерфейсы, а затем запустим их внутри контейнера JEE. После этого мы запустим наше приложение Spring и, используя удаленные интерфейсы, создадим экземпляры наших bean-компонентов, чтобы они могли выполнять удаленные вызовы.

Если есть какие-либо сомнения относительно того, что такое EJB-компоненты и как они работают, мы уже опубликовали вводную статью по темеhere.

2. Настройка EJB

Нам нужно будет создать наши удаленные интерфейсы и наши реализации EJB. Чтобы их можно было использовать, нам также понадобится контейнер для хранения и управления фасолью.

2.1. Удаленные интерфейсы EJB

Давайте начнем с определения двух очень простых компонентов - одного без состояния и одного с сохранением состояния.

Начнем с их интерфейсов:

@Remote
public interface HelloStatefulWorld {
    int howManyTimes();
    String getHelloWorld();
}
@Remote
public interface HelloStatelessWorld {
    String getHelloWorld();
}

2.2. Реализация EJB

Теперь давайте реализуем наши удаленные интерфейсы EJB:

@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!";
    }
}

Если компоненты с сохранением состояния и без состояния кажутся вам незнакомыми, может пригодитьсяthis intro article.

2.3. Контейнер EJB

Мы можем запустить наш код в любом JEE-контейнере, но для практических целей мы будем использовать Wildfly и плагинcargo Maven, чтобы сделать за нас тяжелую работу:


    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. Запуск EJB

С этими настройками мы можем запустить контейнер непосредственно из командной строки Maven:

mvn clean package cargo:run -Pwildfly-standalone

Теперь у нас есть рабочий экземпляр Wildfly, на котором размещены наши бины. Мы можем подтвердить это по строкам журнала:

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. Настройка весны

Теперь, когда у нас запущен и работает наш JEE-контейнер и развернуты наши EJB-компоненты, мы можем запустить наше Spring-приложение. Мы будем использоватьspring-boot-web, чтобы упростить тестирование вручную, но это не обязательно для удаленного вызова.

3.1. Maven Зависимости

Чтобы иметь возможность подключаться к удаленным EJB-компонентам, нам понадобится библиотекаWildfly EJB Client и наш удаленный интерфейс:


    org.wildfly
    wildfly-ejb-client-bom
    10.1.0.Final
    pom


    com.example.spring.ejb
    ejb-remote-for-spring
    1.0.1
    ejb

Последнюю версиюwildfly-ejb-client-bom можно найтиhere.

3.2. Контекст стратегии именования

С этими зависимостями в пути к классам мы можемinstantiate a javax.naming.Context to do the lookup of our remote beans. Мы создадим его как Spring Bean, чтобы мы могли автоматически подключать его, когда нам это нужно:

@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);
}

Свойства необходимыinform both the remote URL and the naming strategy context.

3.3. Шаблон JNDI

Прежде чем мы сможем связать наши удаленные bean-компоненты внутри контейнера Spring, нам нужно знать, как с ними связаться. Для этого мы будем использовать их привязки JNDI. Давайте посмотрим на стандартный шаблон для этих привязок:

${appName}/${moduleName}/${distinctName}/${beanName}!${viewClassName}

Имейте в виду, чтоsince 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. Подробности можно найти вEJB Intro article на случай, если что-то покажется странным.

Мы будем использовать этот шаблон для привязки наших удаленных bean-компонентов к нашим Spring.

3.4. Создание нашей весенней фасоли

To reach our EJBs, we’ll use the aforementioned JNDI. Помните строки журнала, которые мы использовали для проверки, были ли развернуты наши корпоративные компоненты?

Теперь мы увидим, что эта информация используется:

@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, иначе контекст не сможет достичь удаленного EJB и создать необходимую базовую инфраструктуру.

Имейте в виду, что методlookup изContext выдастNamingException, если он не найдет требуемый bean-компонент.

4. интеграция

Когда все на месте, мы можемinject our beans in a controller, чтобы проверить правильность подключения:

@RestController
public class HomeEndpoint {

    // ...

    @GetMapping("/stateless")
    public String getStateless() {
        return helloStatelessWorld.getHelloWorld();
    }

    @GetMapping("/stateful")
    public String getStateful() {
        return helloStatefulWorld.getHelloWorld()
          + " called " + helloStatefulWorld.howManyTimes() + " times";
    }
}

Давайте запустим наш Spring сервер и проверим журналы. Мы увидим следующую строку, указывающую, что все в порядке:

EJBCLIENT000013: Successful version handshake completed

Теперь давайте протестируем наш bean-компонент без сохранения состояния. Мы можем попробовать некоторые командыcurl, чтобы убедиться, что они работают должным образом:

curl http://localhost:8081/stateless
Hello Stateless World!

И давайте проверим наш статусный:

curl http://localhost:8081/stateful
Hello Stateful World called 1 times

curl http://localhost:8081/stateful
Hello Stateful World called 2 times

5. Заключение

В этой статье мы узнали, как интегрировать Spring в EJB и делать удаленные вызовы в контейнер JEE. Мы создали два удаленных интерфейса EJB и смогли прозрачно вызывать те, которые используют Spring Beans.

Несмотря на широкое распространение Spring, EJB-компоненты по-прежнему популярны в корпоративных средах, и в этом быстром примере мы показали, что можно использовать как распределенные преимущества JavaEE, так и простоту использования приложений Spring.

Как всегда, код можно найтиover on GitHub.