EJB3.0学习笔记

3.2 EJB实例分析

该实例是运行在JBOSS5.1与SQLServer2005下。

(1)  会话BEAN

对于会话Bean的开发,相对简单如图:

图3.4 会话Bean接口声明

声明接口即与使用此EJB的用户签定了契约。用户可以使用接口提供的功能。当然要为接口实现此功能如图:

图3.5 会话Bean服务实现类

对于接口服务的实现,EJB3中使用了更为方便的标签方式,声明这个Bean并为其指定接口。完成之后,即可以向外提供服务,需要组织成构件,如图:

 

图3.6 jar文件

当这个jar文件部署到服务器中时,服务器解析此为一个EJB的实体Bean,并向外提供服务。

图3.7 调用EJB服务代码

 

图3.8 调用结果显示

(2)  实体BEAN

由于实体BEAN的开发就要涉及与数据库的关联,所以要配置数据源

对于JBOSS数据源的配置做简单的介绍。

对于JBOSS5.1数据源的配置,在目录docs/example/jca中已经包含了相关的数据源配置的xml例子文件,如图:

图3.9 数据源配置xml文档

首先复制一份文件,并修改

<?xml version="1.0"encoding="UTF-8"?>

<datasources>

 <local-tx-datasource>

   <jndi-name>MSSQLDS</jndi-name>//这是设置jndi名称以供在程序能够找到这个数据源

   <connection-url>jdbc:sqlserver://localhost:1433;DatabaseName=MBOOK</connection-url>

   <driver-class>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver-class>

   <user-name>sa</user-name>

   <password>123456</password>

     <metadata>

        <type-mapping>MS SQLSERVER2005</type-mapping>

     </metadata>

 </local-tx-datasource>

</datasources>


 

 

修改好这个文件,同时需要把SQLServer2005所用的jdbc驱动包拷贝到jboss-5.1.0.GA\server\default\lib目录下,如图:

图3.10 数据驱动jar包

然后将文件移动到目录jboss-5.1.0.GA\server\default\deploy发布。如果此时你的jboss已经是启动状态,则会看到控制台打印:

图3.11 数据源加载成功

表示数据源加载成功。

接下来可以写你的EJB应用:

需要注意的是在实体Bean中,(注意实体bean中,get方法才有ejb的标签。另要确保实体bean有一个默认的的构造函数)需要包含一个persistence.xml文件,此文件在导出jar包的时候也要包含。此文件可以为此EJB对象指定数据源。即上面已经配置好的并加载进JBOSS中的。

<persistencexmlns="http://java.sun.com/xml/ns/persistence"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence  

      http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"

    version="1.0">

 

    <!--持久化单元 transaction-type事物的类型。一个是全局事物JTA,一个是本地事物 -->

    <persistence-unitname="sql"transaction-type="JTA">

       <jta-data-source>java:MSSQLDS</jta-data-source>

       <!--当数据源发布到jboss的时候,他的jndi名称默认是在java:的命名空间里 , 需要加上,jndi默认是在全局上找的 -->

       <properties>

//注意如如果下面方言不配置,有时是会报错的。

           <propertyname="hibernate.dialect"value="org.hibernate.dialect.SQLServerDialect"/>

           <propertyname="hibernate.show_sql"value="true"/>

           <propertyname="hibernate.format_sql"value="true"/>

           <propertyname="hibernate.jdbc.fetch_size"value="50"/>

       </properties>

    </persistence-unit>

</persistence>


 

 

 

jndi.properties文件在测试时和应用EJB时是必不可少的。

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory

java.naming.provider.url=localhost:1099

 

发布到jboss-5.1.0.GA-jdk6\jboss-5.1.0.GA\server\default\deploy目录下:

图3.12 发布EJB

如上图,已经成功发布了EntityBeanTest的EJB,该EJB是以jar文件形式存在的。并且还指出了beanName为PersonServiceBean,以及接口名IPersonService.

测试如下:

publicclass PersonServiceTest {

 

    privatestatic IPersonServicepersonService;

     @BeforeClass 

        publicstaticvoid setUpBeforeClass()throws Exception {  

            try { 

                InitialContextic =new InitialContext( ); 

                personService = (IPersonService)ic.lookup("PersonServiceBean/remote"); 

            } catch (Exception e){ 

               e.printStackTrace(); 

            }  

        }  

    @Test

    publicvoid testSave() {

       personService.save(newPerson("sunquan")); 

 

    }

}


 

执行成功,由于在persistence.xml中showSql为true,控制台显示了相应的sql语句。

图3.13 SQL语句

查看数据库:

图3.14 数据添加成功

收到对应结果。

1.  有几点需要注意,在数据库的设计过程中,id必须设为主键,且自增长。

2.  导入jboss/client的所有jar包。由于持久化操作,所以需要hibernate.jar包。

 

这样对于一个实体的bean,对应数据库中的一张表,并且包括对于数据的相应操作,就都包含在这个EJB对象当中。

(3)  消息驱动BEAN

消息驱动BEAN的特性有如异步调用,无状态特性,以及无本地远程接口等。

对于一个消息驱动BEAN,即当客户端发送一条消息时,该BEAN能够自动响应这条消息。能过客户端的消息来驱动该BEAN的调用、执行。

那么首先要存在这样一个所谓消息BEAN,并且他能够监听特定的消息。

packagecn.sunquan.MessageBean;

importjavax.ejb.ActivationConfigProperty;

importjavax.ejb.EJBException;

importjavax.ejb.MessageDriven;

importjavax.ejb.MessageDrivenBean;

importjavax.ejb.MessageDrivenContext;

