2008年04月18日

阴雾背后一定有阳光!

我一定要走过去,走过去,走过去!

2008年04月15日

常想,我存在,但在这里我却找不到人知道我的存在。晃晃悠悠快三年了,在这里有谁知道我?除了同事几乎没有人。知道我的人又有谁真正关心我?没有人。同事也只知道工作时侯的我而已,离开公司我是怎样的?没有人知道。人们都只是过自己的日子,关心自己的生活而已,他们有关心他们的人,我想。

离开公司的生活本来是人的生活,本来是最有乐趣的生活,而我却没有乐趣。离开公司的生活也本来是最让人怀念的生活,而我也没有人可以共同记忆。我真不知道自己想要怎样的生活?或者我因为思考而浪费了太多太多。

但是我不会因此而沮丧,即使他也不会。呵呵,他还是个小孩子,一个太小的孩子。这都可以让他放弃我,可见他有多简单。这完全是个没有心,对人生没有期望的人,他只是想在父母的庇佑做个单纯的人。他只是不想让父母难过,其他人都可以难过,他只是想顺着父母,以自己的几十年生活奉献自己的孝心就可以了。其实他最不想难过的是他自己,最后一句话,他夹在中间很难做,强调的还是自己。他根本就不知道怎么做。他心里根本没有爱,没有真正的爱心,所有的东西都只是形式而已。

哦,形式,我却也看不透,却也被蒙蔽,悲哀的我就是这样的。

 

2008年04月08日

很多事情,到最后若放弃了,那肯定是自己放弃的。 到那时,别人或许还可以帮你找出千万种坚持的理由,在你心中恐怕只留下放弃的理由。

很多事情,到最后,或许只有自己在坚持。有很时候很坚强,那是因为总以为有人跟你身后,当你蓦然回首,就知道感慨,原来是自己过于激动造成了耳鸣,你的后面,其实早就没有脚步声。

坚持是自己在坚持,放弃也是自己在放弃。才说着天长地久,突然就转身不见。轻易出口的信誓旦旦,终究似那过眼云烟。如果说世界上还有什么可信的,只能说我还相信我还有真诚,我还相信前方会更好。

 

2008年03月06日

人生很多事情或许是个意外,有时候都分不清楚人为什么会感到快乐,也许是意外带来了快乐,反正我总觉得我得到快乐也纯粹是一种意外。真希望这快乐能够长久。

真希望我的快乐并不是意外带来了的。因为意外不能长久,缘于意外的快乐也难说能长久。

我希望我真的是意外地获得了快乐,还带着点侥幸。。。

2008年01月24日

 

From http://radio.weblogs.com/0135826/2005/04/26.html

From time to time we get complaints from partners and customers that OC4J do not support anonymous EJB lookup and execution of EJB methods. This means you do not specify the principal and credential when creating the InitialContext. For example, if you are trying to lookup a remote EJB in OC4J your jndi.properties will look like follows:

 

java.naming.factory.initial=oracle.j2ee.naming.ApplicationClientInitialContextFactory

java.naming.provider.url=ormi://localhost:23791/ejb30slsb

java.naming.security.principal=

java.naming.security.credentials=

 

In my opinion security is a practice that starts during development and I view this as a big security hole in the applications because you are leaving your EJBs in ejb30slsb� applications to be executed by anyone and I will advise against doing this.

 

Anyway many of us do not care until we are bitten and want to use anonymous EJB lookup because they do not care and have been doing this for years in some other application servers and want to continue the bad practice in OC4J. We have been looking at this for years and not implementing because our security practice would not allow such an implementation to be available out of the box.

 

However for those folks, who do not care for securing their EJBs, we provide a solution to configure OC4J to allow anonymous EJB lookup and I tried this in OC4J 10.1.3 and it works great. Here are the steps you have to do:

 

  1. Assign anonymous user in config/jazn-data.xml to a more privileged role/group that has RMI permissions

 

 

<role>

                        <name>users</name>

                 

                               <member>

                                    <type>user</type>

                                    <name>anonymous</name>

                              </member>

                        </members>

                  </role>

 

2. Make sure that group/role has name space access to that applications and permissions to execute EJB methods. Provided users role to access to the EJB by specifying the following in orion-application.xml packaged in the EAR.

 

<namespace-access>

            <read-access>

                  <namespace-resource root="">

                        <security-role-mapping name="&lt;jndi-user-role&gt;">

                              <group name="administrators" />

                              <group name="users" />

 

                        </security-role-mapping>

                  </namespace-resource>

            </read-access>

            <write-access>

                  <namespace-resource root="">

                        <security-role-mapping name="&lt;jndi-user-role&gt;">

                              <group name="administrators" />

                                <group name="users" />

                        </security-role-mapping>

                  </namespace-resource>

            </write-access>

      </namespace-access>

 

 

Now you should be able to access remote EJBs without specifying principals and credentials making your EJBs free for all.

 

THINK twice before you do this!

7:11:51 AM    comment [

1]

 

© Copyright 2005 Debu Panda.

PS: These are my own thoughts and not of my employer ..

2008年01月14日

From http://harper.yculblog.com/post.1021639.html

本文涉及的背景知识如下 

1. JNDI (Java Naming and Directory Service )  

2.    JMS (Reference: Java Message Service O’Reilly, Jan 2001 First Ed.)  

3.    EJB (Reference: Mastering

Enterprise JavaBean, O’Reilly & Associates, 2001 )  

本文只涉及EJB中的Message-Driven Bean  

4.    OC4J (Oracle Container For J2EE, Oracle公司的J2EE Application Server)

 

Part I Setting up OC4J JMS Service

 

下面是一个示例:

<?xml version="1.0" standalone=’yes’?>
<!DOCTYPE jms-server PUBLIC "OC4J JMS server" "http://xmlns.oracle.com/ias/dtds/jms-server-9_04.dtd">

<jms-server port="9127">

   
    <queue name="Jera MessageService Queue" location="jms/JeraMSQueue">
        <description>Queue for Jera MessageService</description>
    </queue>

    <topic name="Demo Topic" location="jms/demoTopic">
        <description>A dummy topic</description>
    </topic>
    
    <log>
        <file path="../log/jms.log"/>
        <!– Uncomment this if you want to use ODL logging capabilities
        <odl path="../log/jms/" max-file-size="1000" max-directory-size="10000"/>
        –>
    </log>

    <queue-connection-factory location="jms/JeraMSQueueConnectionFactory"/>
   
</jms-server>

 

其中queuetopic tag声明了可以使用的javax.jms.Queuejavax.jms.Topic,queue-connection-factorytopic-connection-factory则声明了可供使用的javax.jms.QueueConnectionFactoryjavax.jms.TopicConnectionFactory.主要需要配置的就是这几个tag. 其中location的属性最为重要,它指明了该对象的JNDI Name.

 

改动完毕后,重启OC4J,便可以用JNDI服务找到这些对象并使用它们.JMS Service配置完成。可以在AS中运行下述代码以验证服务是否成功启动。(如果在运行过程中没有出现Exception,一般可以确定配置成功)

 

           

 

             Context jndiContext = new InitialContext();

 

             QueueConnectionFactory qcf = (QueueConnectionFactory)

 

             jndiContext.lookup("jms/JeraMSQueueConnectionFactory");

 

             QueueConnection connect = qcf.createQueueConnection();

 

             Queue q = (Queue)jndiContext.lookup("jms/JeraMSQueue");

 

             QueueSession session =      connect.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);

 

             QueueSender sender = session.createSender(q);

 

             connect.start();

 

             sender.send(session.createTextMessage("This is a message"));

 

             connect.close();

 

