- 浏览: 484357 次
- 性别:
- 来自: 大连
文章分类
最新评论
-
龘龘龘:
TrueBrian 写道有个问题,Sample 1中,为了控制 ...
What's New on Java 7 Phaser -
龘龘龘:
楼主总结的不错。
What's New on Java 7 Phaser -
TrueBrian:
有个问题,Sample 1中,为了控制线程的启动时机,博主实际 ...
What's New on Java 7 Phaser -
liguanqun811:
不知道楼主是否对zookeeper实现的分布式锁进行过性能测试 ...
Distributed Lock -
hobitton:
mysql的get lock有版本限制,否则get lock可 ...
Distributed Lock
本文部分内容节选自Enterprise JavaBeans 3.0 by Bill Burke & Richard Monson-Haefel
1 Overview
Apache OpenEJB 是可嵌入、轻量级的EJB3.0实现,它即可作为Standalone Server,也可以作为Embedded Server嵌入到Tomcat, JUnit, Eclipse, Intellij, Maven, Ant 等等。OpenEJB缺省使用Apache OpenJPA作为JPA实现,Apache ActiveMQ作为JMS实现。OpenEJB 被应用于Apache Geronimo应用服务器、IBM WebSphere Application Server CE和Apple's WebObjects。
OpenEJB的创建者是 David Blevins 和 Richard Monson-Haefel。David Blevins目前还活跃在OpenEJB User Froum。而Richard Monson-Haefel则是Enterprise JavaBeans前几版的作者。目前Enterprise JavaBeans由JBoss公司首席架构师Bill Burke执笔,出版了第五版。
OpenEJB 实际上包括两个部分:服务器和容器,这两者是分离的。当创建InitialContext的时候,如果使用LocalInitialContextFactory并配置了openejb.embedded.remotable=true属性,那么会启动ServiceManager。ServiceManager会在类路径上查找ServerServices。如果类路径上有openejb-ejbd jar(依赖openejb-server, openejb-client, openejb-core),那么这些services会被启动并允许远程的客户端访问。如果你希望添加更多的ServerServices以支持其它协议,例如HTTP,那么只要把openejb-httpejbd jar加入到类路径上即可。
2 EJBs
2.1 Session Bean
Session bean可以分为两种类型:stateless和stateful。Stateless session bean不维护两次方法调用间的状态。Stateful session bean维护着与客户端的会话状态。Session bean拥有一个或多个业务接口,业务接口可以是远程接口,也可以是本地接口,但是不能两者兼备。远程接口抛出的异常也会被传播到客户端,因此异常中的成员变量也必须能够被序列化。调用本地接口的方法不会引起参数和返回值的拷贝。如果远程接口和本地接口拥有相同的方法,EJB规范允许它们继承自相同的接口。需要注意的是,只要配置openejb.remotable.businessLocals=true,那么OpenEJB允许客户端远程调用本地接口。在这种情况下,本地接口的参数和返回值仍然需要可以被序列化。
以下是个stateless session bean的例子:
public interface Calculator { int sum(int add1, int add2); int multiply(int mul1, int mul2); }
import javax.ejb.Local; @Local public interface CalculatorLocal extends Calculator{ }
import javax.ejb.Remote; @Remote public interface CalculatorRemote extends Calculator{ }
import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext; @Stateless @TransactionAttribute(TransactionAttributeType.SUPPORTS) public class CalculatorImpl implements CalculatorLocal, CalculatorRemote { public int sum(int add1, int add2) { return add1 + add2; } public int multiply(int mul1, int mul2) { return mul1 * mul2; } @PostConstruct private void init() { System.out.println("#in CalculatorImpl.init()"); } @PreDestroy private void dispose() { System.out.println("#in CalculatorImpl.dispose()"); } @AroundInvoke private Object intercept(InvocationContext ctx) throws Exception { try { System.out.println("#pre-invoke method: " + ctx.getMethod().getName()); return ctx.proceed(); } finally { System.out.println("#post-invoke method: " + ctx.getMethod().getName()); } } }
import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; public class StatelessTest { public static void main(String args[]) throws Exception { // Properties properties = new Properties(); properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory"); InitialContext ctx = new InitialContext(properties); // { CalculatorLocal cl1 = (CalculatorLocal) ctx.lookup("CalculatorImplLocal"); System.out.println("cl1.sum(12, 7): " + cl1.sum(12, 7)); System.out.println("cl1.multiply(12, 7): " + cl1.multiply(12, 7)); } // { Object ref1 = ctx.lookup("CalculatorImplRemote"); CalculatorRemote cr1 = (CalculatorRemote) PortableRemoteObject.narrow(ref1, CalculatorRemote.class); System.out.println("cr1.sum(12, 7): " + cr1.sum(12, 7)); System.out.println("cr1.multiply(12, 7): " + cr1.multiply(12, 7)); } } }
以上例子中,CalculatorImpl 类的init() 和dispose()方法是EJB的生命周期回调方法。intercept()方法是拦截器方法,此外也可以定义拦截器类。需要注意的是,拦截器与所拦截的EJB具有相同的生命周期。
以上例子采用的是local client(embedded container)模式。META-INF/ejb-jar.xml中的内容只是包含了ejb-jar根元素,如下:
<ejb-jar/>
OpenEJB会在扫描并部署类路径上的EJB。另外一种部署的方式是编辑conf/openejb.xml文件,例如:
<openejb> <Deployments dir="./bin/yourpackage" /> <Deployments jar="./lib/another.jar" /> </openejb>
OpenEJB提供缺省的JNDI Name格式是{deploymentId}{interfaceType.annotationName},它可以通过openejb.jndiname.format定制。{deploymentId}缺省是{ejbName},而{ejbName}缺省是EJB的非限定类名。{interfaceType.annotationName}有如下取值:
- RemoteHome (EJB 2 EJBHome)
- LocalHome (EJB 2 EJBLocalHome)
- Remote (EJB 3 Business Remote)
- Local (EJB 3 Business Local)
- Endpoint (EJB webservice endpoint)
因此查找CalculatorLocal接口的JNDI Name是CalculatorImplLocal。关于更多JNDI Name Formatting的介绍,请参考OpenEJB官方文档。
如果在程序的当前路径下存在conf目录,那么OpenEJB在第一次启动的时候会创建以下文件。如果需要,也可以对这些文件进行编辑以修改相关的配置。
- openejb.xml (main config file)
- logging.properties (log levels and files)
- login.config (jaas config file)
- users.properties (users that can log in)
- groups.properties (groups in which users belong)
- admin.properties (network socket for administration)
- ejbd.properties (network socket for ejb invocations)
- hsql.properties (network socket for hsql client access)
- httpejbd.properties (network socket for ejb invocations over http)
- telnet.properties (network socket for telnet "server")
2.2 Entity Bean
EJB3.0规范中,Entity bean是被@Entity标注的POJO。如果Entity bean可以被序列化,那么它可以脱离应用服务器而被传递到表示层。可以为Entity bean定义Entity监听器以便指定Entity bean的生命周期回调方法。关于Entity bean的更多介绍,请参考JPA相关文档。
2.3 Message Driven Bean
Message Driven Bean是无状态的,事务感知的服务器端组件。事务上下文并非从JMS的发送方传播过来,而是由容器发起(有意义的事务属性是NotSupported和Required),或者是由bean明确使用UserTransaction被发起的。如果事务是由容器管理的,JMS确认行为是在事务上下文中执行的。EJB2.1后,EJB规范支持一个可扩展的,也更为开放的MDB定义,使之可以对任何开发商的任何消息系统提供服务,而不仅仅是JMS消息系统。以下是个MDB的简单例子:
import javax.ejb.Remote; @Remote public interface SchedulerRemote { void schedule(long initialExpration, long interval, String subject); void cancel(String subject); }
import javax.annotation.Resource; import javax.ejb.Stateless; import javax.ejb.Timeout; import javax.ejb.Timer; import javax.ejb.TimerService; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.DeliveryMode; import javax.jms.Destination; import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.TextMessage; @Stateless public class SchedulerImpl implements SchedulerRemote { @Resource private TimerService timerService; @Resource(name="JmsConnectionFactory1") private ConnectionFactory connectionFactory; public void schedule(long initialExpration, long interval, String subject) { timerService.createTimer(initialExpration, interval, subject); } public void cancel(String subject) { for(Object obj : timerService.getTimers()) { Timer timer = (Timer)obj; if(timer.getInfo().equals(subject)) { timer.cancel(); } } } @Timeout public void sendMessage(Timer timer) { try { // Connection connection = connectionFactory.createConnection(); connection.start(); // Session session = connection.createSession(true, 0); Destination destination = session.createQueue((String)timer.getInfo()); MessageProducer producer = session.createProducer(destination); producer.setDeliveryMode(DeliveryMode.PERSISTENT); // TextMessage message = session.createTextMessage("this is a simple message, time: " + System.currentTimeMillis()); producer.send(message); connection.close(); } catch (Exception e) { System.err.println("failed to send message, detail: " + e.getMessage()); } } }
import javax.ejb.ActivationConfigProperty; import javax.ejb.MessageDriven; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.TextMessage; @MessageDriven(activationConfig={ @ActivationConfigProperty(propertyName="destinationType",propertyValue="javax.jms.Queue"), @ActivationConfigProperty(propertyName="destination",propertyValue="SimpleQueue") }) public class SimpleConsumer implements MessageListener { public void onMessage(Message msg) { try { TextMessage tm = (TextMessage)msg; System.out.println("on message: " + tm.getText()); } catch(Exception e) { e.printStackTrace(); } } }
import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; public class MdbTestServer { public static void main(String args[]) throws Exception { // Properties properties = new Properties(); properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory"); properties.setProperty("openejb.embedded.remotable", "true"); // @SuppressWarnings("unused") InitialContext ctx = new InitialContext(properties); // while(true) { try { Thread.sleep(1000); } catch (Exception e) { e.printStackTrace(); } } } }
import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; public class MdbTestClient { public static void main(String args[]) throws Exception { // Properties properties = new Properties(); properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.RemoteInitialContextFactory"); properties.setProperty(Context.PROVIDER_URL, "ejbd://localhost:4201"); properties.setProperty(Context.SECURITY_PRINCIPAL, "Kevin"); properties.setProperty(Context.SECURITY_CREDENTIALS, "password"); InitialContext ctx = new InitialContext(properties); // Object ref = ctx.lookup("SchedulerImplRemote"); SchedulerRemote sr = (SchedulerRemote) PortableRemoteObject.narrow(ref, SchedulerRemote.class); sr.schedule(0L, 1000, "SimpleQueue"); // Thread.sleep(5000); // sr.cancel("SimpleQueue"); } }
conf/ users.properties文件的内容如下:
Kevin= password
conf/openejb.xml文件中的相关内容如下:
<Container id="My MDB Container " type="MESSAGE"> # The resource adapter delivers messages to the container ResourceAdapter JmsResourceAdapter1 # Specifies the message listener interface handled by this container MessageListenerInterface javax.jms.MessageListener # Specifies the activation spec class ActivationSpecClass org.apache.activemq.ra.ActiveMQActivationSpec # Specifies the maximum number of bean instances that are # allowed to exist for each MDB deployment. InstanceLimit 10 </Container> <Resource id="mysqlDataSource" type="DataSource"> JdbcDriver com.mysql.jdbc.Driver JdbcUrl jdbc:mysql://localhost:3306/ejb UserName root Password password JtaManaged true </Resource> <Resource id="mysqlDataSourceUnmanaged" type="DataSource"> JdbcDriver com.mysql.jdbc.Driver JdbcUrl jdbc:mysql://localhost:3306/ejb UserName root Password password JtaManaged false </Resource> <Resource id="JmsResourceAdapter1" type="ActiveMQResourceAdapter"> # Broker configuration URI as defined by ActiveMQ # see http://activemq.apache.org/broker-configuration-uri.html BrokerXmlConfig broker:(tcp://localhost:61616)?useJmx=false # Broker address ServerUrl vm://localhost?async=true # DataSource for persistence messages DataSource mysqlDataSourceUnmanaged </Resource> <Connector id="JmsConnectionFactory1" type="javax.jms.ConnectionFactory"> ResourceAdapter JmsResourceAdapter1 # Specifies if the connection is enrolled in global transaction # allowed values: xa, local or none TransactionSupport xa # Maximum number of physical connection to the ActiveMQ broker PoolMaxSize 10 # Minimum number of physical connection to the ActiveMQ broker PoolMinSize 0 # Maximum amount of time to wait for a connection ConnectionMaxWaitMilliseconds 5000 # Maximum amount of time a connection can be idle before being reclaimed ConnectionMaxIdleMinutes 15 </Connector>
以上例子中,SimpleConsumer订阅SimpleQueue;客户端调用SchedulerRemote接口的schedule()和cancel()方法;SchedulerImpl通过使用TimerService定期向SimpleQueue中发送TextMessage。
跟2.1中的例子不同,本例中采用的是remote client(embedded container)模式:MdbTestServer中配置了properties.setProperty("openejb.embedded.remotable", "true");
发表评论
-
Terracotta in Action (3)
2009-03-25 09:20 51723 Inside Terracotta 3.1 Core T ... -
Terracotta in Action (2)
2009-03-21 21:09 47282. Terracotta Eclipse Plugin ... -
Terracotta in Action (1)
2009-03-19 21:52 63021. Introduction Terraco ... -
OpenEJB (4)
2008-05-11 09:05 3201本文部分内容节选自Enterprise JavaBeans 3 ... -
OpenEJB (3)
2008-05-11 09:04 2737本文部分内容节选自Enterprise JavaBeans 3 ... -
OpenEJB (2)
2008-05-11 09:03 3330本文部分内容节选自Enterprise JavaBeans 3 ... -
OpenJPA (7)
2008-03-25 21:56 358210 Miscellaneous Features 10 ... -
OpenJPA (6)
2008-03-23 21:33 63738 Object Locking 8.1 Configu ... -
OpenJPA (5)
2008-03-18 22:38 50717 Inheritance 对象使用引用以便关联到其 ... -
OpenJPA (4)
2008-03-11 23:27 71416 Query 6.1 JPQL Queries 6.1. ... -
OpenJPA (3)
2008-03-09 23:09 52804 EntityManagerFactory 4.1 Ove ... -
OpenJPA (2)
2008-03-05 23:59 73063 Metadata 通过javax.persist ... -
OpenJPA (1)
2008-03-04 23:11 69121 Overview Apache OpenJPA是 ... -
ActiveMQ in Action (7)
2008-02-27 14:33 126882.6.7 Wildcards Wil ... -
ActiveMQ in Action (6)
2008-02-26 15:22 138312.6 Features ActiveMQ包含了很多 ... -
ActiveMQ in Action (5)
2008-02-26 00:35 136302.5 Clustering ActiveMQ从多种 ... -
ActiveMQ in Action (4)
2008-02-26 00:21 113062.4 Security ActiveMQ ... -
ActiveMQ in Action (3)
2008-02-26 00:16 106482.3 Persistence 2.3.1 AMQ Mess ... -
ActiveMQ in Action (2)
2008-02-25 23:58 133132.2 Transport ActiveMQ目前支持 ... -
ActiveMQ in Action (1)
2008-02-25 23:18 239071 JMS 在介绍ActiveMQ ...
相关推荐
1. **EJB 3.0 规范概述** EJB 3.0 是 Java EE 5 中的一项重要更新,它简化了 EJB 的开发,减少了代码量,并引入了注解(Annotation)来替代 XML 配置。在 OpenEJB 3.0 中,你可以看到这些规范的实现,例如: - **...
1. **下载与安装OpenEjb**: 首先,你需要从OpenEjb的官方网站或通过Maven仓库获取最新版本的OpenEjb库。将其解压到一个合适的位置,并确保你的系统路径包含OpenEjb的bin目录。 2. **配置Tomcat**: 在Tomcat的`...
标题中的"openejb-embedded-maven-plugin-4.6.0.1.zip"是一个开源项目的Maven插件包,特别地,它是OpenEJB的嵌入式版本。OpenEJB是一个开源的企业JavaBeans(EJB)容器和服务器,它实现了Java EE(现在称为Jakarta ...
1. **OpenEJB和Apache TomEE**:OpenEJB是Apache TomEE的核心组件,它实现了Java EE的EJB规范,使得开发者可以创建和管理企业级Java组件。Apache TomEE是完全符合Java EE标准的Web服务器,集成了许多Apache项目,...
目前Tomcat并不直接支持EJB,但可借助openejb插件来间接能够支持EJB
一个简单的工具,可简化企业Java bean源代码和openEJB的配置的生成
标签:arquillian-openejb-transaction-provider-1.7.0.jar,arquillian,openejb,transaction,provider,1.7.0,jar包下载,依赖包
标签:arquillian-openejb-transaction-provider-1.5.1.jar,arquillian,openejb,transaction,provider,1.5.1,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.5.2.jar,arquillian,openejb,embedded,4,4.5.2,jar包下载,依赖包
标签:arquillian-openejb-transaction-provider-1.6.0.jar,arquillian,openejb,transaction,provider,1.6.0,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.6.0.jar,arquillian,openejb,embedded,4,4.6.0,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.7.0.jar,arquillian,openejb,embedded,4,4.7.0,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.7.1.jar,arquillian,openejb,embedded,4,4.7.1,jar包下载,依赖包
标签:arquillian-openejb-transaction-provider-1.7.1.jar,arquillian,openejb,transaction,provider,1.7.1,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.5.1.jar,arquillian,openejb,embedded,4,4.5.1,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.5.0.jar,arquillian,openejb,embedded,4,4.5.0,jar包下载,依赖包
标签:arquillian-openejb-transaction-provider-1.5.0.jar,arquillian,openejb,transaction,provider,1.5.0,jar包下载,依赖包
标签:arquillian-openejb-transaction-provider-1.5.2.jar,arquillian,openejb,transaction,provider,1.5.2,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.6.0-javadoc.jar,arquillian,openejb,embedded,4,4.6.0,javadoc,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.6.0.2.jar,arquillian,openejb,embedded,4,4.6.0.2,jar包下载,依赖包