ejb3.1 @Startup .. @Singleton .. @PostConstruct从XML中读取对象

时间:2011-06-07 08:34:06

标签: singleton startup ejb-3.1

我需要初始化一组存储在XML文件中的静态String值[我知道这违反了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启动代码的Onload如下... inpstrem = clds.getClassLoaders(flename)读取Util.xml并将其存储在Hashtable键值pare中....

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 个答案:

答案 0 :(得分:2)

您是否考虑过使用部署描述符并让容器为您工作?

当然有<resource-ref><resource-env-ref><ejb-ref><env-entry>元素来涵盖外部配置哪些内容应该可供bean查找。例如:

<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>

我不确定您的供应商如何处理映射名称(该特定元素是特定于供应商的),但是将有一个等效的语法来指定您想要的数据源。

然后,单例可以查找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>元素来外化字符串。

修改

有关JNDI as it pertains to simple types更全面的说明,请参阅此其他答案。这当然可以在名称/值对不是简单类型的情况下完成,而是更复杂的类型,如DataSourceTopicQueue

例如:

  <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 and simple types答案。

我看到名称和类型,但值是在哪里?

配置这些名称所引用的实际内容历来是在单独的供应商特定部署描述符中完成的,例如sun-ejb-jar.xmlopenejb-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可以在从一个供应商转移到另一个供应商时进行编辑,对于许多人来说也是如此。