[原创][求助]EJB 中消息驱动实体 在Weblogic 中的实现_Android, Python及开发编程讨论区_Weblogic技术|Tuxedo技术|中间件技术|Oracle论坛|JAVA论坛|Linux/Unix技术|hadoop论坛_联动北方技术论坛  
网站首页 | 关于我们 | 服务中心 | 经验交流 | 公司荣誉 | 成功案例 | 合作伙伴 | 联系我们 |
联动北方-国内领先的云技术服务提供商
»  游客             当前位置:  论坛首页 »  自由讨论区 »  Android, Python及开发编程讨论区 »
总帖数
1
每页帖数
101/1页1
返回列表
0
发起投票  发起投票 发新帖子
查看: 2883 | 回复: 0   主题: [原创][求助]EJB 中消息驱动实体 在Weblogic 中的实现        下一篇 
panpan.nie
注册用户
等级:大校
经验:4754
发帖:217
精华:2
注册:1970-1-1
状态:离线
发送短消息息给panpan.nie 加好友    发送短消息息给panpan.nie 发消息
发表于: IP:您无权察看 2014-10-21 17:14:50 | [全部帖] [楼主帖] 楼主

     EJB中的消息驱动bean(MessageDrivenBean,MDB)是设计用来专门处理基于消息请求的组件。一个MDB类必须实现MessageListener接口,当容器检测到bean 守候的队列的一条消息时,就调用onMessage() 方法,将消息作为参数传入。

什么时候使用消息驱动Bean?

1)当一个业务方法需要很长时间处理,而处理时间不确定

2)客户端调用后无需服务器立刻返回结果



EJB中消息驱动BeanMessageDrivenBeanMDB),其典型代表是JMSJava Message Service)的实现。

JMS 支持两种消息模型:

    PTPPoint-to-Point) 消息传递模型规定了一条消息只能传递给一个接收方。

Pub/subPublish/Subscribe消息传递模型允许一条消息传递给多个接收方。

消息驱动bean 实际上就是一个异步的JMS 消费者,而这个消费者一般做以下2件事

1)通过实现 onMessage() 方法来获取消息目的的消息对象

2)通过业务逻辑EJB 组件,对获取的信息执行业务逻辑

EJB容器中,和SessionBean一样都是有一个对象池来维护消息驱动bean的生命周期的。

实例代码:

1、我们在Weblogic的控制台上配置一个新的Queue 类型的JMS 消息目的,其JNDI名称为queue

   步骤:

        ① 配置持久化存储

        ② 配置JMS服务器

        ③ 配置JMS模块

        ④ 为JMS模块配置子部署

        ⑤ 配置消息目的地

详情可参考:JMS配置过程图解

2、代码实例

   1)我们需要在服务器端开发消息驱动Bean和消息驱动Bean相关的类

      TempDTO 类代表了 temp 表的实体

package ejb.message.dto;
import java.io.Serializable;
public class TempDTO implements Serializable
{
      private static final long serialVersionUID = -7614295090818744529L;
      private int id;
      private String name;
      private String address;
      public int getId()
      {
            return id;
      }
      public void setId(int id)
      {
            this.id = id;
      }
      public String getName()
      {
            return name;
      }
      public void setName(String name)
      {
            this.name = name;
      }
      public String getAddress()
      {
            return address;
      }
      public void setAddress(String address)
      {
            this.address = address;
      }
}


懒得写接口了,我直接写处理实体的业务类TempServic

package ejb.sessionbean;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import javax.annotation.Resource;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
import javax.sql.DataSource;
import ejb.message.dto.TempDTO;
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public class TempService
{
      @Resource(mappedName="MySqlDs")
      private DataSource dataSource;
      @Resource
      private SessionContext sessionContext;
      public boolean insertTemp(TempDTO temp)
      {
            if(temp ==null || temp.getName() == null)
            {
                  return false;
            }
            Connection conn = null;
            Statement stmt = null;
            try
            {
                  conn = dataSource.getConnection();
                  stmt = conn.createStatement();
                  StringBuffer sql = new StringBuffer("insert into temp values(");
                  sql.append(temp.getId()).append(",'");
                  sql.append(temp.getName()).append("','");
                  sql.append(temp.getAddress()).append("')");
                  System.out.println(sql.toString());
                  stmt.executeUpdate(sql.toString());
                  stmt.close();
                  conn.close();
                  return true;
            }
            catch (SQLException e)
            {
                  System.out.println("事务回滚");
                  sessionContext.setRollbackOnly();
                  e.printStackTrace();
                  return false;
            }
      }
}


