ejb3.1 @Startup .. @Singleton .. @PostConstruct читает из XML объекты - PullRequest
1 голос
/ 07 июня 2011

Мне нужно инициализировать набор статических строковых значений, хранящихся в файлах XML [я знаю, что это противоречит спецификации EJB], как показано ниже, поскольку общая идея заключается в том, чтобы не создавать хардкор в EJB-информации JNDI

Utils.xml 
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="jndidb">java:jdbc/MYSQLDB10</entry>
<entry key="jndimdbque">java:jms/QueueName/remote</entry>
<entry key="jndi1">DBConnections/remote</entry>
<entry key="jndi2">AddressBean/remote</entry>
</properties>

Загрузка кода запуска ejbserver выглядит следующим образом ... inpstrem = clds.getClassLoaders (flename) Считывает Util.xml и сохраняет его в паре значений ключа Hashtable ....

package com.ejb.utils;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.ConcurrencyManagement;
import javax.ejb.Singleton;
import javax.ejb.Startup;

@Singleton
@Startup
public class StartupUtils  {

private final String INITFILENAME      = "/System/Config/Utils.xml";  
private static Hashtable HTINITFLENME=null,HTERRINITFLENME=null,HTCMMNFLENME=null;

public StartupUtils() {
    HTINITFLENME = new Hashtable();
    HTERRINITFLENME = new Hashtable();
}

public void printAll(Hashtable htcmmnflenme){
    Enumeration ENUMK = null, VALS = null;
    String KEY = "", VALUE = "";
    ENUMK = htcmmnflenme.keys();         
    while (ENUMK.hasMoreElements()) {
        KEY = null;VALUE = null;
        KEY = (ENUMK.nextElement().toString().trim());
        VALUE = htcmmnflenme.get(KEY).toString().trim();
        InitLogDisplay(KEY +  " :::: " + VALUE);
    }
}

public static  void InitLogDisplay(String Datadisplay){
   System.out.println(Datadisplay); 
}

public Hashtable getDataProp(String flename){
    Map htData = null;
    InputStream inpstrem = null;        
    ClassLoaders clds = null;
    Enumeration enumk = null, vals = null;
    String key = "", value = "";
    Properties props = null;
    Hashtable htx = null;       
    try {
        clds = new ClassLoaders();          
        inpstrem = clds.getClassLoaders(flename);           
        props = new Properties();
        props.loadFromXML(inpstrem);                    
        enumk = props.keys();
        vals = props.elements();
        htData = new HashMap();
        htData = new TreeMap();
        while (enumk.hasMoreElements()) {
              key = (enumk.nextElement().toString().trim());
          value = (vals.nextElement().toString().trim());
          htData.put(key,value);                
        }
        clds = null;
        props = null;
        inpstrem.close();
        } catch (Exception e) {
        e.printStackTrace();
        }finally{
         key = ""; value = "";
         enumk = null;vals = null;
         clds=null;
         props=null;
         }
        htx = new Hashtable();
        htx.putAll(htData);
        return htx;
    }


    public void setUtilsPropDetails(){
        HTINITFLENME = getDataProp(INITFILENAME);
        this.printAll(HTINITFLENME);
    }

    public static Hashtable getUtilsPropDetails(){
        return HTINITFLENME;
    }

    @PostConstruct  
    public void startOnstartup(){       
      this.setUtilsPropDetails();
          this.printAll();          
    }

    @PreDestroy
    public void startOnshutdown(){      
        try {
            this.finalize();
        } catch (Throwable e) {
           e.printStackTrace();
        }       
    }   
}

При запуске сервера EJB "this.printAll (HTINITFLENME);"печатает значения ключа файла XML, однако если внешний вызов сделан через любой другой EJB-компонент в метод "getUtilsPropDetails ()", не возвращает значения ключа ....

Я делаю что-то не так ??????

1 Ответ

2 голосов
/ 07 июня 2011

Рассматривали ли вы использование дескриптора развертывания и чтобы контейнер выполнял эту работу за вас?

Есть, конечно, <resource-ref>, <resource-env-ref>, <ejb-ref> и <env-entry> элементы для внешней настройкикакие вещи должны быть доступны бину для поиска.Например:

<resource-ref>
    <res-ref-name>db</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <mapped-name>java:jdbc/MYSQLDB10</mapped-name>
