Можно ли использовать @Resource для внедрения примитивов в EJB3.0? - PullRequest
10 голосов
/ 16 июня 2011

Используя Glassfish, я могу настроить строковую запись jndi:

JNDI name: "com/xyzcompany/echo/EchoServiceBean/viewName"
Factory Class: org.glassfish.resources.custom.factory.PrimitivesAndStringFactory
Properties: value="Testing123"

Я могу затем вставить эту сконфигурированную строку контейнера в мой EJB:

    @Resource(lookup = "com/xyzcompany/echo/EchoServiceBean/viewName")
    String viewName;

Внутренний поиск = отображается внутреннесделать InitialContext.lookup (...).Тем не менее, это использует ejb3.1, но, к сожалению, моя среда разработки только ejb3.0.

Я думаю, я пытаюсь выяснить, есть ли способ использовать @Resource (name =) или @Resource (mappedName =) сделать что-то подобное?Кажется, что имя = зависит от приложения, поэтому я должен каким-то образом сопоставить относительное имя с глобальным именем JNDI, но я не могу понять, какая аннотация делает сопоставление.

Спасибо!

1 Ответ

35 голосов
/ 17 июня 2011

Все 8 примитивных оболочек и String поддерживаются типами @Resource и доступны для поиска или внедрения через объявление их в стандартном файле ejb-jar.xml.

Объявление пар значения значения (и типа)

Это делается с помощью элемента <env-entry> xml в дескрипторе развертывания.

В EJB 3.0 вы должны делать это для каждого компонента, который хочет ссылаться на одни и те же пары имя / значение.Это связано с тем, что EJB изначально проектировался не так, как сервлеты, и каждый EJB буквально получает свое собственное пространство имен JNDI java:comp/env, тогда как все сервлеты в одном модуле совместно используют один и тот же java:comp/env.

<ejb-jar>
  <enterprise-beans>
    <session>
      <ejb-name>MySessionBean</ejb-name>
      <env-entry>
        <env-entry-name>myBoolean</env-entry-name>
        <env-entry-type>java.lang.Boolean</env-entry-type>
        <env-entry-value>true</env-entry-value>
      </env-entry>
      <env-entry>
        <env-entry-name>myString</env-entry-name>
        <env-entry-type>java.lang.String</env-entry-type>
        <env-entry-value>hello world</env-entry-value>
      </env-entry>
      <env-entry>
        <env-entry-name>myDouble</env-entry-name>
        <env-entry-type>java.lang.Double</env-entry-type>
        <env-entry-value>1.1</env-entry-value>
      </env-entry>
      <env-entry>
        <env-entry-name>myLong</env-entry-name>
        <env-entry-type>java.lang.Long</env-entry-type>
        <env-entry-value>12345678</env-entry-value>
      </env-entry>
      <env-entry>
        <env-entry-name>myFloat</env-entry-name>
        <env-entry-type>java.lang.Float</env-entry-type>
        <env-entry-value>1.3</env-entry-value>
      </env-entry>
      <env-entry>
        <env-entry-name>myInteger</env-entry-name>
        <env-entry-type>java.lang.Integer</env-entry-type>
        <env-entry-value>1024</env-entry-value>
      </env-entry>
      <env-entry>
        <env-entry-name>myShort</env-entry-name>
        <env-entry-type>java.lang.Short</env-entry-type>
        <env-entry-value>42</env-entry-value>
      </env-entry>
      <env-entry>
        <env-entry-name>myByte</env-entry-name>
        <env-entry-type>java.lang.Byte</env-entry-type>
        <env-entry-value>128</env-entry-value>
      </env-entry>
      <env-entry>
        <env-entry-name>myCharacter</env-entry-name>
        <env-entry-type>java.lang.Character</env-entry-type>
        <env-entry-value>D</env-entry-value>
      </env-entry>
    </session>
  </enterprise-beans>
</ejb-jar>

Для читателей.повезло, что вы используете EJB 3.1, вы можете использовать глобальный JNDI и объявить их в application.xml и искать их откуда угодно с помощью java:app/myString.Функция, которую многие поставщики имели в течение многих лет, теперь окончательно стала стандартной для Java EE 6. Внедрение этих записей также возможно с помощью @Resource(lookup="java:app/myString")

Также в Java EE 6 появилась новая поддержка двух дополнительных env-entry-typeтипы, java.lang.Class и любые перечисления.Например:

<env-entry>
  <env-entry-name>myPreferredListImpl</env-entry-name>
  <env-entry-type>java.lang.Class</env-entry-type>
  <env-entry-value>java.util.ArrayList</env-entry-value>
</env-entry>
<env-entry>
  <env-entry-name>myBillingStragety</env-entry-name>
  <env-entry-type>java.lang.Class</env-entry-type>
  <env-entry-value>org.superbiz.BiMonthly</env-entry-value>
</env-entry>
<env-entry>
  <env-entry-name>displayElapsedTimeAs</env-entry-name>
  <env-entry-type>java.util.concurrent.TimeUnit</env-entry-type>
  <env-entry-value>MINUTES</env-entry-value>
