技术开发 频道

多线程、多平台环境中的跟踪

  现在您将创建客户机将要调用的 EJB 组件。它们将做一些非常有限的处理。第一个 bean 将基于一个随机数做出是否调用第二个 bean 的选择。因而,其中一些线程将调用第二个 bean,而有些却不会这样。这样将会给跟踪输出添加一些变化,从而说明这种技术的强大能力。

  要做的第一件事情是在一个系统属性中设置日志记录器。设置方法将因为用于部署 EJB 组件的服务器不同而异。我选择了一个名为 log4j.prop 的设置;这个设置指向一个包含此设置的文件。这对于您正在创建的两个 EJB 组件都是一样的。

  清单 5 包含了第一个示例 EJB 组件。

  注意这些清单是不完整的:我删除了所有的空方法( ejbRemove() ,等等)。显然,您需要那些方法才能执行代码,但是这里列出它们没有意义。

  清单 5. log1Bean

1 package demo.logger.sample;
2 /**
3 * Bean implementation class for Enterprise Bean: log1
4 */
5 import java.rmi.RemoteException;
6 import java.util.Properties;
7 import java.util.Random;
8 import javax.naming.InitialContext;
9 import javax.rmi.PortableRemoteObject;
10 import org.apache.log4j.Logger;
11 import org.apache.log4j.PropertyConfigurator;
12 public class log1Bean implements javax.ejb.SessionBean {
13    private static Logger logger = Logger.getLogger(log1Bean.class);
14    private static String ejbHomeLocation = "ejb/log2Home";
15    private javax.ejb.SessionContext mySessionCtx;
16   
17    /**
18     * ejbCreate
19     */
20    public void ejbCreate() throws javax.ejb.CreateException {
21       //
22       //pickup the location of the property file as a system property
23       //
24       Properties sp = System.getProperties();
25       String propFile = sp.getProperty("log4j.props");
26       PropertyConfigurator.configure(propFile);
27       logger.info("Logger started for log1Bean, bean created");
28       String ejbHomeLocation = sp.getProperty("log2.jndi");
29    }
30   
31   
32    public boolean doTest(int id)
33    {
34    //this method takes the id of the thread that called it to continue use in its own logging
35    //it will roll a random number, and choose to lookup another EJB or not
36        boolean result = true;
37        logger.info("[" +id +"]"+ " Started doTest method in log1Bean");
38       
39        Random rand = new Random();
40        int choice = rand.nextInt(10);
41        logger.debug("[" +id +"]"+ " Random choice is " + choice);
42        if (choice <=5){
43           //
44           //link to ejb2
45           //
46       try{
47         
48          InitialContext ic = new InitialContext();
49          Object or = ic.lookup(ejbHomeLocation);
50          if (or != null) {
51          // Narrow the return object to the Home class type
52          log2Home home =
53               (log2Home)PortableRemoteObject.narrow(or,
54                  log2Home.class);
55          // Create an EJB object instance using the home interface.
56          try{
57             log2 lb2 = home.create();
58             // Invoke the method
59                                  if (lb2.doTest(id) == true){
60                logger.info("[" + id +"]"+ " Execution ran successfully");         }
61          }catch(RemoteException re){
62             logger.fatal("[" +id + "]" + " Failure to create remote EJB " + re);            
63          }
64          }
65       }catch(Exception e){
66          logger.fatal("[" +id +"]"+ " Failure when looking up log2Bean " + e);
67          e.printStackTrace();
68                   }
69        }else{
70          //
71           //state that you've gone nowhere and return
72           //
73           logger.info("[" +id +"]"+ " Path ends at Log1Bean");
74        }
75       
76       
77       return result;
78    }
79 }
80

  清单 6 包含了第二个 bean。它与第一个非常类似;它只是返回已经到达某次给定的执行过程的结尾这个事实。

  清单 6. log2Bean

1 package demo.logger.sample;
2 import java.util.Properties;
3 import org.apache.log4j.Logger;
4 import org.apache.log4j.PropertyConfigurator;
5 /**
6 * Bean implementation class for Enterprise Bean: log2
7 */
8 public class log2Bean implements javax.ejb.SessionBean {
9    private static Logger logger = Logger.getLogger(log1Bean.class);
10    private javax.ejb.SessionContext mySessionCtx;
11    /**
12     * ejbCreate
13     */
14    public void ejbCreate() throws javax.ejb.CreateException {
15       //
16       //pickup the location of the property file as a system property
17       //
18       Properties sp = System.getProperties();
19       String propFile = sp.getProperty("log4jejb2.props");
20       PropertyConfigurator.configure(propFile);
21       logger.info("Logger started for log2Bean, bean created");
22       
23    }
24       
25    public boolean doTest(int id)
26    {
27    //this method takes the id of the thread that called it to continue use in its own logging
28    //it will roll a random number, and choose to lookup another EJB or not
29       boolean result = true;
30       logger.info("[" +id +"]"+ " Started doTest method in log2Bean");
31        logger.info("[" +id +"]"+ " Path ends in Log2Bean");
32       
33       
34       return result;
35    }
36 }
37

  第一个 bean log1Bean 就它应该简单地返回还是连接到第二个 bean 做出随机的选择。它通过系统属性获得 log4j 属性文件和第二个 bean 的位置,您可以为自己的系统适当地设置这些属性。

  我最初将两个 bean 都设置在相同的服务器上,这样只是为了进行测试。后来我改为使用一个多服务器设置。显而易见,为了在第二个服务器上查找,您需要提供正确的系统属性以使得查找工作能够进行。当一切都在相同的服务器上时,全部三个执行程序都可以使用同一个日志文件,这样您就会得到一个不错的组合日志。但是从现在起,我将假设您在单独的机器上运行程序,因而最终会得到三个单独的日志文件。

  运行方案

  如果您是在家自行测试,现在就是安装 EJB 组件和设置系统属性以挑选配置文件和组件位置的时间了。具体的方式各不相同,取决于您的应用程序服务器选择。您应该能够取得前面提供的属性文件,并为每个 EJB 组件创建该文件的一个拷贝。(这基本上涉及为每个 EJB 组件准备完全相同的文件;在我的例子中,我在一台机器上运行两个示例服务器,因此我必须修改属性文件以指向两个独立但是完全相同的文件。)一旦所有组件都已正常运行,您只需更新客户机来实际执行查找,并调用第一个 EJB 组件。下面让我们通过以下命令行来运行具有 50 个线程的客户机:

1 Java demo.logger.sample.SampleCode 50 /home/wouldd/JavaWork/workspace/LoggerDemo/log4j.properties
2      thisNode/servers/server1/ejb/log1Home
3

  您不需要所有那些线程,不过这样您会看到自己创建的日志记录系统的强大能力。

  如果是在家自行测试,您应该看到在系统的每个部分的属性文件中所指定的目录中生成的日志文件;如果没有指定目录,它将出现在每个进程的当前文件夹中。观察一下这些文件,您将看到类似如下的行:

1 2004-01-24 15:00:23,714  INFO [Thread-1] (SampleCode.java:67) - [-992285010] Program Running
2

  这里您可以看到不同的线程标识符等内容。根据行号(在日志所来自的文件的名称后面),您可以看到各种情况是如何从客户机到两个 EJB 组件的过程中发生的。

  下面让我们实际深入研究一下这些日志,看看 log4j 能告诉您哪些有趣的信息。

0
相关文章