</resource-ref>

Я не уверен, как ваш поставщик обрабатывает mapped-name (этот конкретный элемент зависит от поставщика), но будет эквивалентный синтаксис для указания требуемого источника данных.

Синглтон может затем искать java:comp/env/db и возвращать источник данных другим EJB-компонентам.

Если вы находитесь на совместимом сервере Java EE 6, вы можете изменить имя на <res-ref-name>java:app/db</res-ref-name>, а затем любоеприложение может искать источник данных без необходимости получать его из синглтона.Глобальный JNDI является стандартной функцией Java EE 6 и предназначен именно для этого.

Вы можете поместить эти элементы в ejb-jar.xml, web.xml или application.xml.Помещение их в application.xml сделает одну запись доступной для всего приложения и предоставит вам одно место для поддержки всего.

Глобальные ресурсы также можно вводить с помощью:

@Resource(name="java:app/db")
DataSource dataSource;

Еслипо какой-то причине вы не хотели использовать их, по крайней мере вы могли бы использовать элемент <env-entry> для вывода строк.

EDIT

См. этот другой ответ для гораздо большегополное описание JNDI, поскольку оно относится к простым типам .Это, конечно, можно сделать, когда пары имя / значение не являются простыми типами, а вместо этого являются более сложными типами, такими как DataSource и Topic или Queue

Например:

  <resource-ref>
    <res-ref-name>myDataSource</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
  </resource-ref>
  <resource-ref>
    <res-ref-name>myJmsConnectionFactory</res-ref-name>
    <res-type>javax.jms.ConnectionFactory</res-type>
  </resource-ref>
  <resource-ref>
    <res-ref-name>myQueueCF</res-ref-name>
    <res-type>javax.jms.QueueConnectionFactory</res-type>
  </resource-ref>
  <resource-ref>
    <res-ref-name>myTopicCF</res-ref-name>
    <res-type>javax.jms.TopicConnectionFactory</res-type>
  </resource-ref>
  <resource-env-ref>
    <resource-env-ref-name>myQueue</resource-env-ref-name>
    <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
  </resource-env-ref>
  <resource-env-ref>
    <resource-env-ref-name>myTopic</resource-env-ref-name>
    <resource-env-ref-type>javax.jms.Topic</resource-env-ref-type>
  </resource-env-ref>
  <persistence-context-ref>
    <persistence-context-ref-name>myEntityManager</persistence-context-ref-name>
    <persistence-unit-name>test-unit</persistence-unit-name>
  </persistence-context-ref>
  <persistence-unit-ref>
    <persistence-unit-ref-name>myEntityManagerFactory</persistence-unit-ref-name>
    <persistence-unit-name>test-unit</persistence-unit-name>
  </persistence-unit-ref>

См. JNDI и простой тип ответ для синтаксиса вида и инъекции.

Я вижу имя и тип, но где значение?

Настройка этих фактических вещейисторически упоминаемые имена делались в отдельном дескрипторе развертывания, специфичном для поставщика, например sun-ejb-jar.xml или openejb-jar.xml или в соответствии с требованиями поставщика.Дескриптор для конкретного поставщика и стандартный дескриптор ejb-jar.xml обеспечивают гарантированную мобильность приложений.

Файл ejb-jar.xml предлагает только стандартные вещи, такие как возможность определить, какие типы ресурсов требуется приложению, икакие имена приложение выбрало для ссылки на эти ресурсы.Специфичный для поставщика дескриптор заполняет пробел в сопоставлении этих имен с реальными ресурсами в системе.

Начиная с EJB 3.0 / Java EE 5 мы в группах спецификаций немного отошли от этого и добавили элемент <mapped-name>который может использоваться в ejb-jar.xml с любой из приведенных выше ссылок, таких как <resource-ref>, на имя конкретного поставщика.Отображаемое имя никогда не будет переносимым , и его значение всегда будет зависеть от поставщика - если оно вообще поддерживается.

Тем не менее, <mapped-name> может быть удобен для избежания необходимости в отдельном файле, специфичном для поставщика, и достигает цели извлечения имен, специфичных для поставщика, из кода.В конце концов, ejb-jar.xml можно редактировать при переходе от одного поставщика к другому, и для многих людей этого достаточно.

...