hk2000c技术专栏

技术源于哲学,哲学来源于生活 关心生活,关注健康,关心他人

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  111 随笔 :: 1 文章 :: 28 评论 :: 0 Trackbacks

#

这是总结以前使用spring调用Oracle存储过程,并用cursor返回结果集的一个完整实例,希望能对大家有帮助。

1. 创建表:

代码
  1. create table TEST_USERS    
  2. (    
  3.   USER_ID  VARCHAR2(10) not null,    
  4.   NAME     VARCHAR2(10) not null,    
  5.   PASSWORD VARCHAR2(20) not null    
  6. )  

 

2. 创建存储过程:

代码
  1. create or replace package display_users_package is    
  2.      type search_results is ref cursor;    
  3.      procedure display_users_proc(results_out out search_results, userId in test_users.user_id%type);    
  4. end display_users_package;    
  5.   
  6. create or replace package body display_users_package is    
  7.      procedure display_users_proc(results_out out search_results, userId in test_users.user_id%type)    
  8.           is    
  9.           begin    
  10.           if userId is not null then    
  11.               open results_out for select * from test_users where user_id like userId || '%';    
  12.           else    
  13.               open results_out for  select * from test_users;    
  14.           end if;    
  15.       end display_users_proc;    
  16. end display_users_package;  

 

这个results_out是一个游标类型,用来返回查找的结果集。

3. 完整实现代码:

代码
  1. import java.sql.CallableStatement;   
  2. import java.sql.Connection;   
  3. import java.sql.ResultSet;   
  4. import java.sql.SQLException;   
  5. import java.util.ArrayList;   
  6. import java.util.HashMap;   
  7. import java.util.List;   
  8. import java.util.Map;   
  9.   
  10. import javax.sql.DataSource;   
  11.   
  12. import oracle.jdbc.OracleTypes;   
  13.   
  14. import org.springframework.dao.DataAccessException;   
  15. import org.springframework.jdbc.core.CallableStatementCallback;   
  16. import org.springframework.jdbc.core.CallableStatementCreator;   
  17. import org.springframework.jdbc.core.JdbcTemplate;   
  18.   
  19. import com.spring.stored.procedure.util.DataContextUtil;   
  20.   
  21. /**  
  22.  * @author Jane Jiao  
  23.  *  
  24.  */  
  25. public class SpringStoredProce {   
  26.        
  27.     public List<Map> execute(String storedProc, String params){   
  28.         List<Map> resultList = null;   
  29.         try{   
  30.             final DataSource ds = DataContextUtil.getInstance().getDataSource();   
  31.             final JdbcTemplate template = new JdbcTemplate(ds);   
  32.             resultList = (List<Map>)template.execute(new ProcCallableStatementCreator(storedProc, params),   
  33.                                                      new ProcCallableStatementCallback());   
  34.         }catch(DataAccessException e){   
  35.             throw new RuntimeException("execute method error : DataAccessException " + e.getMessage());   
  36.         }   
  37.          return resultList;   
  38.     }   
  39.        
  40.        
  41.     /**  
  42.      * Create a callable statement in this connection.  
  43.      */  
  44.     private class ProcCallableStatementCreator implements CallableStatementCreator {   
  45.         private String storedProc;   
  46.         private String params;   
  47.            
  48.        
  49.         /**  
  50.          * Constructs a callable statement.  
  51.          * @param storedProc                  The stored procedure's name.  
  52.          * @param params                      Input parameters.  
  53.          * @param outResultCount              count of output result set.  
  54.          */  
  55.         public ProcCallableStatementCreator(String storedProc, String params) {   
  56.             this.params = params;   
  57.             this.storedProc = storedProc;   
  58.         }   
  59.            
  60.         /**  
  61.          * Returns a callable statement  
  62.          * @param conn          Connection to use to create statement  
  63.          * @return cs           A callable statement  
  64.          */  
  65.         public CallableStatement createCallableStatement(Connection conn) {   
  66.             StringBuffer storedProcName = new StringBuffer("call ");   
  67.             storedProcName.append(storedProc + "(");   
  68.             //set output parameters   
  69.             storedProcName.append("?");   
  70.             storedProcName.append(", ");   
  71.                
  72.             //set input parameters   
  73.             storedProcName.append("?");   
  74.             storedProcName.append(")");   
  75.   
  76.             CallableStatement cs = null;   
  77.             try {   
  78.                 // set the first parameter is OracleTyep.CURSOR for oracel stored procedure   
  79.                 cs = conn.prepareCall(storedProcName.toString());   
  80.                 cs.registerOutParameter (1, OracleTypes.CURSOR);   
  81.                // set the sencond paramter   
  82.                 cs.setObject(2, params);   
  83.             } catch (SQLException e) {   
  84.                 throw new RuntimeException("createCallableStatement method Error : SQLException " + e.getMessage());   
  85.             }   
  86.             return cs;   
  87.         }   
  88.            
  89.     }   
  90.        
  91.     /**  
  92.      *   
  93.      * The ProcCallableStatementCallback return a result object,   
  94.      * for example a collection of domain objects.  
  95.      *  
  96.      */  
  97.     private class ProcCallableStatementCallback implements CallableStatementCallback {   
  98.            
  99.         /**  
  100.          * Constructs a ProcCallableStatementCallback.  
  101.          */  
  102.         public ProcCallableStatementCallback() {   
  103.         }   
  104.   
  105.         /**  
  106.          * Returns a List(Map) collection.  
  107.          * @param cs                       object that can create a CallableStatement given a Connection  
  108.          * @return resultsList             a result object returned by the action, or null  
  109.          */  
  110.         public Object doInCallableStatement(CallableStatement cs){   
  111.             List<Map> resultsMap =  new ArrayList<Map>();   
  112.             try {   
  113.                 cs.execute();    
  114.                 ResultSet rs = (ResultSet) cs.getObject(1);   
  115.                 while (rs.next()) {   
  116.                     Map<String, String> rowMap = new HashMap<String, String>();   
  117.                     rowMap.put("userId", rs.getString("USER_ID"));   
  118.                     rowMap.put("name", rs.getString("NAME"));   
  119.                     rowMap.put("password", rs.getString("PASSWORD"));   
  120.                     resultsMap.add(rowMap);   
  121.                 }      
  122.                 rs.close();   
  123.             }catch(SQLException e) {   
  124.                 throw new RuntimeException("doInCallableStatement method error : SQLException " + e.getMessage());   
  125.             }   
  126.             return resultsMap;   
  127.        }   
  128.     }   
  129. }   

 

4. 测试代码,在这里使用了Junit4测试:

代码
  1. import static org.junit.Assert.assertNotNull;    
  2. import static org.junit.Assert.assertTrue;    
  3.   
  4. import java.util.List;    
  5. import java.util.Map;    
  6.   
  7. import org.junit.After;    
  8. import org.junit.Before;    
  9. import org.junit.Test;    
  10.   
  11. /**   
  12.  * @author Jane Jiao   
  13.  *   
  14.  */    
  15. public class SpringStoredProceTest {    
  16.        
  17.    private SpringStoredProce springStoredProce;    
  18.   
  19.    /**   
  20.     * @throws java.lang.Exception   
  21.     */    
  22.    @Before    
  23.    public void setUp() throws Exception {    
  24.       springStoredProce = new SpringStoredProce();    
  25.    }    
  26.   
  27.    /**   
  28.     * @throws java.lang.Exception   
  29.     */    
  30.    @After    
  31.    public void tearDown() throws Exception {    
  32.       springStoredProce = null;    
  33.    }    
  34.   
  35.    /**   
  36.     * Test method for {@link com.hactl.listingframework.dao.SpringStoredProce#execute(java.lang.String, java.lang.String)}.   
  37.     */    
  38.    @Test    
  39.    public void testExecute() {    
  40.       final String storedProcName = "display_users_package.display_users_proc";    
  41.       final String param = "test";    
  42.       List<Map> resultList = springStoredProce.execute(storedProcName, param);    
  43.       assertNotNull(resultList);    
  44.       assertTrue(resultList.size() > 0);    
  45.       for (int i = 0; i < resultList.size(); i++) {    
  46.          Map rowMap = resultList.get(i);    
  47.          final String userId = rowMap.get("userId").toString();    
  48.          final String name = rowMap.get("name").toString();    
  49.          final String password = rowMap.get("password").toString();    
  50.          System.out.println("USER_ID=" + userId + "\t name=" + name + "\t password=" + password);    
  51.       }    
  52.           
  53.    }    
  54. }  

 

5. 测试的输出结果:

代码
  1. USER_ID=test1    name=aa    password=aa    
  2. USER_ID=test2    name=bb    password=bb    
  3. USER_ID=test3    name=cc    password=cc  
posted @ 2007-11-16 17:31 hk2000c 阅读(3523) | 评论 (2)编辑 收藏

内容或简介:
/**
调用数据库里的一个函数
一个函数本质上一个返回一个结果的存储过程,这个例子示范了怎么调用有in、out和in/out参数的函数
***********************************/
CallableStatement cs;
try {
// 调用一个没有参数的函数; 函数返回 a VARCHAR
// 预处理callable语句

  cs = connection.prepareCall("{? = call myfunc}");

// 注册返回值类型
cs.registerOutParameter(1, i);

// Execute and retrieve the returned value
cs.execute();
String retValue = cs.getString(1);

// 调用有一个in参数的函数; the function returns a VARCHAR
cs = connection.prepareCall("{? = call myfuncin(?)}");

// Register the type of the return value
cs.registerOutParameter(1, Types.VARCHAR);

// Set the value for the IN parameter
cs.setString(2, "a string");

// Execute and retrieve the returned value
cs.execute();
retValue = cs.getString(1);

// 调用有一个out参数的函数; the function returns a VARCHAR
cs = connection.prepareCall("{? = call myfuncout(?)}");

// Register the types of the return value and OUT parameter
cs.registerOutParameter(1, Types.VARCHAR);
cs.registerOutParameter(2, Types.VARCHAR);

// Execute and retrieve the returned values
cs.execute();
retValue = cs.getString(1);           // return value
String outParam = cs.getString(2);    // OUT parameter

// 调用有一个in/out参数的函数; the function returns a VARCHAR
cs = connection.prepareCall("{? = call myfuncinout(?)}");

// Register the types of the return value and OUT parameter
cs.registerOutParameter(1, Types.VARCHAR);
cs.registerOutParameter(2, Types.VARCHAR);

// Set the value for the IN/OUT parameter
cs.setString(2, "a string");

// Execute and retrieve the returned values
cs.execute();
retValue = cs.getString(1);           // return value
outParam = cs.getString(2);           // IN/OUT parameter
} catch (SQLException e) {
}

posted @ 2007-11-16 17:18 hk2000c 阅读(286) | 评论 (0)编辑 收藏

这段时间开始学习写存储过程,主要原因还是因为工作需要吧,本来以为很简单的,但几经挫折,豪气消磨殆尽,但总算搞通了,为了避免后来者少走弯路,特记述与此,同时亦对自己进行鼓励。

一:无返回值的存储过程

存储过程为:

CREATE OR REPLACE PROCEDURE TESTA(PARA1 IN VARCHAR2,PARA2 IN VARCHAR2) AS

BEGIN

   INSERT INTO HYQ.B_ID (I_ID,I_NAME) VALUES (PARA1, PARA2);

END TESTA;

然后呢,在java里调用时就用下面的代码:

package com.hyq.src;

import java.sql.*;

import java.sql.ResultSet;

public class TestProcedureOne {

 public TestProcedureOne() {

 }

 public static void main(String[] args ){

    String driver = "oracle.jdbc.driver.OracleDriver";

    String strUrl = "jdbc:oracle:thin:@127.0.0.1:1521: hyq ";

    Statement stmt = null;

    ResultSet rs = null;

    Connection conn = null;

    CallableStatement cstmt = null;

    try {

      Class.forName(driver);

      conn = DriverManager.getConnection(strUrl, " hyq ", " hyq ");

      CallableStatement proc = null;

      proc = conn.prepareCall("{ call HYQ.TESTA(?,?) }");

      proc.setString(1, "100");

      proc.setString(2, "TestOne");

      proc.execute();

    }

    catch (SQLException ex2) {

      ex2.printStackTrace();

    }

    catch (Exception ex2) {

      ex2.printStackTrace();

    }

    finally{

      try {

        if(rs != null){

          rs.close();

          if(stmt!=null){

            stmt.close();

          }

          if(conn!=null){

            conn.close();

          }

        }

      }

      catch (SQLException ex1) {

      }

    }

 }

}

当然了,这就先要求要建张表TESTTB,里面两个字段(I_IDI_NAME)。

二:有返回值的存储过程(非列表)

存储过程为:

CREATE OR REPLACE PROCEDURE TESTB(PARA1 IN VARCHAR2,PARA2 OUT VARCHAR2) AS

BEGIN

   SELECT INTO PARA2 FROM TESTTB WHERE I_ID= PARA1;

END TESTB;

java里调用时就用下面的代码:

package com.hyq.src;

public class TestProcedureTWO {

 public TestProcedureTWO() {

 }

 public static void main(String[] args ){

    String driver = "oracle.jdbc.driver.OracleDriver";

    String strUrl = "jdbc:oracle:thin:@127.0.0.1:1521:hyq";

    Statement stmt = null;

    ResultSet rs = null;

    Connection conn = null;

    try {

      Class.forName(driver);

      conn = DriverManager.getConnection(strUrl, " hyq ", " hyq ");

      CallableStatement proc = null;

      proc = conn.prepareCall("{ call HYQ.TESTB(?,?) }");

      proc.setString(1, "100");

      proc.registerOutParameter(2, Types.VARCHAR);

      proc.execute();

      String testPrint = proc.getString(2);

      System.out.println("=testPrint=is="+testPrint);

    }

    catch (SQLException ex2) {

      ex2.printStackTrace();

    }

    catch (Exception ex2) {

      ex2.printStackTrace();

    }

    finally{

      try {

        if(rs != null){

          rs.close();

          if(stmt!=null){

            stmt.close();

          }

          if(conn!=null){

            conn.close();

          }

        }

      }

      catch (SQLException ex1) {

      }

    }

 }

}

}

