基于容器的用户安全管理系统

  作者:板桥banq

上页

3.4  Session Bean实现

本项目需要一个Facade类统一实现用户资料的操作,建立无状态Session Bean 为UserManager的EJB。在这个类中,主要实现有关用户的新增、删除或修改。代码如下:
public class UserManagerBean implements SessionBean {
  private final static Logger logger = Logger.getLogger(UserManagerBean.class);

  SessionContext sessionContext;
  UserHome userHome;
  UsersRolesHome usersRolesHome;
  UsersGroupsHome usersGroupsHome;
  RoleManagerLocalHome roleManagerLocalHome;
  SequenceGeneratorLocalHome sequenceHome;
  // ejbCreate()一般只执行一次,以后再调用时不再执行,通过ejbCreate()可以
   //实现一些类属性的缓冲
  public void ejbCreate() throws CreateException {
    try {
      ServiceLocator serviceLocator = new ServiceLocator();
      userHome = (UserHome) serviceLocator.getLocalHome(
          JNDINames.USER_HOME);
      sequenceHome = (SequenceGeneratorLocalHome)
    serviceLocator.getLocalHome(JNDINames.SEQUENCEGENERATOR_HOME);
      usersRolesHome = (UsersRolesHome) serviceLocator.getLocalHome(
            JNDINames.USERSROLES_HOME);
      usersGroupsHome = (UsersGroupsHome) serviceLocator.getLocalHome(
          JNDINames.USERSGROUPS_HOME);
      roleManagerLocalHome = (RoleManagerLocalHome)
      serviceLocator.getLocalHome( JNDINames.ROLEMANAGER_HOME);
    } catch (Exception ex) {
      logger.error("Service Locate error:" + ex);
      throw new CreateException();
    }
  }
  //从Sequence EJB组件获得自增的序列号
  public int getNewId(String name) {
    try {
      SequenceGeneratorLocal seq = sequenceHome.create();
      return seq.nextSequenceNumber(name);
    } catch (Exception ex) {
      throw new EJBException("Error generating id for : " + name + ex);
    }
  }
  //创建一个用户
  public void createUser(UserEvent userEvent) {
    User userDTO = userEvent.getUser();
    if (nameIsExisted(userDTO)){
      logger.debug("name :" + userDTO.getName() + " has been exsited");
      userEvent.setErrors(Constants.NAME_EXISTED);
      return;
    }
    if (emailIsExisted(userDTO)){
      logger.debug("eamil :" + userDTO.getEmail() + " has been exsited");
      userEvent.setErrors(Constants.EMAIL_EXISTED);
      return;
    }
    UserLocal userLocal = null;
    try {
      String id = Integer.toString(getNewId(Constants.SEQUENCE_USER_NAME));
      userLocal = userHome.create(id);
      userDTO.setUserId(id);
      updateUser(userEvent);
      //创建该用户的默认角色
      createUsersRoles(userDTO);
    } catch (Exception ex) {
      logger.error(ex);
      throw new EJBException("create user error : " + ex);
    }
  }
  //检查是否有重复用户名
  private boolean nameIsExisted(User userDTO) {
    boolean found = false;
    User user = getUserByName(userDTO.getName());
    if (user != null)
      found = true;
    return found;
  }
  //检查是否有重复E-mail
  private boolean emailIsExisted(User userDTO) {
    boolean found = false;
    User user = getUserByEmail(userDTO.getEmail());
    if (user != null)
      found = true;
    return found;
  }
  //创建用户默认角色,也就是建立用户和角色的对应关系
  public void createUsersRoles(User userDTO) throws Exception {
    UsersRoles usersRoles = null;
    try {
      RoleManagerLocal roleManagerLocal = roleManagerLocalHome.create();
      String roleId = roleManagerLocal.getRoleId(Role.USER);
      usersRoles = usersRolesHome.create(userDTO.getUserId(), roleId);
    } catch (Exception ex) {
      logger.error(ex);
      throw new EJBException("createUsersRoles error : " + ex);
    }
  }
  //修改用户资料
  public void updateUser(UserEvent userEvent) {
    User userDTO = userEvent.getUser();
    UserLocal userLocal = null;
    try {
      userLocal = userHome.findByPrimaryKey(userDTO.getUserId());
      userLocal.setName(userDTO.getName());
      userLocal.setEmail(userDTO.getEmail());
      userLocal.setPassword(userDTO.getPassword());

    } catch (Exception ex) {
      logger.error(ex);
    }
  }
  //以E-mail获得用户
  public User getUserByEmail(String emailAddress) {
    emailAddress = emailAddress.trim().toLowerCase();
    UserLocal userLocal = null;
    try {
      userLocal = userHome.findByEmail(emailAddress);
    } catch (Exception ex) {
      logger.warn(ex);
    }
    return getUser(userLocal);
  }
  //以Id查询用户
  public User getUserById(String userId) {
    userId = userId.trim().toLowerCase();
    logger.debug(" userId =" + userId);
    UserLocal userLocal = null;
    try {
      userLocal = userHome.findByPrimaryKey(userId);
    } catch (Exception ex) {
      logger.warn(ex);
    }
    return getUser(userLocal);
  }
  //获得用户User实例 DTO模式
  private User getUser(UserLocal userLocal) {
    if (userLocal == null)
      return null;
    logger.debug(" userId =" + userLocal.getUserId());
    User user = new UserModel(userLocal.getUserId());
    user.setEmail(userLocal.getEmail());
    user.setName(userLocal.getName());
    user.setPassword(userLocal.getPassword());
    user.setUserId(userLocal.getUserId());
    return user;
  }
  //获得用户的Principal
  public User getUserByPrincipal() throws Exception, PrincipalException {
    Principal principal = null;
    try {
      principal = sessionContext.getCallerPrincipal();
    } catch (Exception e) {
      logger.error(e);
      throw new PrincipalException();
    }
    if (principal == null) {
      throw new PrincipalException();
    }
    String name = principal.getName();
    return getUserByName(name);
   }
   …
}
在UserManager中基本实现了用户资料的相关操作。在本项目中,还有用户组以及角色的相关操作。为避免UserManager中包含过多逻辑,需要再建立一个无状态Session Bean,如RoleManager。
用户注册登录后,其Session生存周期的活动将一直维持到其离开系统。因此可以建立一个有状态Session Bean保存用户的资料如User实例,这样不必经常到数据库读取。有状态Session Bean还可以作为一个总的Facade类,分别包含其他Facade群,这样,系统会显得条理分明。创建有状态Session Bean代码如下:
public class SecurityFacadeBean extends EJBControllerBean {
  private final static Logger logger = Logger.getLogger(SecurityFacadeBean.class);

