跟我学EJB 分布式编程技术——实现JNDI检索的基类和EJBHandle实现实例
- 格式:pdf
- 大小:256.72 KB
- 文档页数:14
目录1.1EJB WebService相关实现技术及应用实例 (2)1.1.1EJB作为Web服务端点技术概述 (2)1.1.2EJB WebService实例应用 (5)1.1.3编译该EJB组件 (9)1.1.4将该EJB组件发布为WebService组件 (9)1.1.5导出EJBBean组件 (17)1.1.6对客户和服务器进行设置 (17)1.1.7查看该客户端的*.jar文件 (20)1.1.8发布该EAR文件 (22)1.1.9查看所部署的结果 (22)1.1EJB WebService相关实现技术及应用实例1.1.1EJB作为Web服务端点技术概述1、JAX-RPC快速入门(1)JAX-RPC(Java API for XMLbased RPC)顾名思义,它是一种远程方法调用(或者说远程过程调用),那么它和其它的远程方法调用(RPC, COM,CORBA,RMI)有什么区别呢?(2)一般的远程方法调用的结构我们看一般的远程方法调用的结构,如下图所示。
综合比较常用的远程方法调用技术,它们有以下的共性:●在客户端和服务端有通用编程接口;●在客户端有Stub,在服务端有Tie(有的叫Skeleton);●客户端和服务端有专门的协议进行数据传输。
对于通用接口的描述,比如CORBA有IDL of CORBA,Java RMI有Java RMI interface in RMI,对于XMLbased RPC来说,IDL就是WSDL(Web服务描述语言)。
那么XMLbased RPC来说,什么是这个结构中的"传输协议",当然是SOAP,SOAP消息通过以传输文本为基础的协议(HTTP、SMTP、FTP)为载体来使用的,也就是说,SOAP消息的传输建立在HTTP传输协议之上。
(3)JAX-RPC的构架从上图可以看出,客户端调用的是JAX-RPC服务端点(Service Endpoint),这个服务端点是通过WSDL语言描述的。
菜鸟学EJB(⼀)——第⼀个实例EJB⽤了那么长时间了,从来没写过关于它的东西,挺对不住它的。
今天先写⼀个简单的⼩实例,虽然⼩但是却能体现出EJB的核⼼——分布式。
我们可以将业务逻辑的接⼝跟实现部署到⼀台机器上,将调⽤它们的客户端部署到另⼀台机器上。
⾄于为什么要⽤分布式,今天不做讨论,以后再细说。
先来看接⼝:package com.tjb.ejb;public interface MyEjb {String helloEjb ();}接下来是对接⼝的具体实现:package com.tjb.ejb;import javax.ejb.Remote;import javax.ejb.Stateless;import javax.jws.WebMethod;import javax.jws.WebService;@Stateless@Remote@WebServicepublic class MyEjbBean implements MyEjb {public String helloEjb() {return "Hello EJB";}}然后编写⼀个客户端来通过接⼝调⽤我们的实现:package com.tgb.ejb;import javax.naming.InitialContext;import javax.naming.NamingException;import com.tjb.ejb.MyEjb;public class MyEjbClient {public static void main(String[] args) throws NamingException {InitialContext ctx = new InitialContext();MyEjb ejb = (MyEjb) ctx.lookup("MyEjbBean/remote");String hello = ejb.helloEjb();System.out.println(hello);}}客户端实例化⼀个上下⽂对象,然后通过其lookup⽅法查找远程实现,最后调⽤具体的⽅法。
目录1.1跟我学EJB 分布式编程技术——WebLogic下的事务JTA编程实例 (2)1.1.1利用JTA实现事务管理相关的技术 (2)1.1.2了解JTS 和JTA之间的关系和差别 (6)1.1.3JDBC事务编程实现 (8)1.1.4BEAN管理的事务实现及实例 (10)1.1.5容器管理的事务 (12)1.1.6在Java中的事务处理技术编程的实例 (17)1.1跟我学EJB 分布式编程技术——WebLogic下的事务JTA编程实例1.1.1利用JTA实现事务管理相关的技术1、事务概述(1)什么是事务事务是一种手段,用于保证一系列的数据库操作能够准确的完成并将在(分布式)资源上的一组操作被当作一个工作单元(unit)。
以保证数据的准确性、可靠性、一致性和时效性。
(2)应用的领域在贸易、金融和电子商业领域中,多数大的企业应用依赖于递送它们的商务的事务处理功能。
鉴于当今商务对灵活性的要求,在建造、部署和维护企业级别的分布式应用中,事务处理占据的是其中最复杂的部分之一。
(3)为什么要使用事务完成一个操作可能需要使用多步使用事务的一个重要原因,是完成一个操作可能需要使用多步,其中任何一步操作的失败,都希望全部回滚。
提供事务的目的在于简化既要求可靠性又要求可用性的应用程序结构,特别是那些需要同时访问共享数据的应用程序。
以银行转账系统为例:如下图所示,转账是通过两步完成的,但转账时,提款是正确的,但存款错误,总的账目将发生不平衡,显然这是不允许的。
因为一个将资金从一个帐户转移到另一个帐户的Enterprise beans 中可能有一系列方法,它们是借记第一个帐户,贷记第二个帐户。
你想将整个操作作为一个单元处理,但是,如果借记后、贷记前出现故障,借记就会滚回。
不必处理数据库故障恢复和维护数据库完整性利用事务管理,可以把应用程序的工作分成若干称为事务的工作单元。
此时,开发者就不必处理数据库故障恢复和维护数据库完整性这样的复杂问题。
1.1JBuilder MessageBean (2)1.1.1WebLogic (2)1.1.2JBuilder MDB (5)1.1.3 (10)1.1.4 (15)1.1.5MapMessage (18)1.1JBuilder MessageBean1.1.1WebLogic"Connection Factory""File Stores""JMS Servers""JMS Queue"1WebLogic MDB1Connection Factories JNDI EBussFactory2File Stores EBussStore c:\temp3JMS Servers EbussJMSServer4JMS Queue JNDI EBussJMSQueueJNDI EBussJMSQueue21EBussFactoryName JNDI EBussFactory2EBussJMSFileStore c:\temp3JMSEBussJMSServer4EBussJMSQueue JNDI EBussJMSQueueJNDI3Topic JNDI 1"JMS Topic..."Name EBussJMSTopicJNDI Name EBussJMSTopicJNDI"Create" "Apply"1.1.2JBuilder MDB1JBuilder Project JMSEJBBean2EJB ModuleJMSMDBBean 2.03MDB1)MDB MDBEJBBean2)Message Selector3)DestinName EBussJMSQueueJNDIJNDI weblogic mydomain> JMS Servers> MyJMSServer> JMS Destinations JNDI Name1)Destination Type javax.jms.Queue2)Connect Factory Name EBussFactory weblogic JMS connectionfactory JNDI Name3)Transaction type Bean BeanMessageJMSSQL-92 SQL WHERE item<message-selector>item = 'Financial Analysis' OR item ='Gardening'</message-selector>MDBEJBBean.javapackage jmsejbbean;import javax.ejb.*;import javax.jms.*;import javax.naming.*;public class MDBEJBBean implements MessageDrivenBean, MessageListener { MessageDrivenContext messageDrivenContext;public void ejbCreate() throws CreateException {/**@todo Complete this method*/}public void ejbRemove() {/**@todo Complete this method*/}public void onMessage(Message msg) {/**@todo Complete this method*/}public void setMessageDrivenContext(MessageDrivenContext messageDrivenContext) { this.messageDrivenContext = messageDrivenContext;}}4MDB onMessage(Message msg)MessageListenerEJBpublic void onMessage(Message msg){try{if (msg instanceof TextMessage){TextMessage text=(TextMessage)msg;System.out.println(text.getText()); //}else{System.out.println("error text");}}catch(JMSException e) //TextMessage.getText() {}}5Project6ejb-jar.xml MDB7weblogic-ejb-jar.xml1.1.31jmsejbbeanClient QueueSend2package jmsejbbeanClient;import java.io.*;import java.util.Hashtable;import javax.jms.*;import javax.naming.*;public class QueueSend{// Defines the JNDI context factory.public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";// Defines the JMS context factory.public final static String JMS_FACTORY="EBussFactory";//weblogic JMS Connection Factories JNDI Namepublic final static String QUEUE="EBussJMSQueueJNDI";//weblogic mydomain> JMS Servers> MyJMSServer> JMS Destinations JNDI Nameprivate QueueConnectionFactory queueConnectionFactory;private QueueConnection queueConnection;private QueueSession queueSession;private QueueSender queueSender;private Queue queue;private TextMessage textMessage;public void init(Context ctx, String queueName) throws NamingException, JMSException{//1weblogic JMS Connection Factories JNDI NameConnection FactoriesqueueConnectionFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);//2Connection Factories QueueConnection queueConnection = queueConnectionFactory.createQueueConnection();//3QueueConnection QueueSessionqueueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);//4weblogic mydomain> JMS Servers> MyJMSServer> JMS Destinations JNDI Name Queuequeue = (Queue) ctx.lookup(queueName);//5QueueSession QueueSenderqueueSender = queueSession.createSender(queue);//QueueSession TextMessagetextMessage = queueSession.createTextMessage();//6queueConnection.start();}public void send(String message) throws JMSException{textMessage.setText(message); //7queueSender.send(textMessage); //8}public void close() throws JMSException{queueSender.close();queueSession.close();queueConnection.close();}private void readAndSendMessageText(QueueSend messageQueueSendClient) throws IOException, JMSException{BufferedReader msgStream = new BufferedReader(new InputStreamReader(System.in));String userMessageText=null;boolean isQuitNow = false;do{ //'quit'System.out.print("('quit'): ");userMessageText=msgStream.readLine();if (userMessageText != null && userMessageText.trim().length() != 0){messageQueueSendClient.send(userMessageText);System.out.println("JMS:"+userMessageText+"\n");isQuitNow = userMessageText.equalsIgnoreCase("quit");}}while (! isQuitNow);}public static void main(String[] args) throws IOException, JMSException,javax.naming.NamingException{QueueSend messageQueueSendClient = new QueueSend();InitialContext ic =messageQueueSendClient.getInitialContext("t3://localhost:7001");messageQueueSendClient.init(ic, QUEUE);messageQueueSendClient.readAndSendMessageText(messageQueueSendClient);messageQueueSendClient.close(); //9}private static InitialContext getInitialContext(String url) throws NamingException{Hashtable env = new Hashtable();env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);env.put(Context.PROVIDER_URL, url);return new InitialContext(env);}}1.1.41*.jar2WebLogic3WebLogic"JMSMDBBean"4JMS5MDB1)weblogic JMS Connection Factories JNDI NameConnection Factories2)Connection Factories QueueConnection3)QueueConnection QueueSession4)weblogic mydomain> JMS Servers> MyJMSServer> JMS DestinationsJNDI Name Queue5)QueueSession QueueSender6)QueueSession TextMessage7)8)9)10)1.1.5MapMessage1TextMessageMapMessageMapMessage2package jmsejbbeanClient;import java.io.*;import java.util.Hashtable;import javax.jms.*;import javax.naming.*;public class QueueSend{// Defines the JNDI context factory.public final static String JNDI_FACTORY="weblogic.jndi.WLInitialContextFactory";// Defines the JMS context factory.public final static String JMS_FACTORY="EBussFactory";//weblogic JMS Connection Factories JNDI Namepublic final static String QUEUE="EBussJMSQueueJNDI";//weblogic mydomain> JMS Servers> MyJMSServer> JMS Destinations JNDI Nameprivate QueueConnectionFactory queueConnectionFactory;private QueueConnection queueConnection;private QueueSession queueSession;private QueueSender queueSender;private Queue queue;private MapMessage mapMessage;public void init(Context ctx, String queueName) throws NamingException, JMSException{//1weblogic JMS Connection Factories JNDI NameConnection FactoriesqueueConnectionFactory = (QueueConnectionFactory) ctx.lookup(JMS_FACTORY);//2Connection Factories QueueConnection queueConnection = queueConnectionFactory.createQueueConnection();//3QueueConnection QueueSessionqueueSession = queueConnection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);//4weblogic mydomain> JMS Servers> MyJMSServer> JMS Destinations JNDI Name Queuequeue = (Queue) ctx.lookup(queueName);//5QueueSession QueueSenderqueueSender = queueSession.createSender(queue);//QueueSession TextMessagemapMessage = queueSession.createMapMessage();//6queueConnection.start();}public void send() throws JMSException{mapMessage.clearBody(); //7mapMessage.setInt("userID", 1234); //name=" userID"Value= 1234 mapMessage.setString("userName", "");mapMessage.setInt("userAge", 30);mapMessage.setString("userEMAIL", "abc@");queueSender.send(mapMessage); //8System.out.println("JMS");}public void close() throws JMSException{queueSender.close();queueSession.close();queueConnection.close();}public static void main(String[] args) throws IOException,JMSException,javax.naming.NamingException{QueueSend messageQueueSendClient = new QueueSend();InitialContext ic =messageQueueSendClient.getInitialContext("t3://localhost:7001");messageQueueSendClient.init(ic, QUEUE);messageQueueSendClient.send();messageQueueSendClient.close(); //9}private static InitialContext getInitialContext(String url) throws NamingException {Hashtable env = new Hashtable();env.put(Context.INITIAL_CONTEXT_FACTORY, JNDI_FACTORY);env.put(Context.PROVIDER_URL, url);return new InitialContext(env);}}3package jmsejbbean;import javax.ejb.*;import javax.jms.*;import javax.naming.*;public class MDBEJBBean implements MessageDrivenBean, MessageListener {MessageDrivenContext messageDrivenContext;public void ejbCreate() throws CreateException {/**@todo Complete this method*/}public void ejbRemove() {/**@todo Complete this method*/public void onMessage(Message msg){try{if (msg instanceof TextMessage){TextMessage text=(TextMessage)msg;System.out.println(text.getText()); //}else if (msg instanceof MapMessage){MapMessage mapMessage = (MapMessage) msg;System.out.println("");System.out.println("ID"+mapMessage.getInt("userID"));System.out.println(""+mapMessage.getString("userName"));System.out.println(""+mapMessage.getInt("userAge"));System.out.println("Email"+mapMessage.getString("userEMAIL"));}else{System.out.println("");}}catch(JMSException e) //TextMessage.getText(){}/***Bean context*/public void setMessageDrivenContext(MessageDrivenContext messageDrivenContext) {this.messageDrivenContext = messageDrivenContext;}}45WebLogic。
1.1J2EE架构师——J2EE EJB分布式组件编程应用技术培训课程
1、课程简介
本课程是J2EE架构师中的第一阶段—— J2EE EJB分布式组件编程技术,学员经过二个阶段的课程模块的系统培训学习,将帮助软件开发人员最终掌握J2EE企业开发技术和系统构架、设计模式以及后台数据库。
2、学习基础
掌握JAVA核心技术,JAVA高级应用开发,J2EE Web应用开发技术。
3、培训目标
掌握和使用Workshop、JBuilder和WebLogic等工具开发和部署J2EE多层、松耦合和可重用的企业级组件。
内容涵盖EJB的三大组件技术,同时还将涉及JNDI、RMI和J2EE的安全验证授权,综合应用等方面的内容。
实现企业级多层分布式应用的RMI、JNDI和EJB组件技术(三种EJB Bean)以及J2EE 的安全/事务/资源连接服务,能够独立完成J2EE四层构架的项目开发。
4、培训时间
6天,48学时。
上午(8:30--11:45,4学时)、下午(1:00--4:15,4学时),人手一机,边学边练、逐步深入!强调独立实践操作能力、实例讲解。
5、培训内容(可根据具体学员的基础进行适当调整,以便学员能够快速接受)。
目录1.1无状态的SessionBean等EJB的安全访问实现实例 (2)1.1.1访问EJB的安全技术 (2)1.1.2在Weblogic服务器的控制台中创建出用户和用户组 (4)1.1.3在EJB配置描述文件中定义安全角色和对该角色进行授权 (8)1.1.4管理委托策略及应用实例 (14)1.1无状态的SessionBean等EJB的安全访问实现实例1.1.1访问EJB的安全技术1、安全性技术概述(1)安全策略安全是每个企业级应用不可缺少的一部分,一个安全应用必须考虑安全策略,以保护应用中每一个层次上的资源。
比如可以将企业应用系统划分为企业员工、供应商、合作伙伴等不同的安全域,对这些安全区域采用不同的安全策略下面,我们将会详细讨论如何建立一个安全的WebLogic的应用。
这里,我们将介绍EJB 容器中一个标准的安全特性。
一个安全的EJB应用应该利用EJB容器提供的安全服务,集成到应用的安全模型中去。
(2)基于容器的安全在J2EE的环境中,组件的安全是由他们各自的容器来负责的,组件的开发人员几乎可以不用或者很少在组件中添加有关安全的代码。
这种安全逻辑和业务逻辑相对独立的架构,使得企业级应用系统有更好的灵活性和扩展性。
因为J2EE的规范要求J2EE产品必须为应用程序开发者提供两种形式的基于容器的安全性-----说明性的安全性和可编程的安全性。
2、说明性的安全性(1)部署描述符文件说明性的安全性是通过安全结构描述的方式来代表应用程序的安全需求,安全结构一般包括安全角色,访问控制和验证要求等。
在J2EE平台中的EJB组件的部署描述符将充当说明性的安全性的主要工具。
部署描述符是组件开发者和应用程序部署者或应用程序组装者之间的交流工具。
应用程序的开发者用它来表示应用中的安全需求,应用程序部署者或应用程序组装者将安全角色与部署环境中的用户和组映射起来。
(2)标准的EJB安全模型安全角色标准的EJB安全模型基于EJB配置描述器中的设置以及简单的编程安全接口。
目录1.1实现JNDI检索的基类和EJBHandle实现实例 (2)1.1.1实现JNDI检索的基类 (2)1.1.2修改访问EJB组件的客户端程序 (4)1.1.3执行该客户程序 (7)1.1.4使用EJB Bean的句柄来保存EJB (7)1.1.5句柄应用程序例 (13)1.1.6HomeHandle的应用例 (13)1.1.7应用Handle所应该注意的问题 (14)1.1实现JNDI检索的基类和EJBHandle实现实例1.1.1实现JNDI检索的基类1、概述由于在EJB的客户程序中的JNDI检索是非常标准的,所以我们在应用中没有必要每次写客户程序的时候都重新编写它,而可以专门做一个类GetEJBHomeByJNDI,放在文件GetEJBHomeByJNDI.java中。
实际的客户程序可以从该类来继承和派生。
2、GetEJBHomeByJNDI.java文件(1)添加一个类(2)包名称为statlessSBclient,类名称为GetEJBHomeByJNDI(3)编程该类的代码package statlessSBclient;import javax.naming.*;import java.util.Properties;import javax.rmi.PortableRemoteObject;public class GetEJBHomeByJNDI extends Object {public Context getInitialContext() throws Exception {String url = "t3://localhost:7001";/* String user = null;String password = null;*/String user = "WebAdmin";String password = "12345678";Properties properties = null;try{properties = new Properties();properties.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");properties.put(Context.PROVIDER_URL, url);if (user != null) {properties.put(Context.SECURITY_PRINCIPAL, user);properties.put(Context.SECURITY_CREDENTIALS, password == null ? "" : password);}return new InitialContext(properties);}catch(Exception e){System.out.println("Unable to connect to WebLogic server at " + url);System.out.println("Please make sure that the server is running.");throw e;}}}1.1.2修改访问EJB组件的客户端程序package statlessSBclient;import statelesssessionbean.*;import javax.naming.*;import java.util.Properties;import javax.rmi.PortableRemoteObject;public class mathSessionEJBBeanTestClient extends GetEJBHomeByJNDI{private mathSessionEJBHome mathSessionEJBHomeObject = null;private mathSessionEJB mathSessionEJBRemote = null; //声明一个Remote接口对象//Construct the EJB test clientpublic mathSessionEJBBeanTestClient(){initialize();}public void initialize(){try{Context context = getInitialContext(); //get naming contextObject ref = context.lookup("mathSessionEJBBean"); //look up jndi name//look up jndi name and cast to Home interfacemathSessionEJBHomeObject = (mathSessionEJBHome) PortableRemoteObject.narrow(ref, mathSessionEJBHome.class);//下面为创建出Remote主接口类型的对象mathSessionEJBRemote = mathSessionEJBHomeObject.create();//下面为利用Remote主接口类型的对象对EJBBean类中的方法进行访问System.out.println("利用无状态会话EJB计算10+20的结果="+mathSessionEJBRemote.getSummary(10,20));System.out.println("获得无状态会话EJB中的环境变量"+mathSessionEJBRemote.getEJBEnvItem());}catch(Exception e){e.printStackTrace();}}public void executeRemoteCallsWithDefaultArguments(mathSessionEJB mathSessionEJBObject){if (mathSessionEJBObject == null){return ;}try{mathSessionEJBObject.getSummary(0 ,0);}catch(Exception e){e.printStackTrace();}}//----------------------------------------------------------------------------// Utility Methods//----------------------------------------------------------------------------public mathSessionEJBHome getHome(){return mathSessionEJBHomeObject;}//Main methodpublic static void main(String[] args){mathSessionEJBBeanTestClient client = new mathSessionEJBBeanTestClient();// Use the getHome() method of the client object to call Home interface// methods that will return a Remote interface reference. Then// use that Remote interface reference to access the EJB.}}1.1.3执行该客户程序1.1.4使用EJB Bean的句柄来保存EJB1、关于句柄的使用在某些情况下,EJB客户机也许希望把EJBObject引用保留到永久的设备上,以便将来使用,甚至在另一个程序中使用。
EJB规范定义了句柄(Handle)的概念。
作为一个序列化对象,据柄中封装了足够的信息,以便重建对EJBObject的引用。
2、获得句柄或者重建EJB Bean的引用只能用remote接口的句柄来重新建立Bean的引用。
你不能用句柄来创建Bean本身。
如果另一个进程删除了Bean,或者系统崩溃或关闭,删除了Bean的实例,则当应用程序试图用句柄重新建立对Bean的引用时会抛出异常。
当你不确定Bean的实例是否依然存在的时候,你可以不用remote接口的句柄。
而是保存Bean的home接口的句柄,在以后要用的时候再通过调用create方法或finder方法重新创建Bean对象。
在客户创建了Bean的实例以后,就能够用getHandle()方法来获得实例的句柄。
一旦拥有的句柄,就能够将它写到文件里面去。
在以后的时间,客户可以读这个文件,将读出来的对象转化为句柄类型。
然后,就可以在句柄上调用的getEJBObject方法来获得bean的引用。
最后再将getEJBObject方法返回的值转化为合适的类型。
为了取得句柄,程序员可以调用EJBObject接口中的getHandle()方法,该方法返回一个javav.ejb.Handle实例。
为了重建EJBObject的引用,可以使用Handle接口的getEJBObject()方法。
3、在客户程序中根据Bean的Remote对象获得并保存其句柄javax.ejb.Handle mathSessionEJBHander=null;…mathSessionEJBRemote = mathSessionEJBHomeObject.create();mathSessionEJBHander=mathSessionEJBRemote.getHandle();4、将句柄序列化到某一文件中FileOutputStream fileOutputStream = new FileOutputStream("mathSessionEJBHander.ser");ObjectOutputStream objectOutputStream= new ObjectOutputStream(fileOutputStream);objectOutputStream.writeObject(mathSessionEJBHander);objectOutputStream.flush();objectOutputStream.close();此时在磁盘文件中的项目目录下将产生出一个mathSessionEJBHander.ser文件。