注意,这里的proc.getString(2)中的数值2并非任意的,而是和存储过程中的out列对应的,如果out是在第一个位置,那就是proc.getString(1),如果是第三个位置,就是proc.getString(3),当然也可以同时有多个返回值,那就是再多加几个out参数了。

三:返回列表

由于oracle存储过程没有返回值,它的所有返回值都是通过out参数来替代的,列表同样也不例外,但由于是集合,所以不能用一般的参数,必须要用pagkage.所以要分两部分,

1, 建一个程序包。如下:

CREATE OR REPLACE PACKAGE TESTPACKAGE  AS

 TYPE Test_CURSOR IS REF CURSOR;

end TESTPACKAGE;

2,建立存储过程,存储过程为:

CREATE OR REPLACE PROCEDURE TESTC(p_CURSOR out TESTPACKAGE.Test_CURSOR) IS

BEGIN

    OPEN p_CURSOR FOR SELECT * FROM HYQ.TESTTB;

END TESTC;

可以看到,它是把游标(可以理解为一个指针),作为一个out 参数来返回值的。

java里调用时就用下面的代码:

package com.hyq.src;

import java.sql.*;

import java.io.OutputStream;

import java.io.Writer;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import oracle.jdbc.driver.*;

public class TestProcedureTHREE {

 public TestProcedureTHREE() {

 }

 public static void main(String[] args ){

    String driver = "oracle.jdbc.driver.OracleDriver";

    String strUrl = "jdbc:oracle:thin:@127.0.0.1:1521:hyq";

    Statement stmt = null;

    ResultSet rs = null;

    Connection conn = null;

    try {

      Class.forName(driver);

      conn = DriverManager.getConnection(strUrl, "hyq", "hyq");

      CallableStatement proc = null;

      proc = conn.prepareCall("{ call hyq.testc(?) }");

      proc.registerOutParameter(1,oracle.jdbc.OracleTypes.CURSOR);

      proc.execute();

      rs = (ResultSet)proc.getObject(1);

      while(rs.next())

      {

          System.out.println("<tr><td>" + rs.getString(1) + "</td><td>"+rs.getString(2)+"</td></tr>");

      }

    }

    catch (SQLException ex2) {

      ex2.printStackTrace();

    }

    catch (Exception ex2) {

      ex2.printStackTrace();

    }

    finally{

      try {

        if(rs != null){

          rs.close();

          if(stmt!=null){

            stmt.close();

          }

          if(conn!=null){

            conn.close();

          }

        }

      }

      catch (SQLException ex1) {

      }

    }

 }

}

在这里要注意,在执行前一定要先把oracle的驱动包放到class路径里,否则会报错的。

 

posted @ 2007-11-16 17:15 hk2000c 阅读(223) | 评论 (0)编辑 收藏

关键字:   ActiveMQ    

ActiveMQ 实践之路(四) ActiveMQ 4.x +JBoss 4.x MDP实战篇

      在<<ActiveMQ 实践之路(三) ActiveMQ 4.x +JBoss 4.x 整合篇 >>里面我们比较详细的讲解了ActiveMQ与JBoss的整合,
既然选择了JBoss,那么项目里面或多或少都会使用到EJB,下面我们就详细地介绍如何在ActiveMQ 4.x+JBOSS 4.x环境下开发
Message Driven Bean,并且与使用jbossMQ在配置上作了比较详细地比较。这里的OrderMessage 仅仅是一个自动生成的Message Driven Bean,在onMessage方法里面,作日志输入。

 一. 配置ejb-jar.xml
      
        1.  ejb-jar.xml 不能使用XML DTD,需要使用XML Schema(XSD)
            
很多朋友可能使用XDoclet来生成ejb-jar.xml,我这里直接使用XDoclet生成的ejb-jar.xml是

<!--CTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dt-->

           但是在ActiveMQ+JBoss配置中间需要使用新的XML Schema才能完成对ra的定义,如下.

xml 代码
  1. <ejb-jar xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" version="2.1">  

 

2. ejb-jar.xml 直接使用JBossMQ的Message DriverBean 和使用ActiveMQ RA配置的区别

        (1) .使用JBossMQ的MessageDrivenBean的 ejb-jar.xml配置

xml 代码
  1. <!-- Message Driven Beans -->  
  2. <message-driven>  
  3.     <description>  
  4.           
  5.     description>  
  6.     <display-name>Name for OrderMessagedisplay-name>  
  7.     <ejb-name>OrderMessageejb-name>  
  8.     <ejb-class>com.mostone.ejb.OrderMessageejb-class>  
  9.     <transaction-type>Containertransaction-type>  
  10.     <acknowledge-mode>Auto-acknowledgeacknowledge-mode>  
  11.     <message-driven-destination>  
  12.         <destination-type>javax.jms.Queuedestination-type>  
  13.     message-driven-destination>  
  14. message-driven>  

     (2). 使用ActiveMQ RA配置的MessageDrivenBean的ejb-jar.xml配置

xml 代码
  1. <!-- Message Driven Beans -->  
  2. <message-driven>  
  3.     <description>  
  4.           
  5.     description>  
  6.     <display-name>Name for OrderMessagedisplay-name>  
  7.     <ejb-name>OrderMessageejb-name>  
  8.     <ejb-class>com.mostone.ejb.OrderMessageejb-class>  
  9.     <transaction-type>Containertransaction-type>  
  10.     <acknowledge-mode>Auto-acknowledgeacknowledge-mode>  
  11.     <!--使用了activetion-config-->  
  12.     <activation-config>  
  13.         <activation-config-property>  
  14.             <activation-config-property-name>destinationactivation-config-property-name>  
  15.             <activation-config-property-value>queue.outboundactivation-config-property-value>  
  16.         activation-config-property>  
  17.         <activation-config-property>  
  18.             <activation-config-property-name>destinationTypeactivation-config-property-name>  
  19.             <activation-config-property-value>javax.jms.Queueactivation-config-property-value>  
  20.         activation-config-property>  
  21.     activation-config>  
  22. message-driven>  

        其中destination,destinationType是ra.xml里面提供的配置属性,(这里官方的文档是Destination,DestinationType, 而实际上activemq-ra.rar里面的ra.xml是destination,destinationType,注意大小写区别)

. 配置jboss.xml
           大部分配置都是在jboss.xml里面.
         1.使用JBossMQ 和使用ActiveMQ RA配置Message Driven Bean的区别
           1.) 使用JBossMQ 的配置


xml 代码
  1. <message-driven>  
  2.     <ejb-name>OrderMessageejb-name>  
  3.     <destination-jndi-name>queue/testQueuedestination-jndi-name>  
  4. message-driven>  

         2.) 使用ActiveMQ RA的配置