importjavax.jms.JMSException;

import javax.jms.Message;

import javax.jms.MessageListener;

importjavax.jms.TextMessage;

@MessageDriven(mappedName="MyMessageDrivenBean",activationConfig = {

              @ActivationConfigProperty(propertyName ="destinationType", propertyValue ="javax.jms.Queue"),

       @ActivationConfigProperty(propertyName ="destination", propertyValue ="queue/itmQueue")})

//关于上述标签的解释:destination指明要去监听容器通道的名字,destinationType指//明要去监听容器通道的类型。mappedName非必须的。

publicclassMyMessageDrivenBeanimplements MessageDrivenBean, MessageListener {

    privatestaticfinallongserialVersionUID = 1L;

    publicMyMessageDrivenBean() {

       //TODO Auto-generated constructor stub

    }

    @Override

    publicvoid onMessage(Messagemessage) {

       TextMessagemsg = (TextMessage) message;

       try {

           System.out.println(msg.getText());

       } catch (JMSException e) {

           e.printStackTrace();

       }

    }

    @Override

    publicvoid ejbRemove()throws EJBException {

    }

    @Override

    publicvoidsetMessageDrivenContext(MessageDrivenContext arg0)

           throws EJBException {

       }

}


 

 

下面这个xml文件就是声明上述那个通道,打在jar包和单独发布到deploy目录下效果一样。

<?xmlversion="1.0"encoding="UTF-8"?> 

<server> 

  <mbeancode="org.jboss.mq.server.jmx.Queue" 

         name="jboss.mq.destination:server=Queue,name=itmQueue"> 

            <attributename="JNDIName">queue/itmQueue</attribute> 

            <dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends> 

  </mbean> 

 <!--  <mbeancode="org.jboss.mq.server.jmx.Topic" 

        name="jboss.mq.destination:service=Topic,name=itmTopic">   

    <attributename="JNDIName">topic/itmTopic</attribute> 

    <dependsoptional-attribute-name="DestinationManager">jboss.mq:service=DestinationManager</depends>

     </mbean>

     --> 

</server>


 

 

 

测试发现在bean打成jar包后,如果不包含上述这个xml的文件(xxx-service.xml)时,这个消息驱动bean是bound不成功的。为什么呢?

图3.15 绑定不成功

既然JBOSS已经发现了一个叫做itemQueue类型的消息,服务器此时只能从bean中的标签中发现itemQueue,至此服务器已经知道有一个bean,

他是处理itemQueue类型的。当一个itemQueue消息发送过来的时候,服务器应该是可以把这条消息交给指定bean处理的,或者是这个bean一直在等待,类似监听这类消息,一旦有就处理。(仅是猜测)

那么EJB消息驱动Bean是哪种处理方法的呢?

很明显,由于异步的需要,是采用的第二种,BEAN一直在监听。那么JBOSS就要为这个BEAN开辟一条通道,让BEAN在这条通道上监听,发送对应类型的消息时,也发送到这个通道上。那么我们就需要为JBOSS指定这个通道,然后把BEAN绑定到这条通道上。

(同时联想到bean中的一个属性名是destination,目的地,bean是消息处理的终点,怎么还有目的地,哈哈,此处的意思是去容器的一个目的通道上监听。)

而上面我们只声明了BEAN,JBOSS中确不存在这条通道,而你的bean又要去这里监听,那么JBOSS服务器会显示指定的通道没有绑定。

 

所以有理由相信,所以要通过上面xml文件使用容器创建一个通道(该文件可以打包在jar文件中,也可以只直接以xml文件的方式发布在deploy目录下,其效果是一样的):

 

 

图3.16 绑定成功

 

接下来就是处理发送消息:

package cn.sunquan.send;

import java.util.Properties;

import javax.jms.Queue;

importjavax.jms.QueueConnection;

import javax.jms.QueueConnectionFactory;

import javax.jms.QueueSession;

import javax.jms.TextMessage;

import javax.naming.InitialContext;

publicclass QueueSender {

    publicstaticvoid main(String[]args){ 

       try {  

        Properties props = new Properties();

           props.setProperty("java.naming.factory.initial","org.jnp.interfaces.NamingContextFactory");

           props.setProperty("java.naming.provider.url","localhost:1099");

           props.setProperty("java.naming.factory.url.pkgs","org.jboss.naming");

           InitialContext ctx = new InitialContext(props);

          

           //查找 QUeue类型的连接工厂。  

           QueueConnectionFactory factory = (QueueConnectionFactory)ctx

                    .lookup("ConnectionFactory");

                     QueueConnection conn=factory.createQueueConnection();

                     //创建一个到该地址的会话,第二个参数:消息的确认模式,这里用自动的确认模式。  

           QueueSession session = conn.createQueueSession(false,  

                    QueueSession.AUTO_ACKNOWLEDGE);

                  Queue queue = (Queue) ctx  

            .lookup("queue/itmQueue");  

                        TextMessage msg =session.createTextMessage("您好,这是我的第一个消息驱动Bean");

           javax.jms.QueueSender sender=session.createSender(queue);

           sender.send(msg);

           session.close();   

           conn.close();   

       } catch (Exception e) {  

           e.printStackTrace();  

       }   

   }  

}


 

可以看到lookup时是找的queue/itmQueue

图3.17 绑定成功

 

即在bean中指定的destination.

图3.18 显示结果

 

 

(注:上面的xxx-service.xml既然可以放在jar包中,那么实体bean中的dataSource.xml声明是否也可以放在实体bean的jar包中……)

 

 

下载:

HelloWorldEJB

EntityBeanTest

MessageBeanTest

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值