</env-entry>
<env-entry>
  <env-entry-name>myFavoriteColor</env-entry-name>
  <env-entry-type>org.superbiz.ColorEnum</env-entry-type>
  <env-entry-value>ORANGE</env-entry-value>
</env-entry>

Ссылка на них с помощью инъекции

Любое из вышеперечисленного может быть введено с помощью @Resource.Только не забудьте заполнить атрибут name, чтобы он соответствовал <env-entry-name>

@Stateless
public class MySessionBean implements MySessionLocal {

    @Resource(name="myString")
    private String striing;

    @Resource(name = "myDouble")
    private Double doouble;

    @Resource(name = "myLong")
    private Long loong;

    @Resource(name = "myName")
    private Float flooat;

    @Resource(name = "myInteger")
    private Integer inteeger;

    @Resource(name = "myShort")
    private Short shoort;

    @Resource(name = "myBoolean")
    private Boolean booolean;

    @Resource(name = "myByte")
    private Byte byyte;

    @Resource(name = "myCharacter")
    private Character chaaracter;

}

Ссылка на них с помощью JNDI

Эти имена также можно стандартно искать через javax.naming.InitialContext в частном и переносимом пространстве имен EJB java:comp/env.

@Stateless
public class MySessionBean implements MySessionLocal {

    @PostConstruct
    private void init() {

        try {
            final InitialContext initialContext = new InitialContext();// must use the no-arg constructor

            final String myString = (String) initialContext.lookup("java:comp/env/myString");
            final Boolean myBoolean = (Boolean) initialContext.lookup("java:comp/env/myBoolean");
            final Double myDouble = (Double) initialContext.lookup("java:comp/env/myDouble");
            final Long myLong = (Long) initialContext.lookup("java:comp/env/myLong");
            final Float myFloat = (Float) initialContext.lookup("java:comp/env/myFloat");
            final Integer myInteger = (Integer) initialContext.lookup("java:comp/env/myInteger");
            final Short myShort = (Short) initialContext.lookup("java:comp/env/myShort");
            final Byte myByte = (Byte) initialContext.lookup("java:comp/env/myByte");
            final Character myCharacter = (Character) initialContext.lookup("java:comp/env/myCharacter");
        } catch (NamingException e) {
            throw new EJBException(e);
        }
    }
}

Ссылка на них с помощью SessionContext

В EJB 3.0 в рамках усилий по упрощению мы добавили возможность использоватьjavax.ejb.SessionContext для поиска.По сути это то же самое, но содержит немного сахара.

  • префикс java:comp/env не требуется
  • не генерирует проверенное исключение (вместо этого генерируется EJBExceptionдля пропущенных имен)

Шаблоны Service Locator были популярны в 2003 году, поэтому мы решили добавить немного удобства в EJB API.

@Stateless
public class MySessionBean implements MySessionLocal {

    @Resource
    private SessionContext sessionContext;

    @PostConstruct
    private void init() {

        final String myString = (String) sessionContext.lookup("myString");
        final Boolean myBoolean = (Boolean) sessionContext.lookup("myBoolean");
        final Double myDouble = (Double) sessionContext.lookup("myDouble");
        final Long myLong = (Long) sessionContext.lookup("myLong");
        final Float myFloat = (Float) sessionContext.lookup("myFloat");
        final Integer myInteger = (Integer) sessionContext.lookup("myInteger");
        final Short myShort = (Short) sessionContext.lookup("myShort");
        final Byte myByte = (Byte) sessionContext.lookup("myByte");
        final Character myCharacter = (Character) sessionContext.lookup("myCharacter");
    }
}

Примечание на IntialContextзло

Кроме того, при включенной шляпе продавца я могу сказать вам, что под капотом можно найти немало медленной сантехники с помощью поиска SessionContext.

Когда вы это делаете'java:' ищет на InitialContext, вызов направляется на виртуальную машину, через кучу обручей, чтобы найти, кто может разрешить это имя, а затем, в конечном итоге, поставщику, которому придется искать состояние из потока, чтобы выяснить, кто спросили какое пространство имен они должны получить.Он делает это при каждом вызове независимо от того, какие свойства вы передаете в InitialContext и какой контекст инициализировал поставщик при его создании.«Java:» просто перепрыгивает через все это.Это довольно расстраивающая часть быть продавцом.Именно поэтому новый javax.ejb.embedded.EJBContainer API вообще нигде не использует InitialContext и просто ссылается на javax.naming.Context, который является реальным интерфейсом, а не конкретным "фабричным" классом с интенсивной и тупой сантехникой.

Выполнениевызов SessionContext должен быть намного быстрее, если поставщик сделал это правильно.По крайней мере, в OpenEJB все вышеперечисленное, включая ThreadLocal, пропускается, и вызов переходит прямо в пространство имен JNDI этого бина, которое уже подключено к SessionContext.

Еще один способ избежать издержек InitialContext - этопросто найдите java:comp/env один раз в @PostConstruct и сохраните полученный в результате объект Context и используйте его только.Тогда не добавляйте префиксы для поиска к java:comp/env/, а просто ищите имена, такие как myString и myInteger.Это будет быстрее, гарантировано.

...