xml 代码
  1. <message-driven>  
  2.     <ejb-name>ActiveMQMDPejb-name>  
  3.     <!-- 使用了resource-adapter-name -->  
  4.     <resource-adapter-name>activemq-ra.rarresource-adapter-name>  
  5.     <!-- 这里的configuration-name 需要和后面container-name 的名字相同 -->  
  6.     <configuration-name>ActiveMQ Message Driven Beanconfiguration-name>  
  7. message-driven>  

        2. jboss.xml 配置invoker proxy和container 支持ActiveMQ RA

xml 代码
  1. <invoker-proxy-bindings>  
  2.     <invoker-proxy-binding>  
  3.         <name>activemq-message-driven-beanname>  
  4.         <invoker-mbean>defaultinvoker-mbean>  
  5.         <proxy-factory>org.jboss.ejb.plugins.inflow.JBossMessageEndpointFactoryproxy-factory>  
  6.         <proxy-factory-config>  
  7.             <endpoint-interceptors>  
  8.                 <interceptor>org.jboss.proxy.ClientMethodInterceptorinterceptor>  
  9.                 <interceptor>org.jboss.ejb.plugins.inflow.MessageEndpointInterceptorinterceptor>  
  10.                 <interceptor>org.jboss.proxy.TransactionInterceptorinterceptor>  
  11.                 <interceptor>org.jboss.invocation.InvokerInterceptorinterceptor>  
  12.             endpoint-interceptors>  
  13.         proxy-factory-config>  
  14.     invoker-proxy-binding>  
  15. invoker-proxy-bindings>  

MessageDrivenBean的container配置,这里的必须和上面的相同 才能起作用.


 

xml 代码
  1. <container-configurations>  
  2.     <container-configuration>  
  3.         <container-name>ActiveMQ Message Driven Beancontainer-name>  
  4.         <call-logging>falsecall-logging>  
  5.         <invoker-proxy-binding-name>activemq-message-driven-beaninvoker-proxy-binding-name>  
  6.         <container-interceptors>  
  7.             <interceptor>org.jboss.ejb.plugins.ProxyFactoryFinderInterceptorinterceptor>  
  8.                 <interceptor>org.jboss.ejb.plugins.LogInterceptorinterceptor>  
  9.                 <interceptor>org.jboss.ejb.plugins.RunAsSecurityInterceptorinterceptor>  
  10.                 <!-- CMT -->  
  11.                 <interceptor transaction="Container">org.jboss.ejb.plugins.TxInterceptorCMTinterceptor>  
  12.                 <interceptor transaction="Container">org.jboss.ejb.plugins.CallValidationInterceptorinterceptor>  
  13.                 <interceptor transaction="Container" metricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptorinterceptor>  
  14.                 <interceptor transaction="Container">org.jboss.ejb.plugins.MessageDrivenInstanceInterceptorinterceptor>  
  15.                 <!-- BMT -->  
  16.                 <interceptor transaction="Bean">org.jboss.ejb.plugins.MessageDrivenInstanceInterceptorinterceptor>  
  17.                 <interceptor transaction="Bean">org.jboss.ejb.plugins.MessageDrivenTxInterceptorBMTinterceptor>  
  18.                 <interceptor transaction="Bean">org.jboss.ejb.plugins.CallValidationInterceptorinterceptor>  
  19.                 <interceptor transaction="Bean" metricsEnabled="true">org.jboss.ejb.plugins.MetricsInterceptorinterceptor>  
  20.                 <interceptor>org.jboss.resource.connectionmanager.CachedConnectionInterceptorinterceptor>  
  21.         container-interceptors>  
  22.         <instance-pool>org.jboss.ejb.plugins.MessageDrivenInstancePoolinstance-pool>  
  23.         <instance-cache>instance-cache>  
  24.         <persistence-manager>persistence-manager>  
  25.         <container-pool-conf>  
  26.                 <MaximumSize>100MaximumSize>  
  27.         container-pool-conf>  
  28.         container-configuration>  
  29. container-configurations>  

以上就是ActiveMQ+JBoss InBound 的配置

三.在Servlet中通过发送消息,验证上面的Message Driven Bean

     为了验证这个MessageDrivenBean能够正常工作,我使用一个很简单的servlet向这个queue发送消息,前一篇的activemq-ds.xml 已经提供在启动的时候绑定了JNDI activemq/QueueConnectionFactory,activemq/queue/outbound,我们直接使用就行了,

java 代码
  1. try {   
  2.         initialContext = new InitialContext();   
  3.         QueueConnectionFactory connectionFactory = (QueueConnectionFactory) initialContext   
  4.                 .lookup("java:activemq/QueueConnectionFactory");   
  5.            Connection con=connectionFactory.createConnection();   
  6.         Session session =  con.createSession(false, Session.AUTO_ACKNOWLEDGE);   
  7.   
  8.         Queue queue = (Queue) initialContext.lookup("activemq/queue/outbound");   
  9.         MessageProducer producer = session.createProducer(queue);   
  10.         TextMessage txtMessage = session.createTextMessage();   
  11.         txtMessage.setText("A");   
  12.         producer.send(txtMessage);   
  13.         producer.close();   
  14.         session.close();   
  15.         con.close();   
  16.            
  17.     } catch (NamingException e) {   
  18.         // TODO Auto-generated catch block   
  19.         e.printStackTrace();   
  20.     } catch (JMSException e) {   
  21.         // TODO Auto-generated catch block   
  22.         e.printStackTrace();   
  23.     }   

四.关于durable方式订阅topic的补充说明
     使用durable方式,你需要在ejb-jar.xml中额外的配置,subscriptionDurability,clientId,subscriptionName

xml 代码
  1. <activation-config>  
  2.     <activation-config-property>  
  3.         ......   
  4.         <activation-config-property>  
  5.             <activation-config-property-name>subscriptionDurabilityactivation-config-property-name>  
  6.             <activation-config-property-value>Durableactivation-config-property-value>  
  7.         activation-config-property>  
  8.         <activation-config-property>  
  9.             <activation-config-property-name>clientIdactivation-config-property-name>  
  10.             <activation-config-property-value>fooactivation-config-property-value>  
  11.         activation-config-property>  
  12.         <activation-config-property>  
  13.             <activation-config-property-name>subscriptionNameactivation-config-property-name>  
  14.             <activation-config-property-value>baractivation-config-property-value>  
  15.         activation-config-property>  
  16.         ......   
  17.     activation-config-property>  
  18. activation-config>  

 

ok 这样就可以使用durable方式订阅topic了。

参考文档:
        JBoss Integration
       ActiveMQ Inbound Communication
    ActiveMQ Outbound Communication


posted @ 2007-11-16 17:10 hk2000c 阅读(535) | 评论 (0)编辑 收藏

