подключение к внедрению @EJB или @PersistenceContext в JAX -Модульные тесты RS

Мне нравится изучать JAX -RS и Jersey, но я столкнулся с препятствием, пытаясь протестировать простой ресурс, который требует внедрения DAO, что-то вроде этого:

@Stateless
@Path("simple")
public class SimpleResource {

    @PersistenceContext
    private EntityManager em;

// @GET, etc...

}

(Я перейду к более абстрактному шаблону DAO, но проблема та же, т. е. как внедрить @EJB DAO?)

В своих модульных тестах я использую встроенный сервер Jetty, который настраивает Джерси в своем web.xml, и я хотел бы подключиться к жизненному циклу ресурса, чтобы я мог внедрить фиктивный EntityManager, но я не нашел четкого ответа после долгих поисков. Вы можете помочь? Некоторые возможные направления, с которыми я столкнулся:

1 )Используйте поиск контекста JNDI в моем коде, чтобы получить компонент DAO, и зарегистрировать фиктивный объект в тестах.

Вместо @EJB или @PersistenceContext используйте что-то подобное в конструкторе ресурса:

  theDAO = (DAOImpl) new InitialContext().lookup("java:global/EJB/DAOImpl");

Однако это означает, что моя тестовая среда должна поддерживать JNDI, и выполнение этого в Jetty, вероятно, потребует некоторых усилий. Кроме того, он не использует метод чистой аннотации.

2 )Использовать метод впрыска.

Внедрить в метод, чтобы я мог установить экземпляр DAO post -, например,

@PersistenceContext(name = "persistence/pu00")
public void setPersistenceUnit00(final EntityManager em) {
    em00 = em;
}

ИЛИ

private MyEjbInterface myEjb;
@EJB(mappedName="ejb/MyEjb")
public void setMyEjb(MyEjb myEjb) {
    this.myEjb = myEjb;
}

Однако для этого мне нужен инстанцированный экземпляр Jersey -, например, SimpleResource. Как мне это получить?

3 )Используйте отражение.

Этакая самодельная инъекция, что-то вроде:

public static void setPrivateField(Class<? extends Object> instanceFieldClass, Object instance, String fieldName, Object fieldValue) {
    Field setId = instanceFieldClass.getDeclaredField(fieldName);
    setId.setAccessible(true);
    setId.set(instance, fieldValue);
}

Опять же, мне нужен инстанцированный экземпляр Jersey -.

4 )Используйте поставщика инъекций.

Я все еще не понимаю, как это работает, но похоже, что Джерси предоставляет средства для определения настраиваемых инъекционных аннотаций, например,

    @Provider
    public class EJBProvider implements InjectableProvider<EJB, Type> {

    public ComponentScope getScope() {
    return ComponentScope.Singleton;
    }

    public Injectable getInjectable(ComponentContext cc, EJB ejb, Type t) {
    if (!(t instanceof Class)) {
        return null;
    }
    try {
        Class c = (Class) t;
        Context ic = new InitialContext();
        final Object o = ic.lookup(c.getName());
        return new Injectable<Object>() {
        public Object getValue() {
            return o;
        }
        };
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
    }
}

Вариант с использованием вспомогательного класса:

Server server = new Server(8080);
Context root = new Context(server,"/",Context.SESSIONS);

ResourceConfig rc = new PackagesResourceConfig("edu.mit.senseable.livesingapore.platform.restws.representations");
rc.getSingletons().add(new SingletonTypeInjectableProvider<javax.ws.rs.core.Context, Myobj>(Myobj.class, new Myobj(12,13)){});

root.addServlet(new ServletHolder(new ServletContainer(rc)), "/");
server.start();

При таком использовании:

@Path("/helloworld")
public class HelloWorldResource {
    @Context Myobj myClass;
   ....
}

Это жизнеспособно для @EJB или @PersistenceContext?

5 )Расширить javax.ws.rs.core.Application.

Схематично об этом, но:

@javax.ws.rs.ApplicationPath("application")
public class InjectionApplication extends javax.ws.rs.core.Application {

  private Set<Object> singletons = new HashSet<Object>();
  private Set<Class<?>> classes = new HashSet<Class<?>>();

  public InjectionApplication() {
    // no instance is created, just class is listed
    classes.add(BookResource.class);
  }

  @Override
  public Set<Class<?>> getClasses() {
    return classes;
  }

  @Override
  public Set<Object> getSingletons() {
    return singletons;
  }
}

6 )Расширение контейнера сервлетов.

Старый стиль использования InjectableProvider? Выглядит сложнее:

public class ServletAdapter extends ServletContainer {

@Override
protected void configure(ServletConfig servletConfig, ResourceConfig rc, WebApplication wa) {
    super.configure(servletConfig, rc, wa);

    rc.getSingletons().add(new InjectableProvider<Resource, Type>() {

        public ComponentScope getScope() {
            return ComponentScope.Singleton;
        }

        public Injectable<Object> getInjectable(ComponentContext ic, Resource r, Type c) {
            final Holder value = new Holder();

                Context ctx = new InitialContext();
                try {
                    value.value = ctx.lookup(r.name());
                } catch (NamingException ex) {

                    value.value = ctx.lookup("java:comp/env/" + r.name());
                }

            return new Injectable<Object>() {
                public Object getValue() {
                    return value.value;
                }
            };
        }
    });
}
}  

7 )Используйте встроенный контейнер EJB.

Например,http://openejb.apache.org. Это довольно тяжело, и я ожидаю, что это будет грязно, чтобы работать. (На самом деле, то, что заставило меня пойти по маршруту «Jetty + Jersey», было ошибкой в ​​​​GlassFish Embedded, связанной с безопасностью входа в систему. Я также рассмотрел другие контейнеры приложений Java EE 6, такие как JBoss AS, но у каждого из них были проблемы во встроенном режиме с ограниченной поддержкой сообщества пользователей.)

8 )Используйте стороннюю -библиотеку IoC, такую ​​как Spring или Guice.

Spring, по-видимому, обычно используется для решения таких проблем (внедрение макетов при модульном тестировании ), но я хотел избежать изучения другого большого набора API -чистая Java EE была достаточно сложной задачей! Но я в игре, если это лучшее решение. Я еще не внимательно изучил Spring или Guice.

Вы успешно использовали что-то из этого? Любые другие решения, которые вам нравятся? Очень жду ваших советов по этому поводу. Заранее спасибо --матовый

14
задан Matthew Cornell 19 July 2012 в 13:52
поделиться