Part II Configuring Message-Driven Bean

 

 

      <message-driven >

 

         <description><![CDATA[<!-- begin-user-doc --> You can insert your documentation for '<em><b>MessageServiceBean</b></em>'.]]></description>

 

         <ejb-name>MessageServiceBean</ejb-name>

 

         <ejb-class>org.harper.frm.core.ejb.msg.MessageServiceBean</ejb-class>

 

         <transaction-type>Container</transaction-type>

 

         <acknowledge-mode>Auto-acknowledge</acknowledge-mode>

 

         <message-driven-destination>

 

            <destination-type>javax.jms.Queue</destination-type>

 

         </message-driven-destination>

 

       </message-driven>

 

  

 

      <!– Message Driven Beans –>

 

      <message-driven-deployment name="MessageServiceBean"

 

                  destination-location="jms/JeraMSQueue"

 

                  connection-factory-location="jms/JeraMSQueueConnectionFactory">

 

      </message-driven-deployment>

 

 

 

 

 

    protected void doGet(HttpServletRequest request,

            HttpServletResponse response) throws Exception {

        doService(request, response);

    }

    protected void doPost(HttpServletRequest request,

            HttpServletResponse response) throws Exception {

        doService(request, response);

    }

    protected void doService(HttpServletRequest request,

            HttpServletResponse response) throws Exception {

        Context jndiContext = new InitialContext();

        QueueConnectionFactory qcf = (QueueConnectionFactory)

        jndiContext.lookup("jms/JeraMSQueueConnectionFactory");

      QueueConnection connect = qcf.createQueueConnection();

      Queue q = (Queue)jndiContext.lookup("jms/JeraMSQueue");

        QueueSession session = connect.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);

        QueueSender sender = session.createSender(q);

        connect.start();

        sender.send(session.createTextMessage("This is a message"));

        connect.close();  } 


      Message-Driven Bean
onMessage函数如下 

    public void onMessage(javax.jms.Message message) {

        // begin-user-code

        System.out.println("Message Driven Bean got message " + message);

        // TODO:  do business logic here

      // end-user-code

}


      执行后输出结果如下:

“Message Driven Bean got message TextMessage[ID:Oc4jJMS.Message.jiangha.71dc3d:1082ce8377e:-8000.8]”

证明配置成功完成。

 这里的name属性与上面ejb-jar.xml中的ejb-name属性是对应的。 destination-locationconnection-factory-location分别指定了MDB读取Message使用的消息队列和创建连接使用的Factory.这里的location必须是在jms.xml中声明过的连接。

 

 至此配置完成,下面要做的是测试工作。

 

 Part III Test

 

 测试环境由两部分组成:负责发送消息的Servlet和后台处理消息的Message-Driven Bean.

 

 Servlet端代码如下

  这个deployment-descriptor中,需要修改的部分主要有<transaction-type>(可选项为ContainerBean)<destination-type>(可选项为QueueTopic),根据MDB具体选择。

 

  如果读者对EJB比较熟悉,可能会注意到:SessionBeanEntityBean不同的是,Message-Driven Beandeployment-descriptor中没有包含JNDI location的信息。这是由MDB与其他两种EJB不同的工作方式决定的。在被创建后,MDB会使用指定的ConnectionFactory创建与JMS Service的连接,随后在指定的消息队列中监听消息,并根据收到的消息决定自己的行为。应用程序只能通过这个消息队列与MDB交互,所以MDB并不需要一个JNDI location.

 

  2.  orion-ejb-jar.xml的配置

 

 这个文件是OC4J系列Server专用的deployment-descriptor文件。如果使用的ASJBOSS,则要配置jboss.xml,其他类似。

 

 下面是一个示例:

 本段假设读者已经具有EJB的相关背景知识(包括deployment descriptor),因此不再对一些常识进行说明。

 

    1.  ejb-jar.xml的配置

    JMS Service的运行需要一台JMS Server的支持。目前主流J2EE AS的开发商都在自己的产品中集成了JMS Server的实现,只需要正确的配置,启用JMS服务就可以了。本文中使用的JMS ServerOC4J JMS

 

    OC4J JMS的配置文件是$ORACLE_HOME/config/jms.xml,在$ORACLE_HOME/config/server.xml中使用”<jms-config path="./jms.xml"/>” tag指明。

 

   Jms.xmlDTD文件是http://xmlns.oracle.com/ias/dtds/jms-server-9_04.dtd

From http://harper.yculblog.com/post.1021639.html

本文涉及的背景知识如下 

1. JNDI (Java Naming and Directory Service )  

2.    JMS (Reference: Java Message Service O’Reilly, Jan 2001 First Ed.)  

3.    EJB (Reference: Mastering

Enterprise JavaBean, O’Reilly & Associates, 2001 )  

本文只涉及EJB中的Message-Driven Bean  

4.    OC4J (Oracle Container For J2EE, Oracle公司的J2EE Application Server)

 

Part I Setting up OC4J JMS Service

 

下面是一个示例:

<?xml version="1.0" standalone=’yes’?>
<!DOCTYPE jms-server PUBLIC "OC4J JMS server" "http://xmlns.oracle.com/ias/dtds/jms-server-9_04.dtd">

<jms-server port="9127">

   
    <queue name="Jera MessageService Queue" location="jms/JeraMSQueue">
        <description>Queue for Jera MessageService</description>
    </queue>

    <topic name="Demo Topic" location="jms/demoTopic">
        <description>A dummy topic</description>
    </topic>
    
    <log>
        <file path="../log/jms.log"/>
        <!– Uncomment this if you want to use ODL logging capabilities
        <odl path="../log/jms/" max-file-size="1000" max-directory-size="10000"/>
        –>
    </log>

    <queue-connection-factory location="jms/JeraMSQueueConnectionFactory"/>
   
</jms-server>

 

其中queuetopic tag声明了可以使用的javax.jms.Queuejavax.jms.Topic,queue-connection-factorytopic-connection-factory则声明了可供使用的javax.jms.QueueConnectionFactoryjavax.jms.TopicConnectionFactory.主要需要配置的就是这几个tag. 其中location的属性最为重要,它指明了该对象的JNDI Name.

 

改动完毕后,重启OC4J,便可以用JNDI服务找到这些对象并使用它们.JMS Service配置完成。可以在AS中运行下述代码以验证服务是否成功启动。(如果在运行过程中没有出现Exception,一般可以确定配置成功)

 

           

 

             Context jndiContext = new InitialContext();

 

             QueueConnectionFactory qcf = (QueueConnectionFactory)

 

             jndiContext.lookup("jms/JeraMSQueueConnectionFactory");

 

             QueueConnection connect = qcf.createQueueConnection();

 

             Queue q = (Queue)jndiContext.lookup("jms/JeraMSQueue");

 

             QueueSession session =      connect.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);

 

             QueueSender sender = session.createSender(q);

 

             connect.start();

 

             sender.send(session.createTextMessage("This is a message"));

 

             connect.close();

 

Part II Configuring Message-Driven Bean

 

 

      <message-driven >

 

         <description><![CDATA[<!-- begin-user-doc --> You can insert your documentation for '<em><b>MessageServiceBean</b></em>'.]]></description>

 

         <ejb-name>MessageServiceBean</ejb-name>

 

         <ejb-class>org.harper.frm.core.ejb.msg.MessageServiceBean</ejb-class>

 

         <transaction-type>Container</transaction-type>

 

         <acknowledge-mode>Auto-acknowledge</acknowledge-mode>

 

         <message-driven-destination>

 

            <destination-type>javax.jms.Queue</destination-type>

 

         </message-driven-destination>

 

       </message-driven>

 

  

 

      <!– Message Driven Beans –>

 

      <message-driven-deployment name="MessageServiceBean"

 

                  destination-location="jms/JeraMSQueue"

 

                  connection-factory-location="jms/JeraMSQueueConnectionFactory">

 

      </message-driven-deployment>

 

 

 

 

 

    protected void doGet(HttpServletRequest request,

            HttpServletResponse response) throws Exception {

        doService(request, response);

    }

    protected void doPost(HttpServletRequest request,

            HttpServletResponse response) throws Exception {

        doService(request, response);

    }

    protected void doService(HttpServletRequest request,

            HttpServletResponse response) throws Exception {

        Context jndiContext = new InitialContext();

        QueueConnectionFactory qcf = (QueueConnectionFactory)

        jndiContext.lookup("jms/JeraMSQueueConnectionFactory");

      QueueConnection connect = qcf.createQueueConnection();

      Queue q = (Queue)jndiContext.lookup("jms/JeraMSQueue");

        QueueSession session = connect.createQueueSession(false,Session.AUTO_ACKNOWLEDGE);

        QueueSender sender = session.createSender(q);

        connect.start();

        sender.send(session.createTextMessage("This is a message"));

        connect.close();  } 


      Message-Driven Bean