关键字:   ActiveMQ    

      ActiveMQ本身是开源项目,所以采用ActiveMQ的项目往往也是以其他开源软件共同构建,目前主流开源应用服务器有Boss,geronimo,JOnAs,而其中geronimo 默认的JMS Provider就是ActiveMQ,那我们就着重介绍ActiveMQ与JBoss,JOnAs的整合方案

本文参考了 Integrating Apache ActiveMQ with JBossJBoss Integration,再根据笔者实际整合经验总结而成。

 一.整合需要的环境.
              jdk1.5
              jboss-4.0.5.GA
              activemq-ra-4.1.0-incubator.rar  (在ActiveMQ 4.*  lib\optional 目录里面有对应的ra的压缩包)
   开始整合前请确保jboss能够正确的启动起来。

             二.整合步骤

              1. 步骤一: 解压activemq-rar-4.1.0-incubator.rar 到 jboss-4.0.5.GA\server\default\deploy\activemq-ra.rar (这个是目录名字) 下面是activemq-rar.rar目录下面的文件和子目录,请注意红色标记的地方(后面会逐一说明,整合的过程)

              activeio-core-3.0.0-incubator.jar
              activemq-core-4.1.0-incubator.jar
              activemq-ra-4.1.0-incubator.jar
              backport-util-concurrent-2.1.jar
              commons-logging-1.0.3.jar
              derby-10.1.1.0.jar
              geronimo-j2ee-management_1.0_spec-1.0.jar
              spring-2.0.jar
              spring-1.2.6.jar
              xbean-spring-2.7.jar
              broker-config.xml
              META-INF 
 2.步骤二. 删除多余的spring-1.2.6.jar,由于4.1.0的ra里面包含了2个不同版本的spring会触发一个exception的产生,https://issues.apache.org/activemq/browse/AMQ-1124, 而且为了以后能够使用新的spring schema配置方式,我们这里会删除spring-1.2.6.jar,保留spring-2.0.jar。(最新的snapshot version的ra已经去掉了这个多余的spring-1.2.6.jar).

               3.步骤三: 修改META-INF\ra.xml,让JBoss使用broker-config.xml 作为默认的配置文件配置borker. 修改下面的地方

  1. <config-property-value>config-property-value>              
  2. <!--  <config-property-value>xbean:broker-config.xml</config-property-value>-->  

      改为:

  1. <!-- <config-property-value></config-property-value> -->  
  2. <config-property-value>xbean:broker-config.xmlconfig-property-value>  

    表示使用broker-config.xml来配置启动ActiveMQ.
 
                 4.步骤四: 修改borker-config.xml,默认的borker-config.xml会产生一个错误,无论是我使用的版本还是最后的snapshot版本,默认的borker-config.xml都会让xbean-spring 2.7(snapshot 使用的是2.8)抛出exception.解决的办法如下
       将        
  1. <beans xmlns="http://activemq.org/config/1.0">  
  2.           <broker useJmx="true" >    
     
     改为
 
  1. <beans>  
  2. <broker useJmx="true" xmlns="http://activemq.org/config/1.0">  
 
   即可
       
              5.步骤五: 将xbean-spring-2.7.jar (或者是2.8) 复制到jboss-4.0.5.GA\server\default\lib下面
 
          三 使用整合完毕的ActiveMQ作为ds绑定到JBoss的JNDI服务。
                编写jboss-4.0.5.GA\server\default\depoly\activemq-ds.xml