  SessionContext sessionContext;
  RoleManagerLocalHome roleManagerLocalHome;
  UserManagerLocalHome userManagerLocalHome;
  AsyncSenderLocalHome asyncSenderLocalHome;
  private User user = null;
  …
  //获得Facade类 UsermanagerLocal
  public UserManagerLocal getUserManager() {
    UserManagerLocal userManagerLocal = null;
    try {
      userManagerLocal = userManagerLocalHome.create();
    } catch (Exception ex) {
      logger.error("getUserManager() error:" + ex);
    }
    return userManagerLocal;
  }
  //获得Facade类RoleManagerLocal
  public RoleManagerLocal getRoleManager() {
    RoleManagerLocal roleManagerLocal = null;
    try {
      roleManagerLocal = roleManagerLocalHome.create();
    } catch (Exception ex) {
      logger.error("getRoleManager() error:" + ex);
    }
    return roleManagerLocal;
  }
  //获得当前session的User实例
  public User getUser() {
    if (this.user != null)
      return this.user;
    logger.debug("user is null, get it from principal ...");
    setUser();
    return this.user;
  }
 //密码丢失查询
 public boolean getPassword(String email) {
    logger.debug("--> enter getpassword");
    boolean success = false;
    try {
      User user = getUserManager().getUserByEmail(email);
      if (user == null)
        return success;
      String subject = " 用户名和密码";
      StringBuffer buffer = new StringBuffer();
      buffer.append(" 用户:").append(user.getName());
      buffer.append(" 密码:").append(user.getPassword());
      if (sendMail(user.getEmail(), subject, buffer.toString()))
        success = true;
    } catch (Exception ex) {
      logger.error(" getPassword: " + ex);
    }
    return success;
  }
  //调用E-mail发送组件,通过JMS发出E-mail
  public boolean sendMail(String toAddress, String subject, String content) {
    try {
      logger.debug(" -->enter send mail");
      Mail mail = new Mail();
      mail.setToAddress(toAddress);
      mail.setFromAddress("banq@jdon.com");
      mail.setSubject(subject);
      mail.setContent(content);
      String msg = MailUtil.getMsgFromMail(mail);
      AsyncSenderLocal asyncSenderLocal = asyncSenderLocalHome.create();
      asyncSenderLocal.sendAMessage(msg);
      logger.debug(" -->send mail to: " + toAddress + " successfully!");
      return true;
    } catch (Exception ex) {
      logger.error(" sendMail() error : " + ex);
      return false;
    }
  }
  //判断当前用户是否是管理员
  public boolean isAdministrator() {
    return sessionContext.isCallerInRole(Role.ADMINISTRATOR);
  }
  //判断当前用户是否是普通用户
  public boolean isUser() {
    return sessionContext.isCallerInRole(Role.USER);
  }
  …
}
可以看到,SecurityFacadeBean是继承接口框架系统中的EJBController,SecurityFacadeBean作为一个总的Facade类,通过接口框架负责和Web实现联系,如图6-6所示。
1
图6-6  EJB Facade群