onMessage函数如下 

    public void onMessage(javax.jms.Message message) {

        // begin-user-code

        System.out.println("Message Driven Bean got message " + message);

        // TODO:  do business logic here

      // end-user-code

}


      执行后输出结果如下:

“Message Driven Bean got message TextMessage[ID:Oc4jJMS.Message.jiangha.71dc3d:1082ce8377e:-8000.8]”

证明配置成功完成。

 这里的name属性与上面ejb-jar.xml中的ejb-name属性是对应的。 destination-locationconnection-factory-location分别指定了MDB读取Message使用的消息队列和创建连接使用的Factory.这里的location必须是在jms.xml中声明过的连接。

 

 至此配置完成,下面要做的是测试工作。

 

 Part III Test

 

 测试环境由两部分组成:负责发送消息的Servlet和后台处理消息的Message-Driven Bean.

 

 Servlet端代码如下

  这个deployment-descriptor中,需要修改的部分主要有<transaction-type>(可选项为ContainerBean)<destination-type>(可选项为QueueTopic),根据MDB具体选择。

 

  如果读者对EJB比较熟悉,可能会注意到:SessionBeanEntityBean不同的是,Message-Driven Beandeployment-descriptor中没有包含JNDI location的信息。这是由MDB与其他两种EJB不同的工作方式决定的。在被创建后,MDB会使用指定的ConnectionFactory创建与JMS Service的连接,随后在指定的消息队列中监听消息,并根据收到的消息决定自己的行为。应用程序只能通过这个消息队列与MDB交互,所以MDB并不需要一个JNDI location.

 

  2.  orion-ejb-jar.xml的配置

 

 这个文件是OC4J系列Server专用的deployment-descriptor文件。如果使用的ASJBOSS,则要配置jboss.xml,其他类似。

 

 下面是一个示例:

 本段假设读者已经具有EJB的相关背景知识(包括deployment descriptor),因此不再对一些常识进行说明。

 

    1.  ejb-jar.xml的配置

    JMS Service的运行需要一台JMS Server的支持。目前主流J2EE AS的开发商都在自己的产品中集成了JMS Server的实现,只需要正确的配置,启用JMS服务就可以了。本文中使用的JMS ServerOC4J JMS

 

    OC4J JMS的配置文件是$ORACLE_HOME/config/jms.xml,在$ORACLE_HOME/config/server.xml中使用”<jms-config path="./jms.xml"/>” tag指明。

 

   Jms.xmlDTD文件是http://xmlns.oracle.com/ias/dtds/jms-server-9_04.dtd

2007年12月24日

