- 浏览: 483181 次
- 性别:
- 来自: 大连
文章分类
最新评论
-
龘龘龘:
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
3 Injection
每个部署于应用服务器中的EJB容器都拥有一个属于它自己的内部注册表(internal registry),该内部注册表被成为Enterprise Naming Context(ENC)。EJB容器可以在其中维护某些指向外部环境资源的引用。可以通过annotation和XML文件配置ENC。可以绑定到ENC中的内容有:EJB接口、EntityManagerFactory、EntityManager、DataSource、JMS Destination、TimeService、UserTransaction和Environment Entry等。
3.1 Injection of EJBs
以下是个关于Injection of EJBs的简单例子:
public interface DataStore { String getData(); }
import javax.ejb.Local; @Local public interface DataStoreLocal extends DataStore { }
import javax.ejb.Remote; @Remote public interface DataStoreRemote extends DataStore { }
import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; @Stateless @TransactionAttribute(TransactionAttributeType.SUPPORTS) public class DataStoreImpl implements DataStoreLocal, DataStoreRemote { public String getData() { return "data"; } }
import javax.ejb.Local; @Local public interface DataReaderLocal { String readLocalData(); }
import javax.ejb.Remote; @Remote public interface DataReaderRemote { String readRemoteData(); }
import javax.ejb.EJB; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; @Stateless @TransactionAttribute(TransactionAttributeType.SUPPORTS) public class DataReaderImpl implements DataReaderLocal, DataReaderRemote { @EJB(name="DataStoreLocal") private DataStoreLocal dataStoreLocal; @EJB(name="DataStoreRemote") private DataStoreRemote dataStoreRemote; public String readLocalData() { return "Local " + dataStoreLocal.getData(); } public String readRemoteData() { return "Remote " + dataStoreRemote.getData(); } }
import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; public class InjectionTest { 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); // DataReaderLocal drl = (DataReaderLocal)ctx.lookup("DataReaderImplLocal"); System.out.println(drl.readLocalData()); // Object ref = ctx.lookup("DataReaderImplRemote"); DataReaderRemote drr = (DataReaderRemote) PortableRemoteObject.narrow(ref, DataReaderRemote.class); System.out.println(drr.readRemoteData()); } }
任何注册到ENC中的内容都可以在java:comp/env上下文中通过名称查找。SessionContext和MessageDrivenContext接口都继承自EJBContext。EJBContext接口中有个便捷方法用于JNDI查找,它不抛出检查式异常,而且用的是相对于ENC的内部名称,而不是之前提到的java:comp/env全名。以下是个简单的例子:
import javax.annotation.Resource; import javax.ejb.EJB; import javax.ejb.EJBs; import javax.ejb.SessionContext; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject; @Stateless @EJBs ({ @EJB(name="DataStoreLocal", beanInterface=DataStoreLocal.class), @EJB(name="DataStoreRemote", beanInterface=DataStoreRemote.class) }) @TransactionAttribute(TransactionAttributeType.SUPPORTS) public class DataReaderImpl implements DataReaderLocal, DataReaderRemote { @Resource private SessionContext context; public String readLocalData() { // DataStoreLocal dsl = null; try { InitialContext ctx = new InitialContext(); dsl = (DataStoreLocal)ctx.lookup("java:comp/env/DataStoreLocal"); } catch (NamingException e) { throw new RuntimeException("failed to lookup DataStoreLocal", e); } // return "Local " + dsl.getData(); } public String readRemoteData() { Object ref = context.lookup("DataStoreRemote"); DataStoreRemote dsr = (DataStoreRemote)PortableRemoteObject.narrow(ref, DataStoreRemote.class); return "Remote " + dsr.getData(); } }
3.2 Injection of DataSource
以下是个关于Injection of DataSource的简单例子:
import java.io.Serializable; import javax.persistence.Basic; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; @Entity public class Movie implements Serializable { // private static final long serialVersionUID = -3282817754636291024L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Basic private String title; @Basic private String director; @Basic private int year; public Movie() { } public Movie(String title, String director, int year) { this.title = title; this.director = director; this.year = year; } public String toString() { StringBuffer sb = new StringBuffer(); sb.append("id: " + id); sb.append(", title: " + title); sb.append(", director: " + director); sb.append(", year: " + year); return sb.toString(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getDirector() { return director; } public void setDirector(String director) { this.director = director; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } }
import java.util.List; public interface MovieDao { List<Movie> getAllMovies(); void addMovies(List<Movie> movies); void deleteMovie(Movie movie); }
import javax.ejb.Local; @Local public interface MovieDaoJdbcLocal extends MovieDao { }
import javax.ejb.Remote; @Remote public interface MovieDaoJdbcRemote extends MovieDao { }
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import javax.annotation.Resource; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.sql.DataSource; @Stateless @TransactionAttribute(TransactionAttributeType.REQUIRED) public class MovieDaoJdbcImpl implements MovieDaoJdbcLocal, MovieDaoJdbcRemote { @Resource(name="mysqlDataSource") private DataSource mysql; public List<Movie> getAllMovies() { ArrayList<Movie> movies = new ArrayList<Movie>(); try { Connection con = mysql.getConnection(); PreparedStatement stmt = con.prepareStatement("SELECT id, director, title, year FROM movie"); ResultSet rs = stmt.executeQuery(); while ( rs.next() ) { Movie movie = new Movie(); movie.setId(rs.getInt("id")); movie.setDirector(rs.getString("director")); movie.setTitle(rs.getString("title")); movie.setYear(rs.getInt("year")); movies.add(movie); } rs.close(); stmt.close(); con.close(); } catch(SQLException e) { throw new RuntimeException(e); } return movies; } public void addMovies(List<Movie> movies) { try { Connection con = mysql.getConnection(); for(Movie movie : movies) { PreparedStatement stmt = con.prepareStatement("INSERT INTO movie (director, title, year) VALUES (?, ?, ?)"); stmt.setString(1, movie.getDirector()); stmt.setString(2, movie.getTitle()); stmt.setInt(3, movie.getYear()); stmt.execute(); stmt.close(); } con.close(); } catch(SQLException e) { throw new RuntimeException(e); } } public void deleteMovie(Movie m) { try { Connection con = mysql.getConnection(); PreparedStatement stmt = con.prepareStatement("DELETE FROM movie WHERE id = ?"); stmt.setInt(1, m.getId()); stmt.executeUpdate(); stmt.close(); con.close(); } catch(SQLException e) { throw new RuntimeException(e); } } }
OpenEJB可以通过JNDI Context的properties定义DataSource,例如:
import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; public class InjectionOfDataSourceTest { public static void main(String args[]) throws Exception { // Properties properties = new Properties(); properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory"); properties.put("mysqlDataSource", "new://Resource?type=DataSource"); properties.put("mysqlDataSource.JdbcDriver", "com.mysql.jdbc.Driver"); properties.put("mysqlDataSource.JdbcUrl", "jdbc:mysql://localhost:3306/ejb"); properties.put("mysqlDataSource.username", "root"); properties.put("mysqlDataSource.password", "password"); properties.put("mysqlDataSourceUnmanaged.JtaManaged", "true"); InitialContext ctx = new InitialContext(properties); // List<Movie> movies = new ArrayList<Movie>(); movies.add(new Movie("Dances with Wolves", "Kevin Costner", 1990)); movies.add(new Movie("Legends of the Fall", "Edward Zwich", 1994)); movies.add(new Movie("A Very Long Engagement", "Jean-Pierre Jeunet", 2004)); // Object ref1 = ctx.lookup("MovieDaoJdbcImplRemote"); MovieDaoJdbcRemote dao1 = (MovieDaoJdbcRemote) PortableRemoteObject.narrow(ref1, MovieDaoJdbcRemote.class); dao1.addMovies(movies); for(Movie m : dao1.getAllMovies()) { System.out.println("dao1.getAllMovies(): " + m); dao1.deleteMovie(m); } } }
此外,也可以在conf/openejb.xml中定义DataSource,例如以下是openejb.xml中的相关配置:
<Resource id="mysqlDataSource" type="DataSource"> JdbcDriver com.mysql.jdbc.Driver JdbcUrl jdbc:mysql://localhost:3306/ejb UserName root Password password JtaManaged true </Resource>
目前OpenEJB尚不支持在openejb.xml中,以加密后的形式保存Password,关于详细介绍请参考OpenEJB User Forum。
3.3 Injection of EntityManager
EntityManager可以被注入到EJB中。当你将EntityManager注册到ENC中或者注入到EJB时,EJB容器会对EntityManager所依赖的persistentce context具有完全的控制权。在注入的EntityManager上调用close方法会导致异常。默认的PersistenceContextType是TRANSACTION。EXTENDED类型的persistence context只能用于stateful session bean。META-INF目录下的persistence.xml用以配置JPA。以下是个简单的例子:
import javax.ejb.Local; @Local public interface MovieDaoJpaLocal extends MovieDao { }
import javax.ejb.Remote; @Remote public interface MovieDaoJpaRemote extends MovieDao { }
import java.util.List; import javax.ejb.Stateless; import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContextType; import javax.persistence.Query; @Stateless @TransactionAttribute(TransactionAttributeType.REQUIRED) public class MovieDaoJpaImpl implements MovieDaoJpaLocal, MovieDaoJpaRemote { @PersistenceContext(unitName = "ejb", type = PersistenceContextType.TRANSACTION) private EntityManager entityManager; public List<Movie> getAllMovies() { Query query = entityManager.createQuery("SELECT m from Movie as m"); return query.getResultList(); } public void addMovies(List<Movie> movies) { for(Movie m : movies) { entityManager.persist(m); } } public void deleteMovie(Movie movie) { Movie m = entityManager.merge(movie); entityManager.remove(m); } }
import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; import javax.rmi.PortableRemoteObject; public class InjectionOfEntityManagerTest { public static void main(String args[]) throws Exception { // Properties properties = new Properties(); properties.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.openejb.client.LocalInitialContextFactory"); properties.put("mysqlDataSource", "new://Resource?type=DataSource"); properties.put("mysqlDataSource.JdbcDriver", "com.mysql.jdbc.Driver"); properties.put("mysqlDataSource.JdbcUrl", "jdbc:mysql://localhost:3306/ejb"); properties.put("mysqlDataSource.username", "root"); properties.put("mysqlDataSource.password", "password"); properties.put("mysqlDataSourceUnmanaged.JtaManaged", "true"); InitialContext ctx = new InitialContext(properties); // List<Movie> movies = new ArrayList<Movie>(); movies.add(new Movie("Dances with Wolves", "Kevin Costner", 1990)); movies.add(new Movie("Legends of the Fall", "Edward Zwich", 1994)); movies.add(new Movie("A Very Long Engagement", "Jean-Pierre Jeunet", 2004)); // Object ref2 = ctx.lookup("MovieDaoJpaImplRemote"); MovieDaoJpaRemote dao2 = (MovieDaoJpaRemote) PortableRemoteObject.narrow(ref2, MovieDaoJpaRemote.class); dao2.addMovies(movies); for(Movie m : dao2.getAllMovies()) { System.out.println("dao2.getAllMovies(): " + m); dao2.deleteMovie(m); } } }
META-INF/ persistence.xml文件的内容如下:
<?xml version="1.0" encoding="UTF-8"?> <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"> <persistence-unit name="ejb"> <jta-data-source>mysqlDataSource</jta-data-source> <provider> org.apache.openjpa.persistence.PersistenceProviderImpl </provider> <properties> <property name="openjpa.Log" value="log4j"/> <property name="openjpa.ConnectionFactoryProperties" value="PrettyPrint=true, PrettyPrintLineLength=72"/> <property name="openjpa.jdbc.TransactionIsolation" value="read-committed"/> </properties> </persistence-unit> </persistence>
3.4 Injection of env-entry
可以通过环境注册项(environment entry)对EJB进行配置。环境注册项不是元数据,而是配置项。EJB3.0规范支持的环境注册项类型如下:
- java.lang.String
- java.lang.Integer
- java.lang.Short
- java.lang.Float
- java.lang.Double
- java.lang.Byte
- java.lang.Character
- java.lang.Boolean
在OpenEJB中并不限于以上类型。如果提供了合适的java.beans.PropertyEditor,那么任何可以从String转换到的类型都被支持。除了在META-INF/ejb-jar.xml中配置环境注册项外,也可以在META-INF/env-entries.properties文件中进行配置。以下是个简单的例子:
import java.beans.PropertyEditorManager; public enum Fruit { // APPLE, PEACH, UNKNOWN; // static { PropertyEditorManager.registerEditor(Fruit.class, FruitEditor.class); } }
import java.beans.PropertyEditorSupport; public class FruitEditor extends PropertyEditorSupport { public void setAsText(String text) throws IllegalArgumentException { text = text.trim(); if (text.equalsIgnoreCase("APPLE")) { setValue(Fruit.APPLE); } else if (text.equalsIgnoreCase("PEACH")) { setValue(Fruit.PEACH); } else { setValue(Fruit.UNKNOWN); } } }
import java.util.Date; import java.util.List; import java.util.Map; import javax.ejb.Local; @Local public interface BasketLocal { int getCount(); Date getDate(); Fruit getFruit(); List<Fruit> getList(); Map<Fruit, Float> getMap(); }
import java.util.Date; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.ejb.Stateful; @Stateful public class BasketImpl implements BasketLocal { @Resource private int count; @Resource(name="date") private Date date; @Resource(name = "fruit") private Fruit fruit; @Resource(name="list") private List<Fruit> list; @Resource private Map<Fruit, Float> map; public int getCount() { return count; } public Date getDate() { return date; } public Fruit getFruit() { return fruit; } public List<Fruit> getList() { return list; } public Map<Fruit, Float> getMap() { return map; } }
import java.util.Iterator; import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; public class InjectionOfEnvEntryTest { 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); // BasketLocal basket = (BasketLocal)ctx.lookup("BasketImplLocal"); System.out.println("count: " + basket.getCount()); System.out.println("date: " + basket.getDate()); System.out.println("fruit: " + basket.getFruit()); System.out.print("list: "); for(Iterator<Fruit> iter = basket.getList().iterator(); iter.hasNext();) { System.out.print(iter.next()); if(iter.hasNext()) { System.out.print(", "); } } System.out.println(); System.out.print("map: "); for(Iterator<Fruit> iter = basket.getMap().keySet().iterator(); iter.hasNext();) { Fruit key = iter.next(); System.out.print(key + "=" + basket.getMap().get(key)); if(iter.hasNext()) { System.out.print(", "); } } System.out.println(); } }
META-INF/env-entries.properties的内容如下:
date=2008-05-06
list=APPLE,PEACH,PEACH
com.yourpackage.BasketImpl/map=APPLE=1.00\nPEACH=2.00\n
META-INF/ejb-jar.xml的内容如下:
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" version="3.0" metadata-complete="false"> <enterprise-beans> <session> <ejb-name>BasketImpl</ejb-name> <env-entry> <description>count</description> <env-entry-name>com.yourpackage.BasketImpl/count</env-entry-name> <env-entry-type>java.lang.Integer</env-entry-type> <env-entry-value>12</env-entry-value> </env-entry> <env-entry> <description>fruit</description> <env-entry-name>fruit</env-entry-name> <env-entry-type>java.lang.String</env-entry-type> <env-entry-value>APPLE</env-entry-value> </env-entry> </session> </enterprise-beans> </ejb-jar>
需要注意的是,以上例子中BasketImpl的成员变量count和map的@Resource中没有指定name属性,那么默认的ENC名称是:所在类的全限定类名 / 数据成员或方法的基础名。当需要在XML部署描述文件中进行配置时,需要正确使用ENC名。
发表评论
-
Terracotta in Action (3)
2009-03-25 09:20 51443 Inside Terracotta 3.1 Core T ... -
Terracotta in Action (2)
2009-03-21 21:09 47012. Terracotta Eclipse Plugin ... -
Terracotta in Action (1)
2009-03-19 21:52 62861. Introduction Terraco ... -
OpenEJB (4)
2008-05-11 09:05 3186本文部分内容节选自Enterprise JavaBeans 3 ... -
OpenEJB (3)
2008-05-11 09:04 2727本文部分内容节选自Enterprise JavaBeans 3 ... -
OpenEJB (1)
2008-05-10 22:39 5110本文部分内容节选自Enterprise JavaBeans 3 ... -
OpenJPA (7)
2008-03-25 21:56 357410 Miscellaneous Features 10 ... -
OpenJPA (6)
2008-03-23 21:33 63428 Object Locking 8.1 Configu ... -
OpenJPA (5)
2008-03-18 22:38 50517 Inheritance 对象使用引用以便关联到其 ... -
OpenJPA (4)
2008-03-11 23:27 71106 Query 6.1 JPQL Queries 6.1. ... -
OpenJPA (3)
2008-03-09 23:09 52554 EntityManagerFactory 4.1 Ove ... -
OpenJPA (2)
2008-03-05 23:59 72993 Metadata 通过javax.persist ... -
OpenJPA (1)
2008-03-04 23:11 68811 Overview Apache OpenJPA是 ... -
ActiveMQ in Action (7)
2008-02-27 14:33 126792.6.7 Wildcards Wil ... -
ActiveMQ in Action (6)
2008-02-26 15:22 137982.6 Features ActiveMQ包含了很多 ... -
ActiveMQ in Action (5)
2008-02-26 00:35 136012.5 Clustering ActiveMQ从多种 ... -
ActiveMQ in Action (4)
2008-02-26 00:21 112782.4 Security ActiveMQ ... -
ActiveMQ in Action (3)
2008-02-26 00:16 106382.3 Persistence 2.3.1 AMQ Mess ... -
ActiveMQ in Action (2)
2008-02-25 23:58 132782.2 Transport ActiveMQ目前支持 ... -
ActiveMQ in Action (1)
2008-02-25 23:18 238801 JMS 在介绍ActiveMQ ...
相关推荐
2. **注解驱动的开发** OpenEJB 3.0 强调了注解的使用,使得开发者可以更直观地声明bean的角色和行为,如 `@Stateless`、`@Stateful`、`@Singleton`、`@MessageDriven` 和 `@PersistenceContext` 等。这使得 EJB ...
2. **配置Tomcat**: 在Tomcat的`conf/server.xml`文件中,添加一个Listener来启动OpenEjb。例如: ``` <Listener className="org.apache.openejb.tomcat.OpenEjbSystemLoader" /> ``` 3. **配置EJB项目**: ...
标题中的"openejb-embedded-maven-plugin-4.6.0.1.zip"是一个开源项目的Maven插件包,特别地,它是OpenEJB的嵌入式版本。OpenEJB是一个开源的企业JavaBeans(EJB)容器和服务器,它实现了Java EE(现在称为Jakarta ...
2. **RESTEasy和Jersey**:RESTEasy是JBoss的一个项目,提供了一套用于构建RESTful Web服务的框架,遵循JAX-RS规范。Jersey则是Sun Microsystems(现为Oracle)发起的项目,同样遵循JAX-RS,提供了全面的RESTful服务...
目前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-embedded-4-4.6.0.jar,arquillian,openejb,embedded,4,4.6.0,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.5.1.jar,arquillian,openejb,embedded,4,4.5.1,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.7.0.jar,arquillian,openejb,embedded,4,4.7.0,jar包下载,依赖包
标签:arquillian-openejb-transaction-provider-1.7.1.jar,arquillian,openejb,transaction,provider,1.7.1,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.7.1.jar,arquillian,openejb,embedded,4,4.7.1,jar包下载,依赖包
标签:arquillian-openejb-transaction-provider-1.5.1.jar,arquillian,openejb,transaction,provider,1.5.1,jar包下载,依赖包
标签:arquillian-openejb-transaction-provider-1.6.0.jar,arquillian,openejb,transaction,provider,1.6.0,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.5.2.jar,arquillian,openejb,embedded,4,4.5.2,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.5.1-sources.jar,arquillian,openejb,embedded,4,4.5.1,sources,jar包下载,依赖包
标签:arquillian-openejb-embedded-4-4.6.0.2.jar,arquillian,openejb,embedded,4,4.6.0.2,jar包下载,依赖包