SecurityFacadeBean中isCallerInRole是用来判断当前用户是否属于可以访问该资源的角色,访问该资源角色的权限在ejb-jar.xml中定义。


3.5  EJB容器安全配置

J2EE容器的安全管理框架以角色为联系纽带,分两个方向。一个是用户资料系统;另外一个是访问权限系统。后者是通过web.xml或ejb-jar.xml配置实现的。
在本项目中,为了限制角色对某些类或方法的访问权限,可以在ejb-jar.xml中设置。
<assembly-descriptor>
<security-role>
     <description>the role is super user </description>
      <role-name>Admin</role-name>
</security-role>
<security-role>
     <description>register user</description>
     <role-name>User</role-name>
</security-role>
<method-permission>
     <role-name>User</role-name>
     <method>
          <ejb-name>RoleManager</ejb-name>
           <method-name>*</method-name>
      </method>
</method-permission>

</assembly-descriptor>
在本EJB中定义了两个角色:Admin和User(当然可以根据实际情况定义角色)。具体的权限是在method-permission中设置,可以指定某个类的具体方法,“*”表示所有的方法。
既然定义了角色,那么在具体类的配置中也需要声明具体角色的指向,如SecurityFacadeBean的ejb-jar配置如下:
<session>
            <display-name>SecurityFacade</display-name>
            <ejb-name>SecurityFacade</ejb-name>
            <local-home>
com.jdon.security.auth.ejb.SecurityFacadeLocalHome
</local-home>
            <local>com.jdon.security.auth.ejb.SecurityFacadeLocal</local>
            <ejb-class>com.jdon.security.auth.ejb.SecurityFacadeBean</ejb-class>
            <session-type>Stateful</session-type>
            <transaction-type>Container</transaction-type>
            <ejb-local-ref>
                <description />
                <ejb-ref-name>ejb/UserManager</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <local-home>
                   com.jdon.security.auth.ejb.UserManagerLocalHome
                </local-home>
                <local>com.jdon.security.auth.ejb.UserManagerLocal</local>
                <ejb-link>UserManager</ejb-link>
            </ejb-local-ref>
            <ejb-local-ref>
                <description />
                <ejb-ref-name>ejb/RoleManager</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <local-home>
                    com.jdon.security.auth.ejb.RoleManagerLocalHome
                </local-home>
                <local>com.jdon.security.auth.ejb.RoleManagerLocal</local>
                <ejb-link>RoleManager</ejb-link>
            </ejb-local-ref>
            <ejb-local-ref>
                <description />
                <ejb-ref-name>ejb/AsyncSender</ejb-ref-name>
                <ejb-ref-type>Session</ejb-ref-type>
                <local-home>
                   com.jdon.asyncsender.ejb.AsyncSenderLocalHome
                 </local-home>
                <local>com.jdon.asyncsender.ejb.AsyncSenderLocal</local>
                <ejb-link>AsyncSender</ejb-link>
            </ejb-local-ref>
            <security-role-ref>
                <description />
                <role-name>User</role-name>
                <role-link>User</role-link>
            </security-role-ref>
</session>
在最后几行,指定角色名User指向了security-role中的User,两者名称可以不一样,但role-link必须和security-role是一致的。role-name可以是RegisterUser,那么在SecurityFacadeBean调用就是isCallerInRole("RegisterUse"),检查当前访问SecurityFacadeBean的角色是否是容器中已经定义的、允许访问的角色RegisterUse。
通过ejb-jar.xml的配置,使得角色的访问权限的设置和管理变得非常方便。在系统运行时,有可能有新的角色加入或原有角色权限的修改。这些都可以通过ejb-jar.xml进行修改,修改完毕,运行中的J2EE系统立即生效。
具体ejb-jar.xml的权限配置可参考Sur公司EJB 标准手册。
为了使该EJB的权限机制激活,还需要在相应的容器配置文件中进行适当配置。如在JBoss中部署该EJB时,需要在jboss.xml加入:
<security-domain>java:/jaas/SecurityRealm</security-domain>
这表示该EJB的安全域将使用JAAS中的SecurityRealm配置。关于如何设置JBoss的SecurityRealm将在部署配置相关章节中讨论。