一、前言:
     log4j (http://jakarta.apache.org/log4j/)是一个开放源码项目,是广泛使用的以Java编写的日志记录包。由于log4j出色的表现,当时在log4j完成时,log4j开发组织曾建议sun在jdk1.4中用log4j取代jdk1.4 的日志工具类,但当时jdk1.4已接近完成,所以sun拒绝使用log4j,当在java开发中实际使用最多的还是log4j,人们遗忘了sun的日志工具类.。它的一个独有特性包括在类别中继承的概念。通过使用类别层次结构,这样就减少了日志记录输出量,并将日志记录的开销降到最低。
  
     它允许开发者控制以任意间隔输出哪些日志语句。通过使用外部配置文件,完全可以在运行时进行配置。几乎每个大的应用程序都包括其自己的日志记录或跟踪 API。经验表明日志记录是开发周期中的重要组成部分。同样,日志记录提供一些优点。首先,它可以提供运行应用程序的确切 上下文。一旦插入到代码中,生成日志记录输出就不需要人为干涉。其次,日志输出可以保存到永久媒体中以便以后研究。最后,除了在开发阶段中使用,十分丰富的日志记录包还可以用作审计工具。

    依照该规则,在 1996 年初,EU SEMPER(欧洲安全电子市场)项目就决定编写自己的跟踪 API。 在无数次改进、几次具体化和许多工作之后,该 API 已经演变成 log4j,一种流行的 Java 日志记录包。  这个包按 IBM 公共许可证分发,由开放源码权威机构认证。

    日志记录有其自己的缺点。它会降低应用程序的速度。如果太详细,它可能会使屏幕滚动变得看不见。  为了减低这些影响,log4j 被设计成快速且灵活的。由于应用程序很少将日志记录当作是主要功能,  log4j API 力争易于了解和使用。
     log4j,它可以控制以任意间隔输出哪些日志语句。

二、主要组件

1、根类别(在类别层次结构的顶部,即全局性的日志级别)
 
配置根Logger,其语法为:

log4j.rootLogger = [ level ] , appenderName, appenderName, …

level 是日志记录的类别
appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。

类别level 为 OFF、FATAL、ERROR、WARN、INFO、DEBUG、log、ALL或自定义的优先级。
og4j常用的优先级FATAL>ERROR>WARN>INFO>DEBUG
配置根Logger,其语法为:
log4j.rootLogger = [ level ] , appenderName, appenderName, …
如果为log4j.rootLogger=WARN,则意味着只有WARN,ERROR,FATAL被输出,DEBUG,INFO将被屏蔽掉。

举例:log4j.rootCategory=INFO,stdout,Runlog,Errorlog
根日志类别为INFO,DEBUG将被屏蔽,其他的将被输出。 stdout,Runlog,Errorlog分别为3个输出目的地。

 2、常用输出格式

 -X号:X信息输出时左对齐;
 %p:日志信息级别
 %d{}:日志信息产生时间
 %c:日志信息所在地(类名)
 %m:产生的日志具体信息
 %n:输出日志信息换行
 举例:
log4j.appender.stdout.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n
log4j.appender.Runlog.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n
log4j.appender.Errorlog.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n

3、布局
使用的输出布局,其中log4j提供4种布局:
org.apache.log4j.HTMLLayout(以HTML表格形式布局)
org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

举例:
输出格式为HTML表格
log4j.appender.stdout.layout=org.apache.log4j.HTMLLayout

输出格式为可以灵活地指定布局模式
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

输出格式为包含日志信息的级别和信息字符串
log4j.appender.stdout.layout=org.apache.log4j.SimpleLayout

输出格式为包含日志产生的时间、线程、类别等等信息
log4j.appender.stdout.layout=org.apache.log4j.TTCCLayout

4、目的地

配置日志信息输出目的地Appender,其语法为

log4j.appender.appenderName = fully.qualified.name.of.appender.class
log4j.appender.appenderName.option1 = value1

log4j.appender.appenderName.option = valueN
appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。

log4j支持的输出目的地:
org.apache.log4j.ConsoleAppender 控制台
org.apache.log4j.FileAppender 文件
org.apache.log4j.DailyRollingFileAppender 每天产生一个日志文件
org.apache.log4j.RollingFileAppender (文件大小到达指定尺寸的时候产生一个新的文件),
org.apache.log4j.WriterAppender (将日志信息以流格式发送到任意指定的地方)
org.apache.log4j.net.SMTPAppender 邮件
org.apache.log4j.jdbc.JDBCAppender 数据库
其他如:GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等

举例:

输出到控制台
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender(指定输出到控制台)
log4j.appender.Threshold=DEBUG(指定输出类别)
log4j.appender.CONSOLE.Target=System.out
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout(指定输出布局)
log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n(指定输出格式)

输出到文件

   log4j.appender.FILE=org.apache.log4j.FileAppender(指定输出到文件)
   log4j.appender.FILE.File=file.log(指定输出的路径及文件名)
   log4j.appender.FILE.Append=false
   log4j.appender.FILE.layout=org.apache.log4j.PatternLayout(指定输出的布局)
   log4j.appender.FILE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n(指定输出的格式)

输出到文件(轮换"日志文件",当日志文件达到指定大小时,该文件就被关闭并备份,然后创建一个新的日志文件)

  log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender(指定输出到文件)
  log4j.appender.ROLLING_FILE.Threshold=ERROR(指定输出类别)
  log4j.appender.ROLLING_FILE.File=rolling.log(指定输出的路径及文件名)
  log4j.appender.ROLLING_FILE.Append=true
  log4j.appender.ROLLING_FILE.MaxFileSize=10KB(指定输出到文件的大小)
  log4j.appender.ROLLING_FILE.MaxBackupIndex=1
  log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout(指定采用输出布局)
  log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n(指定采用输出格式)

输出到Socket
 log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender(指定输出到Socket)
 log4j.appender.SOCKET.RemoteHost=localhost(远程主机)
 log4j.appender.SOCKET.Port=5001(远程主机端口)
 log4j.appender.SOCKET.LocationInfo=true
 log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout(布局)
 log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n(输出格式)

输出到邮件
log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender(指定输出到邮件)
 log4j.appender.MAIL.Threshold=FATAL
 log4j.appender.MAIL.BufferSize=10
 log4j.appender.MAIL.From=chunkyo@163.com(发件人)
 log4j.appender.MAIL.SMTPHost=mail.hollycrm.com(SMTP服务器)
 log4j.appender.MAIL.Subject=Log4J Message
 log4j.appender.MAIL.To=chunkyo@163.com(收件人)
 log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout(布局)
 log4j.appender.MAIL.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n(格式)

 

输出到数据库
 log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender(指定输出到数据库)
 log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test(指定数据库URL)
 log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver(指定数据库driver)
 log4j.appender.DATABASE.user=root(指定数据库用户)
 log4j.appender.DATABASE.password=root(指定数据库用户密码)
 log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES (‘[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n’)(组织SQL语句)
 log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout(布局)
 log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n(格式)

5、日志类别补充
有时我们需要对某个特定的部分指定有别于根类别的日志类别,可以指定某个包的优先级
如:
  log4j.category.com.neusoft.mbip.dm.util=ERROR ,其中com.neusoft.mbip.dm.util为我们需要特别指定日志类别的部分。
 
  或者可以指定输出文件的优先级
  log4j.appender.Errorlog.Threshold=ERROR
 
三、 常用log4j配置 

常用log4j配置,一般可以采用两种方式,.properties和.xml,下面举两个简单的例子:

1、log4j.properties

### 设置org.zblog域对应的级别INFO,DEBUG,WARN,ERROR和输出地A1,A2 ##
log4j.category.org.zblog=ERROR,A1
log4j.category.org.zblog=INFO,A2

log4j.appender.A1=org.apache.log4j.ConsoleAppender
### 设置输出地A1,为ConsoleAppender(控制台) ##
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
### 设置A1的输出布局格式PatterLayout,(可以灵活地指定布局模式)##
log4j.appender.A1.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%c]-[%p] %m%n
### 配置日志输出的格式##

log4j.appender.A2=org.apache.log4j.RollingFileAppender
### 设置输出地A2到文件(文件大小到达指定尺寸的时候产生一个新的文件)##
log4j.appender.A2.File=E:/study/log4j/zhuwei.html
### 文件位置##
log4j.appender.A2.MaxFileSize=500KB
### 文件大小##
log4j.appender.A2.MaxBackupIndex=1
log4j.appender.A2.layout=org.apache.log4j.HTMLLayout
##指定采用html方式输出

2、log4j.xml

<?xml version="1.0" encoding="GB2312" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

<appender name="org.zblog.all" class="org.apache.log4j.RollingFileAppender">
<!– 设置通道ID:org.zblog.all和输出方式:org.apache.log4j.RollingFileAppender –>
    <param name="File" value="E:/study/log4j/all.output.log" /><!– 设置File参数:日志输出文件名 –>
    <param name="Append" value="false" /><!– 设置是否在重新启动服务时,在原有日志的基础添加新日志 –>
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%p (%c:%L)- %m%n" /><!– 设置输出文件项目和格式 –>
    </layout>
</appender>

<appender name="org.zblog.zcw" class="org.apache.log4j.RollingFileAppender">
    <param name="File" value="E:/study/log4j/zhuwei.output.log" />
    <param name="Append" value="true" />
    <param name="MaxFileSize" value="10240" /> <!– 设置文件大小 –>
    <layout class="org.apache.log4j.PatternLayout">
        <param name="ConversionPattern" value="%p (%c:%L)- %m%n" />
    </layout>
</appender>

<logger name="zcw.log"> <!– 设置域名限制,即zcw.log域及以下的日志均输出到下面对应的通道中 –>
    <level value="debug" /><!– 设置级别 –>
    <appender-ref ref="org.zblog.zcw" /><!– 与前面的通道id相对应 –>
</logger>

<root> <!– 设置接收所有输出的通道 –>
    <appender-ref ref="org.zblog.all" /><!– 与前面的通道id相对应 –>
</root>

</log4j:configuration>

3、配置文件加载方法:

import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.xml.DOMConfigurator;

public class Log4jApp {
    public static void main(String[] args) {
        DOMConfigurator.configure("E:/study/log4j/log4j.xml");//加载.xml文件
        //PropertyConfigurator.configure("E:/study/log4j/log4j.properties");//加载.properties文件

        Logger log=Logger.getLogger("org.zblog.test");
        log.info("测试");
    }
}

4、项目使用log4j
在web应用中,可以将配置文件的加载放在一个单独的servlet中,并在web.xml中配置该servlet在应用启动时候加载。
对于在多人项目中,可以给每一个人设置一个输出通道,这样在每个人在构建Logger时,用自己的域名称,让调试信
息输出到自己的log文件中。

四、log4j配置举例(properties)

#log4j.rootLogger = [ level ] , appenderName, appenderName,
#类别level 为 OFF、FATAL、ERROR、WARN、INFO、DEBUG、log、ALL或自定义的优先级
#Log4j常用的优先级FATAL>ERROR>WARN>INFO>DEBUG

#stdout为控制台 ,Errorlog为错误记录日志 ,
log4j.rootCategory=INFO,stdout,Runlog,Errorlog

#输出的appender的格式为
#log4j.appender.appenderName = fully.qualified.name.of.appender.class
#log4j.appender.appenderName.option1 = value1
#log4j.appender.appenderName.option = valueN
#Log4j中appender支持的输出
#org.apache.log4j.ConsoleAppender 控制台
#org.apache.log4j.FileAppender 文件
#org.apache.log4j.DailyRollingFileAppender 每天产生一个日志文件
#org.apache.log4j.RollingFileAppender (文件大小到达指定尺寸的时候产生一个新的文件),
#org.apache.log4j.WriterAppender (将日志信息以流格式发送到任意指定的地方)
#org.apache.log4j.net.SMTPAppender 邮件
#org.apache.log4j.jdbc.JDBCAppender 数据库

#定义输出的形式
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.Runlog=org.apache.log4j.DailyRollingFileAppender
log4j.appender.Errorlog=org.apache.log4j.DailyRollingFileAppender

#可以指定输出文件的优先级
log4j.appender.Errorlog.Threshold=ERROR

#指定输出的文件
log4j.appender.Runlog.File=D:\\UserInfoSyn\\WebRoot\\WEB-INF\\runlog\\runlog.log
log4j.appender.Errorlog.File=D:\\UserInfoSyn\\WebRoot\\WEB-INF\\errorlog\\errorlog.log

#Log4j的layout布局
#org.apache.log4j.HTMLLayout 以HTML表格形式布局
#org.apache.log4j.PatternLayout 可以灵活地指定布局模式
#org.apache.log4j.SimpleLayout  包含日志信息的级别和信息字符串
#org.apache.log4j.TTCCLayout    包含日志产生的时间、线程、类别等等信息

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.Runlog.layout=org.apache.log4j.PatternLayout
log4j.appender.Errorlog.layout=org.apache.log4j.PatternLayout

#输出格式,log4j javadoc org.apache.log4j.PatternLayout
#-X号:X信息输出时左对齐;
#%p:日志信息级别
# %d{}:日志信息产生时间
# %c:日志信息所在地(类名)
# %m:产生的日志具体信息
# %n:%n:输出日志信息换行
log4j.appender.stdout.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n
log4j.appender.Runlog.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n
log4j.appender.Errorlog.layout.ConversionPattern= %5p %d{yyyy-MM-dd HH:mm:ss} %c %m %n

#指定某个包的优先级
log4j.category.com.neusoft.mbip.dm.util=ERROR

#示例
###################
# Console Appender
###################
#log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
#log4j.appender.Threshold=DEBUG
#log4j.appender.CONSOLE.Target=System.out
#log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
#log4j.appender.CONSOLE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n
#log4j.appender.CONSOLE.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD] n%c[CATEGORY]%n%m[MESSAGE]%n%n

#####################
# File Appender
#####################
#log4j.appender.FILE=org.apache.log4j.FileAppender
#log4j.appender.FILE.File=file.log
#log4j.appender.FILE.Append=false
#log4j.appender.FILE.layout=org.apache.log4j.PatternLayout
#log4j.appender.FILE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n
# Use this layout for LogFactor 5 analysis

########################
# Rolling File????? RollingFileAppender??????????????????
########################
#log4j.appender.ROLLING_FILE=org.apache.log4j.RollingFileAppender
#log4j.appender.ROLLING_FILE.Threshold=ERROR
# 文件位置
#log4j.appender.ROLLING_FILE.File=rolling.log
#log4j.appender.ROLLING_FILE.Append=true
#文件大小
#log4j.appender.ROLLING_FILE.MaxFileSize=10KB
#指定采用输出布局和输出格式
#log4j.appender.ROLLING_FILE.MaxBackupIndex=1
#log4j.appender.ROLLING_FILE.layout=org.apache.log4j.PatternLayout
#log4j.appender.ROLLING_FILE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n

####################
# Socket Appender
####################
#log4j.appender.SOCKET=org.apache.log4j.RollingFileAppender
#log4j.appender.SOCKET.RemoteHost=localhost
#log4j.appender.SOCKET.Port=5001
#log4j.appender.SOCKET.LocationInfo=true
# Set up for Log Facter 5
#log4j.appender.SOCKET.layout=org.apache.log4j.PatternLayout
#log4j.appender.SOCET.layout.ConversionPattern=[start]%d{DATE}[DATE]%n%p[PRIORITY]%n%x[NDC]%n%t[THREAD]%n%c[CATEGORY]%n%m[MESSAGE]%n%n

########################
# SMTP Appender
#######################
#log4j.appender.MAIL=org.apache.log4j.net.SMTPAppender
#log4j.appender.MAIL.Threshold=FATAL
#log4j.appender.MAIL.BufferSize=10
#log4j.appender.MAIL.From=chunkyo@163.com
#log4j.appender.MAIL.SMTPHost=mail.hollycrm.com
#log4j.appender.MAIL.Subject=Log4J Message
#log4j.appender.MAIL.To=chunkyo@163.com
#log4j.appender.MAIL.layout=org.apache.log4j.PatternLayout
#log4j.appender.MAIL.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n

########################
# JDBC Appender
#######################
#log4j.appender.DATABASE=org.apache.log4j.jdbc.JDBCAppender
#log4j.appender.DATABASE.URL=jdbc:mysql://localhost:3306/test
#log4j.appender.DATABASE.driver=com.mysql.jdbc.Driver
#log4j.appender.DATABASE.user=root
#log4j.appender.DATABASE.password=
#log4j.appender.DATABASE.sql=INSERT INTO LOG4J (Message) VALUES (‘[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n’)
#log4j.appender.DATABASE.layout=org.apache.log4j.PatternLayout
#log4j.appender.DATABASE.layout.ConversionPattern=[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n

########################
# Log Factor 5 Appender
########################
#log4j.appender.LF5_APPENDER=org.apache.log4j.lf5.LF5Appender
#log4j.appender.LF5_APPENDER.MaxNumberOfRecords=2000

###################
#自定义Appender
###################
#log4j.appender.im = net.cybercorlin.util.logger.appender.IMAppender
#log4j.appender.im.host = mail.cybercorlin.net
#log4j.appender.im.username = username
#log4j.appender.im.password = password
#log4j.appender.im.recipient = chunkyo@163.com
#log4j.appender.im.layout=org.apache.log4j.PatternLayout
#log4j.appender.im.layout.ConversionPattern =[framework] %d – %c -%-4r [%t] %-5p %c %x – %m%n

posted on 2007-02-05 12:24 chunkyo 阅读(1667) 评论(2)  编辑  收藏 所属分类: Java技术


FeedBack:

# re: Log4j的介绍
2007-02-05 14:49 | BeanSoft

log4j 过滤日志级别
Please see detail for logconfig.xml. For filter only support xml.

You can use as following appender:

org.apache.log4j.ConsoleAppender ConsoleAppender
org.apache.log4j.FileAppender FileAppender
org.apache.log4j.jdbc.JDBCAppender JDBCAppender
org.apache.log4j.AsyncAppender AsyncAppender
org.apache.log4j.net.JMSAppender JMSAppender
org.apache.log4j.lf5.LF5Appender LF5Appender
org.apache.log4j.nt.NTEventLogAppender NTEventLogAppender
org.apache.log4j.varia.NullAppender NullAppender
org.apache.log4j.net.SMTPAppender SMTPAppender
org.apache.log4j.net.SocketAppender SocketAppender
org.apache.log4j.net.SocketHubAppender SocketHubAppender
org.apache.log4j.net.SyslogAppender SyslogAppender
org.apache.log4j.net.TelnetAppender TelnetAppender
org.apache.log4j.WriterAppender WriterAppender
For only one level deal:
You must user LevelRangeFilter and set LevelMin and LevelMax to the same level,

Note:The value must uppercase.

<filter class="org.apache.log4j.varia.LevelRangeFilter">
<param name="LevelMin" value="ERROR" />
<param name="LevelMax" value="ERROR" />
</filter>

归类于: Java — 海檐 @ 2:10 pm 评论(0)
how to get sysdate date to display in dos

From http://freemind.sourceforge.net/wiki/index.php/Freemind_Win_Collab

Freemind Win Collab

From FreeMind

Table of contents

[hide]

Introduction

Share your mindmaps and build them in collaboration. This simple batch file authorizes collaboration on freemind maps via a fileserver. If you can access the same disk with your collegues in your organisation, you can now work together on your mindmaps : this script avoid multiple edition at the same time (lock the file for you and tell the others that YOU are currently editing it) and make backups each time you open a mindmap (like 2006-04-02_myfilename.mm). Works only on Windows.

Use

Call share.bat instead of the freemind file directly (ex : toto.mm) to lock and backup the map prior editing. Easy way to use it : put your freemind file + share.bat on your shared disk (ex : J://freemindFiles/share.bat and J://freemindFiles/toto.mm) and make a share.bat shortcut on your windows desk (right click on share.bat and select "send to" > "desk")

Code

Copy the code below to a text file (located in the same dir as your mindmap to share if possible) named share.bat (for example). Check if the configuration lines (first lines) fits your needs.

@ECHO OFFCLSREM *** CONFIG : Edit here if necessary ***

SET freemindProgramPath = "C:\Program files\FreeMind\Freemind.exe"

REM if this script is in the same dir as the file (.mm), just write : filepath=.\SET filepath=.\

REM the name of the file to shareSET filename=toto.mm

REM if you like the backuped file to be stored in their own dir. Don't forget the trailing slashREM example : backupsdir=versions\SET backupsdir=

REM ******** Do not edit below ********

IF EXIST %filepath%lock.txt GOTO :LOCKEDFILE

ECHO STARTING FREEMIND on %computername% echo .

REM ********** Backups ***************set mydate=%date:~11,4%%date:~8,2%%date:~5,2%set mytime=%time:~0,2%%time:~3,2%%time:~6,2%ECHO Saving preceding version of this file (good idea, is'nt it ?)copy "%filepath%%filename%" "%filepath%%backupsdir%%mydate%_%mytime%_%filename%"ECHO .echo %filepath%%backupsdir%%mydate%_%mytime%_%filename%echo %mydate%echo %mytime%REM ********** lock file creation ***************ECHO %computername% > "%filepath%lock.txt"%freemindProgramPath% "%filepath%%filename%"ECHO You locked this mindmap file. You can free it later by pressing space bar in this windowecho .PAUSECLSECHO That's it, your file is now free to be edited by others.DEL "%filepath%lock.txt"GOTO THEEND

:LOCKEDFILECLSECHO Sorry, the file is already edited by  TYPE "%filepath%lock.txt"GOTO THEEND

:THEENDecho .PAUSE

Licence

This code is released under GPL licence by Starcrouz (http://stephane.Rouilly.free.fr/). Hope it could be usefull for you.

Who use it ?

Us at EDF R&D (http://www.rd.edf.fr/), France

Generalization

I’ve put the above idea to more general use, meaning the replacement of Freemind.exe in the windows registered filetypes. This means that the script mentioned below will be called instead and locks the mindmap for every opening through the explorer. Another difference of the script to the original is that the user doesn’t need to press any keys in command shells anymore, as the script only continues after the freemind executable (actually java) has been closed by the user. There is still commandshells being opened, which I’m not too happy about.

Use

"Install" the script + the windows registry changes and simply open your .mm files in the explorer

Code

Copy the code below to a command script named startLockFreemind.cmd (for example) and put into your Freemind program folder. Check if the configuration lines (first lines) fits your needs.

Copy the registry entries to a .reg file (e.g. FreemindLock.reg) and import into registry (doubleclicking). In case you changed the name of the command script then you have to modify the contents accordingly. Also you might need to change the path to the command script to reflect your Freemind program folder location.

@ECHO OFFCLSREM *** CONFIG : Edit here if necessary ***(SET fPP=C:\Programme\Freemind\)

REM if you like the backuped file to be stored in their own dir. Don't forget the trailing slashREM example : backupsdir=MMversions\SET backupsdir=MMversions\

REM ******** Do not edit below ********set fileFP=%~1%set fileN=%~n1%set fileP=%~p1%

IF EXIST "%fileFP%.lock" GOTO :LOCKEDFILE

ECHO STARTING FREEMIND on %computername%

REM ********** Backups ***************set mytime=%time:~0,2%%time:~3,2%%time:~6,2%

REM You might need to change that to reflect your local date display...set mydate=%date:~6,4%%date:~3,2%%date:~0,2%

IF NOT EXIST "%fileP%%backupsdir%" mkdir "%fileP%%backupsdir%"copy "%fileFP%" "%fileP%%backupsdir%%mydate%_%mytime%_%fileN%.mm"

REM ********** lock file creation ***************ECHO %computername% > "%fileFP%.lock"start /wait java.exe -cp %fPP%lib\freemind.jar;%fPP%lib\ant\lib\jaxb-api.jar;%fPP%lib\ant\lib\jaxb-impl.jar;%fPP%lib\ant\lib\jaxb-libs.jar;%fPP%lib\ant\lib\namespace.jar;%fPP%lib\ant\lib\relaxngDatatype.jar;%fPP%lib\ant\lib\xsdlib.jar;%fPP%lib\ant\lib\jax-qname.jar;%fPP%lib\ant\lib\sax.jar;%fPP%lib\ant\lib\dom.jar freemind.main.FreeMind "%fileFP%"DEL "%fileFP%.lock"GOTO THEEND

:LOCKEDFILECLSECHO Sorry, the file is already edited by  TYPE "%fileFP%.lock"PAUSEGOTO THEEND

:THEEND

Registry Settings

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\FreeMind Map\Shell\Open\Command]@="\"C:\\Programme\\FreeMind\\startLockFreemind.cmd\" \"%1\""

Licence

This code is released under GPL licence by Roland (http://www.kapl.org/).

归类于: Java — 海檐 @ 10:25 am 评论(0)
2007年12月20日
Jms基础知识整理

from http://njnjut.javaeye.com/blog/64707

Jms基础知识整理

关键字:   jms    
开始文章之前先澄清几个概念

什么是消息

消息是一个用于在组件和应用程序之间通讯的的方法。消息之间的传递是点对点的。任何终端之间都可以相互接受和发送消息。并且每个终端都必须遵守如下的规则
 -> 创建消息 -> 发送消息 -> 接收消息 -> 读取消息

为什么要使用消息
理由很简单,消息是一个分布式的低耦合通讯方案。A发送一个消息到一个agent ,B作为接受者去agent上获取消息。但是A,B不需要同时到agent上去注册。agent作为一个中转为A,B提供搞效率的通讯服务。

开发者的关注点
走到这里,我也不想去解释jms spec上那些抽象且复杂的概念了,说的很白,1年多了我自己也没弄懂是个什么东西,也没时间从头到尾去仔细的看,同时我认为没必要,我所关注的是如何让jms跑起来,并且工作正常,所以spec只是个字典,当我需要用的时候才去查。

开发者的jms环境
遵守简单明了的原则,所谓jms环境只是2个对象
1> ConnectionFactory
2> Destination

通常Provider会提供JNDI的对象获取,具体方法可以去Privider的网站上搜索jndi support

下面我以jbossMq为介质跑一个简单的jms,为了保证jms的本质清晰,我没有使用jbossMq的Api,而是直接调用的jms Api.

java 代码
 
  1. package com.javaeye.jms.jboss;  
  2.   
  3. import javax.jms.Connection;  
  4. import javax.jms.ConnectionFactory;  
  5. import javax.jms.Destination;  
  6. import javax.jms.JMSException;  
  7. import javax.jms.MessageConsumer;  
  8. import javax.jms.MessageProducer;  
  9. import javax.jms.Queue;  
  10. import javax.jms.QueueSender;  
  11. import javax.jms.Session;  
  12. import javax.jms.TextMessage;  
  13. import javax.naming.Context;  
  14. import javax.naming.InitialContext;  
  15. import javax.naming.NamingException;  
  16.   
  17. public class JbossNativeJmsImpl {  
  18.      
  19.     /** 
  20.      * @author zuly 
  21.      * 
  22.      * following jms ptp domain, use an simple text message to test 
  23.      * 
  24.      * A jms ptp sender will following the steps below! 
  25.      *     1> get an ConnectionFactory use JNDI Lookup Or Initial it yourself 
  26.      *     2> use this ConnectionFactory to start a jms connection
  27.      *        [spec to jms 1.1 apito get the main idea of it ] 
  28.      *     3> use connection to create a jms session 
  29.      *     4> get a queue destination / messege agent 
  30.      *     5> start the Producer[jms1.1 spec] by a session 
  31.      *     6> get messege Object or initial it yourself by implements the messegeor 
  32.      *        it’s sub interfaces 
  33.      *     7> call sender or send it selfing 
  34.      *     8> finallized the connection object or it will throw a warning to you! 
  35.      * 
  36.      * @param messege 
  37.      * @throws NamingException 
  38.      * @throws JMSException 
  39.      */  
  40.     public void sendingProcessing(String messege) throws NamingException, JMSException{  
  41.         Context ctx = new InitialContext();  
  42.         ConnectionFactory cf = (ConnectionFactory) ctx.lookup("java:JmsXA");  
  43.         Connection conn = cf.createConnection();  
  44.         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);  
  45.         Destination dest = (Queue) ctx.lookup("queue/A");  
  46.         MessageProducer msgp = session.createProducer(dest);  
  47.         QueueSender sender = (QueueSender) msgp;  
  48.         TextMessage msg = session.createTextMessage();  
  49.         msg.setText(messege);  
  50.         sender.send(msg);  
  51.         conn.close();  
  52.     }  
  53.      
  54.      
  55.      
  56.     /** 
  57.      * @author zuly 
  58.      * 
  59.      * following jms ptp domain, use an simple text message to test 
  60.      * 
  61.      * A jms ptp retriver will following the steps below! 
  62.      *     1> get an ConnectionFactory use JNDI Lookup Or Initial it yourself 
  63.      *     2> use this ConnectionFactory to start a jms connection 
  64.      *        [spec to jms 1.1 api to get the main idea of it ] 
  65.      *     3> use connection to create a jms session 
  66.      *     4> get a queue destination / messege agent 
  67.      *     5> retrive a consumer from session 
  68.      *     6> start the jms connection to retrivte the message 
  69.      *     7> get message from consumer 
  70.      *  
  71.      * @return textMessege 
  72.      * @throws NamingException 
  73.      * @throws JMSException 
  74.      */  
  75.     public String retriveingProcessing() throws NamingException, JMSException{  
  76.         Context ctx = new InitialContext();  
  77.         ConnectionFactory cf = (ConnectionFactory) ctx.lookup("java:JmsXA");  
  78.         Connection conn = cf.createConnection();  
  79.         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);  
  80.         Destination dest = (Queue) ctx.lookup("queue/A");  
  81.         MessageConsumer msgconsumer = session.createConsumer(dest);  
  82.         //MessageListener ml = new JmsListenner();  
  83.         //msgconsumer.setMessageListener(ml);  
  84.         conn.start();  
  85.         TextMessage msg = (TextMessage) msgconsumer.receive();  
  86.         conn.close();  
  87.         System.out.println("messege is" + msg.getText());  
  88.         return msg.getText();  
  89.     }  
  90. }  

注意retrive函数中comment的掉的两行,消息Listener的作用是实现异步通讯,但是它有一个约定,必须和发送者
保持物理上的分离,针对于jboss而言,就要求这个Listener必须跑在容器外面。这是一个很搞的问题,每天Jms的邮件列表里面都有无数的这样的 问题发过来。但是回复的人很少。我自己也从来不回复。 其实我也不清楚写这篇文章到底是出于什么目的,怕只是让这么一个简单的问题有一个回答而已。

把下面这个程序跑起来就可以异步接受消息了。

java 代码
 
  1. package com.javaeye.jms.jboss;  
  2.   
  3. import java.util.Properties;  
  4.   
  5. import javax.jms.Connection;  
  6. import javax.jms.ConnectionFactory;  
  7. import javax.jms.Destination;  
  8. import javax.jms.JMSException;  
  9. import javax.jms.MessageConsumer;  
  10. import javax.jms.MessageListener;  
  11. import javax.jms.Session;  
  12. import javax.naming.Context;  
  13. import javax.naming.InitialContext;  
  14. import javax.naming.NamingException;  
  15.   
  16. import com.javaeye.spring.services.jms.mdp.JmsListenner;  
  17.   
  18. public class JbossJmsAsync {  
  19.   
  20.     /** 
  21.      * @param args 
  22.      * @throws NamingException  
  23.      * @throws JMSException  
  24.      */  
  25.     public static void main(String[] args) throws NamingException, JMSException {  
  26.         Properties pops = new Properties();  
  27.         pops.setProperty("jboss.bind.address""0.0.0.0");  
  28.         pops.setProperty("java.naming.factory.initial""org.jnp.interfaces.NamingContextFactory");  
  29.         pops.setProperty("java.naming.factory.url.pkgs""org.jboss.naming:org.jnp.interfaces");  
  30.         pops.setProperty("java.naming.provider.url""localhost");  
  31.         Context ctx = new InitialContext(pops);  
  32.         ConnectionFactory cf = (ConnectionFactory) ctx.lookup("ConnectionFactory");  
  33.         Connection conn = cf.createConnection();  
  34.         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);  
  35.         Destination dest = (Destination) ctx.lookup("queue/A");  
  36.         MessageConsumer msgConsumer = session.createConsumer(dest);  
  37.         MessageListener ml = new JmsListenner();  
  38.         msgConsumer.setMessageListener(ml);   
  39.         conn.start();  
  40.     }  
  41.   
  42. }  

javaeye的主题好像是spring,为了迎合领导,下面我把这套东西跑在spring里面。同时我发现spring对jms的包装真的简单,而且还提供了一个模版,虽然这个模版的接口是在是很罗唆。

ps:今天是第1次用spring在reference里找了半天找不到方法注入的办法,于是google了一个注入办法,不合理的地方请大家指出。首先我通过方法来注入ConnectionFactory和Destination这两个对象来支撑jms环境

java 代码
 
  1. package com.javaeye.spring.services.jms.mdp;  
  2.   
  3. import java.util.Properties;  
  4.   
  5. import javax.jms.ConnectionFactory;  
  6. import javax.jms.Destination;  
  7. import javax.jms.Queue;  
  8. import javax.naming.Context;  
  9. import javax.naming.InitialContext;  
  10. import javax.naming.NamingException;  
  11.   
  12. public class UserJmsTransactionUtil {  
  13.   
  14.     private String connectionFactoryJndiLookUp;  
  15.      
  16.     private String destinationJndiLookUp;  
  17.      
  18.     private String localConnectionFactoryJndiLookUp;  
  19.      
  20.     private String containerType;  
  21.      
  22.      
  23.     public String getConnectionFactoryJndiLookUp() {  
  24.         return connectionFactoryJndiLookUp;  
  25.     }  
  26.   
  27.   
  28.   
  29.     public void setConnectionFactoryJndiLookUp(String connectionFactoryJndiLookUp) {  
  30.         this.connectionFactoryJndiLookUp = connectionFactoryJndiLookUp;  
  31.     }  
  32.   
  33.   
  34.   
  35.     public String getDestinationJndiLookUp() {  
  36.         return destinationJndiLookUp;  
  37.     }  
  38.   
  39.   
  40.   
  41.     public void setDestinationJndiLookUp(String destinationJndiLookUp) {  
  42.         this.destinationJndiLookUp = destinationJndiLookUp;  
  43.     }  
  44.   
  45.   
  46.   
  47.     public ConnectionFactory getConnectionFactory() throws NamingException{  
  48.         Context ctx = new InitialContext();  
  49.         ConnectionFactory cf = (ConnectionFactory) ctx.lookup(connectionFactoryJndiLookUp);  
  50.         return cf;  
  51.     }  
  52.      
  53.      
  54.     public Destination getJmsDestination() throws NamingException{  
  55.         Context ctx = new InitialContext();  
  56.         Destination dest = (Queue) ctx.lookup(destinationJndiLookUp);  
  57.         return dest;  
  58.     }  
  59.      
  60.      
  61.     public ConnectionFactory getQueueConnectionFactory() throws NamingException{  
  62.         Properties pops = new Properties();  
  63.         pops.setProperty("jboss.bind.address""0.0.0.0");  
  64.         pops.setProperty("java.naming.factory.initial""org.jnp.interfaces.NamingContextFactory");  
  65.         pops.setProperty("java.naming.factory.url.pkgs""org.jboss.naming:org.jnp.interfaces");  
  66.         pops.setProperty("java.naming.provider.url""localhost");  
  67.         Context ctx = new InitialContext(pops);  
  68.         ConnectionFactory cf = (ConnectionFactory) ctx.lookup(localConnectionFactoryJndiLookUp);  
  69.         return cf;  
  70.     }  
  71.      
  72.      
  73.     public Destination getLocalJmsDestination() throws NamingException{  
  74.         Properties pops = new Properties();  
  75.         pops.setProperty("jboss.bind.address""0.0.0.0");  
  76.         pops.setProperty("java.naming.factory.initial""org.jnp.interfaces.NamingContextFactory");  
  77.         pops.setProperty("java.naming.factory.url.pkgs""org.jboss.naming:org.jnp.interfaces");  
  78.         pops.setProperty("java.naming.provider.url""localhost");  
  79.         Context ctx = new InitialContext(pops);  
  80.         Destination dest = (Destination) ctx.lookup(destinationJndiLookUp);  
  81.         return dest;  
  82.     }  
  83.   
  84.   
  85.   
  86.     public String getLocalConnectionFactoryJndiLookUp() {  
  87.         return localConnectionFactoryJndiLookUp;  
  88.     }  
  89.   
  90.   
  91.   
  92.     public void setLocalConnectionFactoryJndiLookUp(  
  93.             String localConnectionFactoryJndiLookUp) {  
  94.         this.localConnectionFactoryJndiLookUp = localConnectionFactoryJndiLookUp;  
  95.     }     
  96. }

发送端的配置如下

xml 代码
 
  1. <beans>  
  2.     <bean id="userJmsUtil" class="com.javaeye.spring.services.jms.mdp.UserJmsTransactionUtil">  
  3.         <property name="connectionFactoryJndiLookUp" value="java:JmsXA"><!–</span–>property>  
  4.         <property name="destinationJndiLookUp" value="queue/A"><!–</span–>property>  
  5.         <property name="localConnectionFactoryJndiLookUp" value="ConnectionFactory"><!–</span–>property>  
  6.     <!–</span–>bean>  
  7.   
  8.     <bean id="connectionFactory" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">  
  9.         <property name="targetObject" ref="userJmsUtil"><!–</span–>property>  
  10.         <property name="targetMethod" value="getConnectionFactory"><!–</span–>property>  
  11.     <!–</span–>bean>  
  12.       
  13.     <bean id="queue" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">  
  14.         <property name="targetObject" ref="userJmsUtil"><!–</span–>property>  
  15.         <property name="targetMethod" value="getJmsDestination"><!–</span–>property>  
  16.     <!–</span–>bean>  
  17.           
  18.     <bean id="jmsQueue" class="org.springframework.jms.core.JmsTemplate">  
  19.         <property name="connectionFactory" ref="connectionFactory"><!–</span–>property>  
  20.         <property name="defaultDestination" ref="queue"><!–</span–>property>  
  21.         <property name="messageConverter">  
  22.             <bean class="org.springframework.jms.support.converter.SimpleMessageConverter"><!–</span–>bean>  
  23.         <!–</span–>property>  
  24.     <!–</span–>bean>  
  25. <!–</span–>beans>  

ps:javaeye的模版工具bug还真多,不管了.

如果使用Listenner的化,一样需要遵守发送者和接收者物理隔离的原则,我的做法是把发送者配到一个xml中,在把接受者配到另外一个xml中去,发送的配置绑定到容器里,接收者的跑在本地.否则spring初始化是过不去的.

下面这个程序是发送消息的程序.使用了spring的模版,发条消息比new个对象还简单.同时spring还提供了适配器的接口,一样通过声明式的配 置,这样可以在同一个接口里发送各种类型的消息了.同时支持事务,我还不知道这个有什么用呵呵,第1次使用嘛!但是就使用上来说,spring是最简单 的.2者都只需要注入一个对象而已.

java 代码
 
  1. @Test public void send(){  
  2.     ApplicationContext ac = new FileSystemXmlApplicationContext("jms.xml");  
  3.     BeanFactory bf = ac;  
  4.     JmsTemplate jt = (JmsTemplate) bf.getBean("jmsQueue");  
  5.     jt.convertAndSend("2132134");  
  6. }  

接收端的配置如下

xml 代码
 
  1. xml version="1.0" encoding="UTF-8"?>  
  2. >  
  3. <beans>  
  4.   
  5.     <bean id="listenner" class="com.javaeye.spring.services.jms.mdp.JmsListenner"><!–</span–>bean>  
  6.       
  7.     <bean id="userJmsUtil" class="com.javaeye.spring.services.jms.mdp.UserJmsTransactionUtil">  
  8.         <property name="connectionFactoryJndiLookUp" value="java:JmsXA"><!–</span–>property>  
  9.         <property name="destinationJndiLookUp" value="queue/A"><!–</span–>property>  
  10.         <property name="localConnectionFactoryJndiLookUp" value="ConnectionFactory"><!–</span–>property>  
  11.     <!–</span–>bean>  
  12.   
  13.     <bean id="localConnectionFactory" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">  
  14.         <property name="targetObject" ref="userJmsUtil"><!–</span–>property>  
  15.         <property name="targetMethod" value="getQueueConnectionFactory"><!–</span–>property>  
  16.     <!–</span–>bean>  
  17.       
  18.     <bean id="localDestination" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">  
  19.         <property name="targetObject" ref="userJmsUtil"><!–</span–>property>  
  20.         <property name="targetMethod" value="getLocalJmsDestination"><!–</span–>property>  
  21.     <!–</span–>bean>  
  22.       
  23.     <bean id="listenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">  
  24.         <property name="concurrentConsumers" value="5"><!–</span–>property>  
  25.         <property name="connectionFactory" ref="localConnectionFactory"><!–</span–>property>  
  26.         <property name="destination" ref="localDestination"><!–</span–>property>  
  27.         <property name="messageListener" ref="listenner"><!–</span–>property>  
  28.     <!–</span–>bean>  
  29. <!–</span–>beans>  

接收端由于需要从jbossmq里取ConnectionFactory和Destination,所以,我调用的是userJmsUtil的localLookup.这个函数的作用等同于发送者的那个函数,只不过前者是容器外获取,而后者是容器内的而已.

java 代码
 
  1. package com.javaeye.spring.services.jms.mdp;  
  2.   
  3. import javax.jms.JMSException;  
  4. import javax.jms.Message;  
  5. import javax.jms.MessageListener;  
  6. import javax.jms.TextMessage;  
  7.   
  8. public class JmsListenner implements MessageListener {  
  9.   
  10.     public void onMessage(Message message) {  
  11.         try {  
  12.             TextMessage msg = (TextMessage) message;  
  13.             System.out.println(msg.getText());  
  14.         } catch (JMSException e) { e.printStackTrace(); }  
  15.     }  
  16.   

spring对jms的整合里提到了一个jms provider ActiveMQ,要用一个开源框架要做的第一件事就是先跑一个demo起来,同样,我们要做的事还是获取ConnectionFactory和 Destination对象,还好,ActiveMQ的JNDI实现比jbossMQ还要简单,直接通过一个本地的Context就可以查到了,具体的可 以参照ActiveMQ官方的支持文档.

最后更新: 2007-03-23 08:49

归类于: Java — 海檐 @ 4:22 pm 评论(0)