Статьи

Имитация сеанса и объема запросов CDI в приложении J2SE

В настоящее время мы рассматриваем рефакторинг инфраструктуры Naked Objects для использования JSR-330 (внедрение зависимостей) и ориентированного на EE старшего брата, JSR-299 (CDI). Использование vanilla JSR-330 не вызывает затруднений, но в JSR-299 есть и некоторые приятные функции, которые мы хотели бы использовать (например, события и декораторы). Загвоздка? Голые объекты также должны прозрачно работать в средах J2SE.

Теперь JSR-299 (по крайней мере, эталонная реализация Weld) может работать на J2SE, но невозможно использовать bean-компоненты, аннотированные как @SessionScoped или @ RequestScoped … на самом деле это не удивительно, потому что нет HttpSession или HttpServletRequest для зацепить С другой стороны, по крайней мере, в инфраструктуре Naked Objects в контексте J2SE у нас есть возможность отобразить эти концепции на собственный внутренний жизненный цикл … например, для клиентского приложения пользователь всегда считается запущенным в одном долгом сеансе.

Как же тогда настроить контексты для этих областей и сделать их автоматически активными при работе в J2SE?

Сначала давайте посмотрим на код, который мы хотим запустить:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package org.nakedobjects.experiments.cdi;
 
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.event.Observes;
import org.jboss.weld.environment.se.bindings.Parameters;
import org.jboss.weld.environment.se.events.ContainerInitialized;
 
@RequestScoped
public class HelloWorld {
    public static void main(String[] args) {
        // bootstrap
        org.jboss.weld.environment.se.StartMain.main(new String[]{"JSR","299"});
    }
    public void printHello(@Observes ContainerInitialized event, @Parameters List<String> args) {
        System.out.println("Hello " + args);
        System.out.flush();
    }
}

Поскольку это бин CDI, нам нужен пустой META-INF / beans.xml.

Приведенный выше класс выведет «Hello [JSR, 299]», если он будет аннотирован как @ApplicationScoped , но не будет аннотирован как @RequestScoped . Поэтому нам нужно написать расширение. Это немного глупо, но работает:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package org.jboss.weld.manager; // required for visibility to BeanManagerImpl#getContexts()
 
import java.lang.annotation.Annotation;
 
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.spi.AfterDeploymentValidation;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.Extension;
 
import org.jboss.weld.context.AbstractThreadLocalMapContext;
import org.jboss.weld.context.beanstore.HashMapBeanStore;
 
public class WeldServletScopesSupportForSe implements Extension {
 
 public void afterDeployment(@Observes AfterDeploymentValidation event,
   BeanManager beanManager) {
 
  setContextActive(beanManager, SessionScoped.class);
  setContextActive(beanManager, RequestScoped.class);
 }
 
 private void setContextActive(BeanManager beanManager,
   Class<? extends Annotation> cls) {
  BeanManagerImpl beanManagerImpl = (BeanManagerImpl) beanManager;
  AbstractThreadLocalMapContext context = (AbstractThreadLocalMapContext) beanManagerImpl
    .getContexts().get(cls).get(0);
  context.setBeanStore(new HashMapBeanStore());
  context.setActive(true);
 }
}

Как и все расширения Weld, это необходимо зарегистрировать в META-INF / services , в данном случае в файле с именем javax.enterprise.inject.spi.Extension, содержащим полное имя класса.

Теперь, когда мы запустим приложение, будут настроены области сеанса и запроса, и сработает наш компонент HelloWorld.

Для разработчиков, пишущих приложения в Naked Objects, они должны будут включить зависимость от дополнительного модуля при развертывании клиента ( -t клиент или сервер на не-веб- сервере (скажем, -t сервер с удаленным взаимодействием на уровне сокетов). В последнем случае нам нужно будет включить некоторые смарты, чтобы выяснить, работаем ли мы в веб-приложении или нет, и настроить контексты только в том случае, если мы определим, что это не так (например, не удается найти классы javax.servlet в CLASSPATH.

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

1
svn co https://nakedobjects.svn.sourceforge.net/svnroot/nakedobjects/framework/trunk/experiments .

Ссылка: Моделирование объема сеанса и запроса CDI в приложении J2SE от нашего партнера JCG Дэна Хейвуда в блоге Дэна Хейвуда .

Статьи по Теме :