4  JMS 邮件发送组件

在J2EE中,JMS(Java Message System)提供了一种异步处理机制的实现。JMS通过异步的、非阻塞的消息传递,将消息的生产者和使用者松散的联系在一起。对于使用者,它无所谓是谁产生了消息或者是在何时产生的。这就能够建立一种动态的、灵活的可靠的系统。所谓可靠,因为JMS将每个消息都保存起来,只有确保本消息处理后才会完全放弃。否则,将会反复提交处理。这种可靠的机制使得JMS能够成功的在证券、银行系统中得到广泛应用。
JMS中的消息类型有两种:Topic和Queue。Topic的操作是使用发布/订阅(publish/subscribe)的方式;Queue的操作是点对点(ponit to point)的方式。
publish/subscribe:发布者(publisher)发布消息到Topic,订阅者(subsribe)从Topic订阅消息,订阅者的数量是不受限制的。
ponit to point:点对点传输消息,建立在消息队列Queue的基础上,每个消息使用者只对应一个消息队列,不像publish/subscribe那样可以有很多消息使用者。
本项目中,可以由单个独立的程序来实现邮件发送,这个程序作为一个消息使用者,只需一个就可以了,因此使用Queue来实现。
JMS在消息到达消息使用者,有两种——同步和异步。
同步是指消息使用者明确地主动地调用从Queue或Topic中得到消息,一直进行循环直至一个消息到达,或者也可以设定超时时间。很明显这个方法是比较耗费CPU资源的。
异步接受是指消息到达时,主动通知消息使用者,消息使用者可以实现message listener接口。这样每当消息到达时,JMS provider 会通过调用这个listener的onMessage方法来传输这个消息。该方法相对要有效率,邮件发送组件将采取这种方式。
下面描述这个邮件发送组件是如何具体实现的。

在这个组件中,消息生产者应该是具体应用程序。但是组件为了达到通用目的,需要建立一个专门的消息生产者,可以称之为AsyncSender,(异步发送器)。具体应用程序通过调用这个异步发送器,将邮件内容发给JMS的Queue,负责邮件发送的类作为这个Queue另外一端的消息使用者,在Queue中有需要发送的邮件出现时就立即将它从Queue中取出,实现邮件发送。


4.1  消息发送器

AsyncSender属于消息生产者,它是具体应用系统直接调用的,可以使用无状态Session Bean来实现。
在AsyncSender中,首先要通过JNDI获得一个ConnectionFactory,创建一个QueueConnection实例,这样就获得与JMS Provider的一个连接。再由这个QueueConnection创建一个QueueSession,这样就启动了一个和JMS Provider连接相关的线程,这个线程可以是发送或接收消息。
AsyncSender还需要通过JNDI获得一个已经存在的Queue。这样,通过将发送消息的线程和这个Queue联系起来,表示向这个Queue中发送消息。
AsyncSender的bean代码如下:
/**
 *  JMS客户端 消息生产者
 * <p>Copyright: Jdon.com Copyright (c) 2003</p>
 * <p>Company: 上海汲道计算机技术有限公司</p>
 * @author banq
 * @version 1.0
 */
public class AsyncSenderBean implements SessionBean {

  private final static Logger logger = Logger.getLogger(AsyncSenderBean.class);

  SessionContext sessionContext;
  private SessionContext sc;
  private Queue queue;
  private QueueConnectionFactory qFactory;