xml 代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE connection-factories   
  3.     PUBLIC "-//JBoss//DTD JBOSS JCA Config 1.5//EN"   
  4.     "http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd">  
  5.   
  6. <connection-factories>  
  7.    <tx-connection-factory>  
  8.       <jndi-name>activemq/QueueConnectionFactory</jndi-name>  
  9.       <xa-transaction/>  
  10.       <track-connection-by-tx/>  
  11.       <rar-name>activemq-ra.rar</rar-name>  
  12.       <connection-definition>javax.jms.QueueConnectionFactory</connection-definition>  
  13.       <ServerUrl>tcp://localhost:61616</ServerUrl>  
  14.       <min-pool-size>1</min-pool-size>  
  15.       <max-pool-size>200</max-pool-size>  
  16.       <blocking-timeout-millis>30000</blocking-timeout-millis>  
  17.       <idle-timeout-minutes>3</idle-timeout-minutes>  
  18.    </tx-connection-factory>  
  19.   
  20.    <tx-connection-factory>  
  21.       <jndi-name>activemq/TopicConnectionFactory</jndi-name>  
  22.       <xa-transaction/>  
  23.       <track-connection-by-tx/>  
  24.       <rar-name>activemq-ra.rar</rar-name>  
  25.       <connection-definition>javax.jms.TopicConnectionFactory</connection-definition>  
  26.       <ServerUrl>tcp://localhost:61616</ServerUrl>  
  27.       <min-pool-size>1</min-pool-size>  
  28.       <max-pool-size>200</max-pool-size>  
  29.       <blocking-timeout-millis>30000</blocking-timeout-millis>  
  30.       <idle-timeout-minutes>3</idle-timeout-minutes>  
  31.    </tx-connection-factory>  
  32.       
  33.    <mbean code="org.jboss.resource.deployment.AdminObject" name="activemq.queue:name=outboundQueue">  
  34.       <attribute name="JNDIName">activemq/queue/outbound</attribute>  
  35.       <depends optional-attribute-name="RARName">jboss.jca:service=RARDeployment,name=&apos;activemq-ra.rar&apos;</depends>  
  36.       <attribute name="Type">javax.jms.Queue</attribute>  
  37.       <attribute name="Properties">PhysicalName=queue.outbound</attribute>  
  38.    </mbean>  
  39.   
  40.    <mbean code="org.jboss.resource.deployment.AdminObject" name="activemq.topic:name=inboundTopic">  
  41.       <attribute name="JNDIName">activemq/topic/inbound</attribute>  
  42.       <depends optional-attribute-name="RARName">jboss.jca:service=RARDeployment,name=&apos;activemq-ra.rar&apos;</depends>  
  43.       <attribute name="Type">javax.jms.Topic</attribute>  
  44.       <attribute name="Properties">PhysicalName=topic.inbound</attribute>  
  45.    </mbean>  
  46.   
  47. </connection-factories>  
               
               启动JBoss.如果看见以下信息就表示ActiveMQ已经成功启动,并且使用上面的ds配置文件成功地将topic/queue绑定到了JNDI服务上。
              ......
              [TransportConnector] Connector tcp://localhost:61616 Started
              [NetworkConnector] Network Connector bridge Started
              [BrokerService] ActiveMQ JMS Message Broker (localhost, ID:MyNoteBook-2165-1173250880171-1:0) started
              ......
              [ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:service=ConnectionFactoryBinding,name=activemq/QueueConnectionFactory' to JNDI name 'java:activemq/QueueConnectionFactory'
              [ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:service=ConnectionFactoryBinding,name=activemq/TopicConnectionFactory' to JNDI name 'java:activemq/TopicConnectionFactory'
                [AdminObject] Bound admin object 'org.apache.activemq.command.ActiveMQQueue' at 'activemq/queue/outbound'
                [AdminObject] Bound admin object 'org.apache.activemq.command.ActiveMQTopic' at 'activemq/topic/inbound
                ......
              
             四.验证ActiveMQ+JBoss
             这里你可以使用简单的jms  client连接到broker-config.xml里面的协议连接器上面,默认的是tcp://localhost:61616
             在后面我们会在此整合基础上开发Message Driver Bean和使用spring MDP 2种构架 来验证本次ActiveMQ+JBoss的整合。
posted @ 2007-11-16 17:06 hk2000c 阅读(582) | 评论 (0)编辑 收藏

  作者 cctvx1
    程度: 入门


    一.安装ActiveMQ

       首先去http://activemq.apache.org/download.html 下载最新版本4.1.0release (http://activemq.apache.org/activemq-410-release.html),
    解压apache-activemq-4.1-incubator.zip(或者apache-activemq-4.1-incubator.tar.gz)目录如下:
      
       +bin       (windows下面的bat和unix/linux下面的sh)
       +conf      (activeMQ配置目录,包含最基本的activeMQ配置文件)
       +data      (默认是空的)
       +docs      (index,replease版本里面没有文档,-.-b不知道为啥不带)
       +example   (几个例子
       +lib       (activemMQ使用到的lib)
       -apache-activemq-4.1-incubator.jar  (ActiveMQ的binary)
       -LICENSE.txt      
       -NOTICE.txt       
       -README.txt
       -user-guide.html


       你可以使用bin\activemq.bat(activemq) 启动,如果一切顺利,你就会看见类似下面的信息
      (细节可能不一样,比如路径,或者jmx,jdbc信息)

  ACTIVEMQ_HOME: D:\java\framework_and_lib\activemq\apache-activemq-4.1-incubator\
bin\..
Loading message broker from: xbean:activemq.xml
INFO  BrokerService                  - ActiveMQ null JMS Message Broker (localho
st) is starting
INFO  BrokerService                  - For help or more information please see:
http://incubator.apache.org/activemq/
INFO  ManagementContext              - JMX consoles can connect to service:jmx:r
mi:///jndi/rmi://localhost:1099/jmxrmi
INFO  JDBCPersistenceAdapter         - Database driver recognized: [apache_derby
_embedded_jdbc_driver]
INFO  DefaultDatabaseLocker          - Attempting to acquire the exclusive lock
to become the Master broker
INFO  DefaultDatabaseLocker          - Becoming the master on dataSource: org.ap
ache.derby.jdbc.EmbeddedDataSource@1d840cd
INFO  JournalPersistenceAdapter      - Journal Recovery Started from: Active Jou
rnal: using 5 x 20.0 Megs at: D:\java\framework_and_lib\activemq\apache-activemq
-4.1-incubator\activemq-data\journal
INFO  JournalPersistenceAdapter      - Journal Recovered: 0 message(s) in transa
ctions recovered.
INFO  TransportServerThreadSupport   - Listening for connections at: tcp://P-SUW
EI:61616
WARN  MulticastDiscoveryAgent        - brokerName not set
INFO  TransportConnector             - Connector default Started
INFO  TransportServerThreadSupport   - Listening for connections at: stomp://P-S
UWEI:61613
INFO  TransportConnector             - Connector stomp Started
INFO  NetworkConnector               - Network Connector default Started
INFO  BrokerService                  - ActiveMQ JMS Message Broker (localhost, I
D:P-SUWEI-1207-1170916242296-1:0) started     

         *。几个小提示
  1. 这个仅仅是最基础的ActiveMQ的配置,很多地方都没有配置因此不要直接使用这个配置用于生产系统
  2. 有的时候由于端口被占用,导致ActiveMQ错误,ActiveMQ可能需要以下端口1099(JMX),61616(默认的TransportConnector)
  3. 如果没有物理网卡,或者MS的LoopBackAdpater Multicast会报一个错误

     二. 测试你的ActiveMQ
       
          由于ActiveMQ是一个独立的jms provider,所以我们不需要其他任何第三方服务器就可以马上做我们的测试了.编译
     example目录下面的程序
         
   ProducerTool/ConsumerTool 是JMS参考里面提到的典型应用,Producer产生消息,Consumer消费消息
   而且这个例子还可以加入参数帮助你测试刚才启动的本地ActiveMQ或者是远程的ActiveMQ

   ProducerTool [url] broker的地址,默认的是tcp://localhost:61616
                [true|flase] 是否使用topic,默认是false
         [subject] subject的名字,默认是TOOL.DEFAULT
         [durabl] 是否持久化消息,默认是false
         [messagecount] 发送消息数量,默认是10
         [messagesize] 消息长度,默认是255
         [clientID] durable为true的时候,需要配置clientID
         [timeToLive] 消息存活时间
         [sleepTime] 发送消息中间的休眠时间
         [transacte]  是否采用事务

         
          ConsumerTool [url] broker的地址,默认的是tcp://localhost:61616
                [true|flase] 是否使用topic,默认是false
         [subject] subject的名字,默认是TOOL.DEFAULT
         [durabl] 是否持久化消息,默认是false
         [maxiumMessages] 接受最大消息数量,0表示不限制
       
         [clientID] durable为true的时候,需要配置clientID
        
         [transacte]  是否采用事务
         [sleepTime]  接受消息中间的休眠时间,默认是0,onMeesage方法不休眠
         [receiveTimeOut] 接受超时

          我们这样可以使用:
   java -classpath .\apache-activemq-4.1-incubator.jar;example\bin ProducerTool  tcp://192.168.3.142:61616 test.mysubject
   java -classpath .\apache-activemq-4.1-incubator.jar;example\bin ConsumerTool  tcp://192.168.3.142:61616 test.mysubject

   当然你可以使用上面的参数进行更复杂的测试,持久,事务

   如果出现下面的信息,恭喜你,你的ActiveMQ已经能够工作了
        
  Connecting to URL: tcp://192.168.3.142:61616
  Publishing a Message with size 255 to queue: TOOL.DEFAULT
  Using non-durable publishing
  Sleeping between publish 0 ms
  Sending message: Message: 0 sent at: Thu Feb 08 15:05:34 CST 2007  ...
  Sending message: Message: 1 sent at: Thu Feb 08 15:05:34 CST 2007  ...
         。。。。。。。。


  Connecting to URL: tcp://192.168.3.142:61616
  Consuming queue: test.mysubject
         Using non-durable subscription
         Received: Message: 0 sent at: Thu Feb 08 14:51:34 CST 2007  ...
         Received: Message: 1 sent at: Thu Feb 08 14:51:34 CST 2007  ...
  。。。。


         三.小结
     
      我们已经下载,启动,并且用程序测试了我们的ActiveMQ,而后面将在这个能跑得ActiveMQ进一步的走下去,一步一步展示ActiveMQ的高级特性。

posted @ 2007-11-16 17:05 hk2000c 阅读(4544) | 评论 (0)编辑 收藏

本篇主要讲解在未使用其他框架(Spring)整合情况下,独立基于ActiveMQ,使用JMS规范进行消息通信。
    
     一.JMS回顾
       因为ActiveMQ是一个JMS Provider的实现,因此在开始实作前,有必要复习下JMS的基础知识
    Java Message Service (JMS)是sun提出来的为J2EE提供企业消息处理的一套规范,JMS目前有2套规范还在使用JMS 1.0.2b和1.1. 1.1已经成为主流的JMS Provider事实上的标准了.
      *1.1主要在session上面有一些重要改变,比如支持建立同一session上的transaction,让他支持同时发送P2P(Queue)消息和接受
Topic消息。
      
       在JMS中间主要定义了2种消息模式Point-to-Point (点对点),Publich/Subscribe Model (发布/订阅者),
    其中在Publich/Subscribe 模式下又有Nondurable subscription和durable subscription (持久化订阅)2种消息处理方式。
    
     下面是JMS规范基本的接口和实现
     JMS Common Interfacse PTP-Specific Interface   Pub/Sub-specific interfaces
     ConnectionFactory     QueueConnectionFactory   TopicConnectionFactory
     Connection            QueueConnection          TopicConnection
     Destination           Queue                    Topic
     Session               QueueSession             TopiSession
     MessageProducer       QueueSender              TopicPublisher
     MessageConsumer       QueueReceiver/QueueBrwer TopicSubscriber


     二.使用Queue

         下面以ActiveMQ example的代码为主进行说明
        
        1. 使用ActiveMQ的Connection,ConnectionFactory 建立连接,注意这里没有用到pool
       

java 代码
  1. import org.apache.activemq.ActiveMQConnection   
  2. import org.apache.activemq.ActiveMQConnectionFactory   

        //建立Connection

java 代码
  1. protected Connection createConnection() throws JMSException, Exception {   
  2.      ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, pwd, url);   
  3.      Connection connection = connectionFactory.createConnection();   
  4.      if (durable && clientID!=null) {   
  5.          connection.setClientID(clientID);   
  6.      }   
  7.      connection.start();   
  8.      return connection;   
  9.     }  

        //建立Session
  

java 代码
  1. protected Session createSession(Connection connection) throws Exception {   
  2.          Session session = connection.createSession(transacted, ackMode);   
  3.          return session;   
  4.         }   

        2。发送消息的代码
 //建立QueueSession
 

java 代码
  1. protected MessageProducer createProducer(Session session) throws JMSException {   
  2.         Destincation destination = session.createQueue("queue.hello");   
  3.         MessageProducer producer = session.createProducer(destination);   
  4.         producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);   
  5.            
  6.         if( timeToLive!=0 )   
  7.             producer.setTimeToLive(timeToLive);   
  8.         return producer;   
  9.         }   

         //使用Producer发送消息到Queue
    

java 代码
  1. producer.send(message);   

       
        3。接受消息,在JMS规范里面,你可以使用
  

java 代码
  1. QueueReceiver/QueueBrowser直接接受消息,但是更多的情况下我们采用消息通知方式,即实现MessageListener接口   
  2.  public void onMessage(Message message) {   
  3.  //process message   
  4.  }   
  5.           
  6.  //set MessageListner ,receive message   
  7.  Destincation destination = session.createQueue("queue.hello");   
  8.  consumer = session.createConsumer(destination);   
  9.  consumer.setMessageListener(this);   

       
        以上就是使用jms queue发送接受消息的基本方式

 
     三 Topic

        1. 建立连接
   

java 代码
  1. protected Connection createConnection() throws JMSException, Exception {      
  2.         ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory(user, pwd, url);      
  3.         Connection connection = connectionFactory.createConnection();      
  4.         //如果你要使用DurableSubScription 方式,你必须为connection设置一个ClientID      
  5.         if (durable && clientID!=null) {      
  6.             connection.setClientID(clientID);      
  7.         }      
  8.         connection.start();      
  9.         return connection;      
  10.        }      

       2. 建立Session

java 代码
  1. protected Session createSession(Connection connection) throws Exception {      
  2.         Session session = connection.createSession(transacted, ackMode);      
  3.         return session;      
  4.         }    

 3.创建Producer 发送消息到Topic   
       

java 代码
  1. //create topic on  session   
  2.        topic = session.createTopic("topic.hello");   
  3.  producer = session.createProducer(topic);   
  4.        //send message    
  5.        producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);   
  6.  producer.send(message);   


 4.创建Consumer接受消息(基本上和Queue相同)