消息驱动bean   ,该类可能有错误,连接Weblogic中的jms 的注解该如何写呢? 

需要重点说明的注解:@MessageDriven

@MessageDriven 注解有activationCofig 属性配置,它是对该驱动bean监听的JMS消息的一些配置西你想,使用@ActivationConfigProperty注解作为配置项,每个配置项都是由propertyName和propertyValue这种键值对儿作为属性的配置。 1):destinationType:表示消费目的类型,是PTP类型或者定制 

acknowledgeMode:JMS消息的确认模式,是否回复,还是自动回复 

destination:表示监听的消息目的JNDI名,此属性只对JBoss容器生效

mappedName:指定消息驱动Bean监听的消息目的,此属性配置对于Weblogic、Glassfish生效。 

package ejb.message;
import javax.ejb.ActivationConfigProperty;
import javax.ejb.EJB;
import javax.ejb.MessageDriven;
import javax.ejb.Stateless;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import ejb.message.dto.TempDTO;
import ejb.sessionbean.TempService;
@Stateless(mappedName="queue")
@MessageDriven(activationConfig = {
      @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
      @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
})
public class TempDTOMessageDrivenBean implements MessageListener
{
      @EJB(beanName = "TempService")
      private TempService tempService;
      @Override
      public void onMessage(Message msg)
      {
            if (msg != null)
            {
                  if (msg instanceof ObjectMessage)
                  {
                        ObjectMessage objmsg = (ObjectMessage)msg;
                        TempDTO temp;
                        try
                        {
                              temp = (TempDTO)objmsg.getObject();
                              tempService.insertTemp(temp);
                              System.out.println("执行插入业务完毕");
                        }
                        catch (JMSException e)
                        {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                        }
                  }
            }
      }
}


至此,可以说MDB 已经完成,只差部署在Weblogic服务器上,然后使用客户端去访问该EJB即可。但是,实际上我的测试并不成功,我始终都不明白这里,如果是把写好的EJB重新部署到了服务器上,那么这与JMS 又是通过什么关联的呢?

客户端访问

package ejb.messageDrivenBean.dto;
import java.util.Hashtable;
import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import ejb.message.dto.TempDTO;
public class MessageSender
{
      public static void main(String[] args)
      {
            try
            {
                  Hashtable cs = new Hashtable();
                  cs.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
                  cs.put(Context.PROVIDER_URL, "t3://localhost:7001");
                  InitialContext ctx = new InitialContext(cs);
                  //获取ConnectionFactory对象
                  QueueConnectionFactory factory = (QueueConnectionFactory)ctx.lookup("weblogic.jms.ConnectionFactory");
                  System.out.println(factory.toString()+" 连接工厂");
                  //创建QueueConnection对象
                  QueueConnection connection = factory.createQueueConnection();
                  //创建QueueSession对象,第一个参数表示事务自动提交,第二个参数标识一旦消息被正确送达,将自动发回响应
                  QueueSession session = connection.createQueueSession(false, QueueSession.AUTO_ACKNOWLEDGE);
                  //获得Destination对象
                  Queue queue = (Queue)ctx.lookup("queue");
                  //创建文本消息
                  //TextMessage msg = session.createTextMessage("世界,你好");
                  //创建发送者
                  QueueSender sender = session.createSender(queue);
                  // 创建对象消息
                  ObjectMessage msg = session.createObjectMessage();
                  TempDTO temp = new TempDTO();
                  temp.setName("xiaoming");
                  temp.setAddress("光谷");
                  msg.setObject(temp);
                  //发送消息
                  sender.send(msg);
                  System.out.println("end");
                  //关闭会话
                  session.close();
            }
            catch (NamingException e)
            {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }
            catch (JMSException e)
            {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
            }
      }
}


后记:

我将前面的EJB部署在Weblogic 上,然后执行客户端类,没有得到预期中的结果。

有几个我不确定的地方:

1) EJB 的部署方法真的像我理解的这样部署吗?具体见: EJB 中 Session Bean 的部署与实现

2) 消息驱动bean 与 JMS的JNDI 相关联的注解该怎么写呢?

3) 该怎样调测服务器上的EJB 可以正常的执行呢?

注:以上代码功能未调测通过,无实际意义。




赞(0)    操作        顶端 
总帖数
1
每页帖数
101/1页1
返回列表
发新帖子
请输入验证码: 点击刷新验证码
您需要登录后才可以回帖 登录 | 注册
技术讨论