  public void ejbCreate() throws CreateException {
    try {
      ServiceLocator serviceLocator = new ServiceLocator();
        //查询JNDI获得QueueConnectionFactory
      qFactory =
          serviceLocator.getQueueConnectionFactory(
          JNDINames.QUEUE_CONNECTION_FACTORY);
       //查询JNDI 获得已经存在的Queue
      queue = serviceLocator.getQueue(JNDINames.ASYNC_SENDER_QUEUE);
    } catch (ServiceLocatorException sle) {
      throw new EJBException("AsyncSenderEJB.ejbCreate failed", sle);
    }
  }
  //发送邮件的方法
  public void sendAMessage(String msg) {
    QueueSession session = null;
    QueueConnection qConnect = null;
    QueueSender qSender = null;
    try {
      //创建一个QueueConnection
      qConnect = qFactory.createQueueConnection();
      //创建一个QueueSession
      session = qConnect.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
      logger.debug("-->>create sender");
      //创建一个发送者
      qSender = session.createSender(queue);
      TextMessage jmsMsg = session.createTextMessage();
      //设置发送内容
      jmsMsg.setText(msg);
      //向目标queue发送
      qSender.send(jmsMsg);
      logger.debug("-->>send ok msg:"+msg);
    } catch (Exception e) {
      logger.error("sendAMessage error " + e);
      throw new EJBException("askMDBToSendAMessage: Error!", e);
    } finally {
      try {
        if (qConnect != null) {          qConnect.close();        }
      } catch (Exception e) {}
    }
  }
  …
}
其中,QueueConnectionFactory的JNDI名称是java:comp/env/jms/QueueConnection Factory,而Queue的JNDI名称是java:comp/env/jms/MailQueue,分别需要在ejb-jar.xml中落实这两个环境变量。
在ejb-jar.xml中,有:
<session>
     <display-name>AsyncSender</display-name>
     <ejb-name>AsyncSender</ejb-name>
     <local-home>
        com.jdon.asyncsender.ejb.AsyncSenderLocalHome
     </local-home>
     <local>com.jdon.asyncsender.ejb.AsyncSenderLocal</local>
    <ejb-class>com.jdon.asyncsender.ejb.AsyncSenderBean</ejb-class>
     <session-type>Stateless</session-type>
     <transaction-type>Container</transaction-type>
      <!-- resource-ref一般用来设置数据库资源或JMS Provider资源  -->
     <resource-ref>
          <description />
                <res-ref-name>jms/QueueConnectionFactory</res-ref-name>
                <res-type>javax.jms.QueueConnectionFactory</res-type>
                <res-auth>Container</res-auth>
   </resource-ref>
   <!--  和resource-ref指定的资源相关的环境配置 -->
     <resource-env-ref>
          <description />
          <resource-env-ref-name>jms/MailQueue</resource-env-ref-name>
          <resource-env-ref-type>javax.jms.Queue</resource-env-ref-type>
    </resource-env-ref>
</session>
QueueConnectionFactory和Queue与具体JMS容器有关。在JBoss 3.0中,提供了现成的QueueConnectionFactory和Queue,当然也可以参考JBoss手册自己设置建立这两个配置。
这里使用JBoss的ConnectionFactory和已经存在的/testQueue,其JNDI名称写法分别是java:/ConnectionFactory和queue/testQueue,这些都是JBoss的规定写法。如果是Topic,那么就需要写成topic/testTopic,testTopic/testQueue是JBoss容器在启动时建立好的一个Topic/Queue。在jboss.xml中,写入下列代码:
  <session>
        <ejb-name>AsyncSender</ejb-name>
        <local-jndi-name>AsyncSenderLocal</local-jndi-name>
        <resource-ref>
             <res-ref-name>jms/QueueConnectionFactory</res-ref-name>
             <jndi-name>java:/ConnectionFactory</jndi-name>
        </resource-ref>
        <resource-env-ref>
             <resource-env-ref-name>jms/MailQueue</resource-env-ref-name>
             <jndi-name>queue/testQueue</jndi-name>
        </resource-env-ref>
  </session>
通过上面开发,消息的生产者功能基本完成,通过调用EJB AsyncSender的sendAMessage(String msg)方法,可以将msg发送到JMS的Queue中。


4.2  MDB

在Queue的另外一端是消息的使用者。MDB(Message-Driven Beans)专门处理JMS异步消息,Session Bean和Entity Bean只允许同步地去发送消息和接收消息,不支持异步。MDB是一个message listener,它能够从一个Queue或一个durable subscription中可靠地接收消息。
MDB与一个普通的消息使用者客户端的区别是,EJB容器将自动做下面的事情,无需应用者再自己编程实现:
创建一个消息接受者(QueueReceiver/TopicSubscriber)接收消息。在部署时,将destination和ConnectionFactory与MDB联合起来。在JBoss中通过指定destination-jndi-name来实现。
自动实现message listener接口(无需调用setMessageListener方法)。
容器自动指定了消息签收模式。
因此,使用MDB作为消息的使用者就非常简单,而且没有home和remote接口,只有一个bean类。建立MDB MailerBean代码如下:
/**
 * JMS消息使用者 EJB消息Bean
 * <p>Copyright: Jdon.com Copyright (c) 2003</p>
 * <p>Company: 上海汲道计算机技术有限公司</p>
 * @author banq
 * @version 1.0
 */