java 代码
  1. Destincation destination  = session.createTopic("topic.hello");      
  2. MessageConsumer consumer = session.createConsumer(destination);      
  3. consumer.setMessageListener(this);      
  4.            
  5.      //如果你使用的是Durable Subscription方式,你必须在建立connection的时候      
  6.      //设置ClientID,而且建立comsumer的时候使用createDurableSubscriber方法,为他指定一个consumerName。      
  7.  //connection.setClientID(clientId);      
  8.  //consumer = session.createDurableSubscriber((Topic) destination, consumerName);   

       
 四:连接ActiveMQ的方式
        ActiveMQConnectionFactory 提供了多种连接到Broker的方式activemq.apache.org/uri-protocols.html

 常见的有
 vm://host:port     //vm
 tcp://host:port    //tcp
 ssl://host:port    //SSL
 stomp://host:port  //stomp协议可以跨语言,目前有很多种stomp client 库(java,c#,c/c++,ruby,python...);

posted @ 2007-11-16 17:05 hk2000c 阅读(8312) | 评论 (2)编辑 收藏

郁闷了三天,今天终于把JMS弄出来了,就是发送消息,然后消息监听器接收到了消息后发送邮件给管理员

先看web.xml里面关于activemq的invoke

<!--调用activemq -->
    <context-param >
     <param-name>brokerURI </param-name >
     <param-value>/WEB-INF/activemq.xml </param-value >
    </context-param>
   
    <listener>
       <listener-class>org.activemq.web.SpringBrokerContextListener</listener-class>
    </listener>


郁闷了三天,今天终于把JMS弄出来了,就是发送消息,然后消息监听器接收到了消息后发送邮件给管理员

先看web.xml里面关于activemq的invoke

<!--调用activemq -->
    <context-param >
     <param-name>brokerURI </param-name >
     <param-value>/WEB-INF/activemq.xml </param-value >
    </context-param>
   
    <listener>
       <listener-class>org.activemq.web.SpringBrokerContextListener</listener-class>
    </listener>

然后是在上下文中定义的JmsTemplate和activemq监听

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "
http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