public class MailerBean implements MessageDrivenBean, MessageListener {
  private final static Logger logger = Logger.getLogger(MailerBean.class);
  MessageDrivenContext messageDrivenContext;
  public void ejbCreate(){
  }
  public void ejbRemove() {}
  //当消息来时,将自动激活这个方法
  public void onMessage(Message msg){
    logger.debug(" --> enter onMessage ..");
    TextMessage textMessage = null;
    String xmlMailMessage = null;
    Mail recMail = null;
    try {
      textMessage = (TextMessage) msg;
      xmlMailMessage = textMessage.getText();
      //将XML文本转换成Mail对象实例
      recMail = MailUtil.getMailFromMsg(xmlMailMessage);
      logger.debug(" --> begin connect the server ....");
      sendMail(recMail);
      logger.debug(" --> send mail ok ");
    } catch (JMSException je) {
      logger.error("MailerMDB.onMessag error" + je);
      throw new EJBException("MailerMDB.onMessage" + je);
    } catch (Exception me) {
      logger.error("MailerMDB.onMessag error" + me);
    }
  }
  //发送邮件
  private void sendMail(Mail mail) throws Exception{
    getMailHelper().createAndSendMail(mail);
  }
  private MailHelper getMailHelper(){
    return (new MailHelper());
  }
  public void setMessageDrivenContext(MessageDrivenContext messageDrivenContext) {
    this.messageDrivenContext = messageDrivenContext;
  }
}
MailHelper是一个专门使用J2EE容器的mail service发送邮件的类,代码如下:
public class MailHelper {
   private final static Logger logger = Logger.getLogger(MailHelper.class);
   //创建一个email message 并且使用J2EE mail services发送它
  public void createAndSendMail(Mail mail) throws MailerAppException {
    try {
      logger.debug(" --> lookup mail session");
      InitialContext ic = new InitialContext();
      Session session = (Session) ic.lookup(JNDINames.MAIL_SESSION);
      Message msg = new MimeMessage(session);

      logger.debug(" --> beigin to set mail ");
      msg.setFrom(new InternetAddress(mail.getFromAddress()));
      msg.setRecipients(Message.RecipientType.TO,
                        InternetAddress.parse(mail.getToAddress(), false));
      msg.setSubject(mail.getSubject());
      msg.setText(mail.getContent());
      msg.setSentDate(new Date());
      logger.debug(" --> beigin to send now ....");
      Transport.send(msg);
    } catch (Exception e) {
      logger.error("createAndSendMail exception : " + e);
      throw new MailerAppException("Failure while sending mail");
    }
  }
}
由上可见,MDB MailerBean是在Queue中有消息到达时,取出后委托MailHelper使用J2EE容器的Mail Service发送邮件。
这两个类都比较依赖容器,所以要进行容器的配置。
在ejb-jar.xml中配置MailerBean如下:
<message-driven>
  <display-name>Mailer</display-name>
    <ejb-name>Mailer</ejb-name>
    <ejb-class>com.jdon.mailer.ejb.MailerBean</ejb-class>
    <transaction-type>Container</transaction-type>
    <message-driven-destination>
        <destination-type>javax.jms.Queue</destination-type>
    </message-driven-destination>
     <!--  使用容器的邮件操作资源 -->
    <resource-ref>
        <description />
          <res-ref-name>mail/DefaultMail</res-ref-name>
          <res-type>javax.mail.Session</res-type>
          <res-auth>Container</res-auth>
    </resource-ref>
</message-driven>
由于使用了容器的邮件发送服务,那么需要指定这个服务的JNDI,在jboss.xml当中加入:
<message-driven>
   <ejb-name>Mailer</ejb-name>
    <destination-jndi-name>queue/testQueue</destination-jndi-name>
    <resource-ref>
         <res-ref-name>mail/DefaultMail</res-ref-name>
         <jndi-name>java:/Mail</jndi-name>
    </resource-ref>
</message-driven>
这表示使用JNDI为java:/Mail的邮件服务资源,那么再部署发布本组件时,就需要在JBoss服务器中配置这个邮件服务资源,具体如何配置参见部署发布的章节。


 

 

下页