<!--JMS Template-->
    <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory">
      <bean class="org.activemq.ActiveMQConnectionFactory">
       <property name="brokerURL">
        <value>tcp://localhost:61616</value>
       </property>
      </bean>
     </property>
     
      <property name="defaultDestinationName" value="Hello.Queue"/>
    </bean>

   <bean id="activeMQContainer" class="org.activemq.jca.JCAContainer">
     <property name="workManager">
       <bean id="workManager" class="org.activemq.work.SpringWorkManager"/>
     </property>

     <property name="resourceAdapter">
       <bean id="activeMQResourceAdapter"
           class="org.activemq.ra.ActiveMQResourceAdapter">
         <property name="serverUrl" value="tcp://localhost:61616"/>
       </bean>
     </property>
   </bean>
 

  <!--监听 Message 的Message Driven POJO-->
    <bean id="HelloPlaceBean" class="com.officetao.jms.HelloMDP" autowire="byName"/>

  <bean id="HelloMDP" factory-method="addConnector" factory-bean="activeMQContainer">
     <property name="activationSpec">
       <bean class="org.activemq.ra.ActiveMQActivationSpec">
         <property name="destination" value="Hello.Queue"/>
         <property name="destinationType" value="javax.jms.Queue"/>
       </bean>
     </property>
     <property name="ref" value="HelloBean" />
   </bean>

</beans>

建立一个模拟的发送消息的bean,内容如下

final String mailContent = "新增单号为0000的订单, 金额";
  try {
            if (jmsTemplate != null)
                jmsTemplate.send(new MessageCreator() {
                    public Message createMessage(Session session)
                            throws JMSException {
                        Message message = session.createMessage();
                        message.setStringProperty("content", mailContent);
                        return message;
                    }
                });
        }
        catch (Exception e) {
            logger.error("JMS error when place order:", e);
        }

最后就是监听消息然后采取行动的bean


public class HelloMDP implements MessageListener {


 
 public void onMessage(javax.jms.Message arg0) {
  
  try   {  
            subAuthenticator   subauth   =   new   subAuthenticator("邮箱登陆名","密码");//smtp验证   authenticator  
            props.put("mail.smtp.host","smtp.163.com");  
            props.put("mail.smtp.auth","true");  
            session   =   Session.getInstance(props,subauth);  
            MimeMessage   message   =   new   MimeMessage(session);  
            message.setRecipient(Message.RecipientType.TO,new   InternetAddress("
接收邮件的邮箱"));  
            message.setFrom(new   InternetAddress("
自己的邮箱"));  
            message.setSubject("ok");  
            message.setText("if you see it,it works!");  
            Transport.send(message);
        }  
        catch(AuthenticationFailedException   e1){  
            System.out.println("SMTP认证出错!");  
        }  
        catch   (MessagingException   e)   {  
            e.printStackTrace();
        }  
 
}

public   static   Properties   props   =   System.getProperties();
public   static   Session   session   =   null;  

/**  
*此内部类定义了smtp认证方法  
*/  
public   class   subAuthenticator   extends   Authenticator{  
private   String   userName;  
private   String   password;  
public   subAuthenticator(String   user,String   pass){  
    userName=user;  
    password=pass;  
}  
public   PasswordAuthentication   getPasswordAuthentication(){  
    return   new   PasswordAuthentication(userName,password);  
}  

posted @ 2007-11-16 16:49 hk2000c 阅读(1105) | 评论 (0)编辑 收藏

 JMS做为J2EE的高级部分一直蒙着一层神秘的面纱,作为JMS的定制者SUN只规定了JMS规范,象很多其他SUN产品一样被多家厂商提供了具体的实现。但是作为tomcat和RESIN(今年初宣布全部支持J2EE规范)。这些面向低端但却被广泛应用的服务器本身并不对JMS提供支持。庆幸的是openjms和activeMQ两家开源软件提供了插件式的支持。

    在应用了一些开发框架如spring的项目里如果要使用到JMS,虽然SPRING提供了部分对JMS的支持但经过我一段时间的应用发现,OO的封装在某些地方反而成为开发过程中的障碍。在实现诸如监听之类的代码段里使人非常的懊恼,即使用callback(回调)有些东西仍然不能够很好的被取到。

下面就一些TOMCAT上面JMS的支持既实现做一下整理。

1.很自然的你需要下载JMS实现,如:opnerJMS或者activeMQ .下载地址www.jmsopen.com 或www.activeMQ.com

2.服务器下载以后的具体配置在以上两个网站上都有很详细的说明,就不再列举了。

3.和WEB服务器的整合,首先要配置应用的web.xml这个文件配置如下:

1  <context-param>
            2  <param-name>brokerURI</param-name>
            3  <param-value>/WEB-INF/activemq.xml</param-value>
            4  </context-param>
            5
            6  <listener>
            7  <listener-class>org.activemq.web.SpringBrokerContextListener</listener-class>
            8  </listener>


将这一段代码放到web.xml里。注意到activemq.xml文件,是jms服务器的具体配置:

<?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE beans PUBLIC
            "-//ACTIVEMQ//DTD//EN"
            "http://activemq.org/dtd/activemq.dtd">
            <beans>
            <!-- ===================== -->
            <!-- ActiveMQ Broker Configuration -->
            <!-- ===================== -->
            <broker>
            <connector>
            <tcpServerTransport
            uri="tcp://localhost:61616"
            useAsyncSend="true"
            maxOutstandingMessages="50"/>
            </connector>
            <!-- to enable Stomp support uncomment this
            <connector>
            <serverTransport
            uri="stomp://localhost:61626"/>
            </connector>
            -->
            <persistence>
            <jdbcPersistence
            dataSourceRef="oracle-ds"/>
            </persistence>
            </broker>
            <!-- ======================= -->
            <!-- JDBC DataSource Configurations -->
            <!-- ======================= -->
            <!-- The Derby Datasource
            that will be used by the Broker -->
            <bean id="derby-ds" class=
            "org.apache.commons.dbcp.BasicDataSource"
            destroy-method="close">
            <property name="driverClassName">
            <value>
            org.apache.derby.jdbc.EmbeddedDriver
            </value>
            </property>
            <property name="url">
            <!-- Use a URL like
            'jdbc:hsqldb:hsql://localhost:9001'
            if you want to connect to a remote hsqldb -->
            <value>
            jdbc:derby:derbydb;create=true
            </value>
            </property>
            <property name="username">
            <value></value>
            </property>
            <property name="password">
            <value></value>
            </property>
            <property name="poolPreparedStatements">
            <value>true</value>
            </property>
            </bean>
            </beans>


此时,在启动你的TOMCAT的时候会看到JMS服务器已经绑到了上面。
posted @ 2007-11-16 16:48 hk2000c 阅读(3888) | 评论 (0)编辑 收藏

     摘要: [原创] SSO(Single Sign-on) in Action(上篇) 1. SSO 原理浅谈        SSO 是一个非常大的主题,我对这个主题有着深深的感受,自从广州 UserGroup 的论坛成立以来,无数网友都在尝试使用开源的 CAS , Kerberos 也提供另外一种方式的 SSO ,即基于 Windows ...  阅读全文
posted @ 2007-11-16 16:27 hk2000c 阅读(358) | 评论 (0)编辑 收藏

仅列出标题
共11页: 上一页 1 2 3 4 5 6 7 8 9 下一页 Last