JCA入门(下)

ref:http://weli.iteye.com/blog/1591180

本文特邀lgao撰写 

在本系列文章的上篇中: 

http://bluedash.iteye.com/blog/1566189 

阿男为大家讲解了JCA的概念。本文将由我用一个例子来描述怎么进行ResourceAdapter的开发。 

在本文中我们要用到的EIS是一个Servlet的服务,运行在一个JBoss AS服务器上(实际上运行在哪里无所谓,是什么也不重要。因为JCA标准中,并没有对EIS的形式或内容做要求。可以是文件,数据库,FTP服务,或像本文要用到的这个HTTP Servlet服务)。 

这个项目的功能是列出自己电脑上的目录。我们将这个项目命名为: 

* services-1.0.0.war 

然后我们要使用另一台JBoss AS服务器做为Application Server,在这上面开发一个ResourceAdapter,用RAR的形式部署,将EIS接进来。将这个项目命名为: 

* listfiles-0.1.rar 

最后,我们要在Application Server上面开发一个Web应用,使用这个ResourceAdapter为我们接入的EIS资源,提供给最终用户进行使用。这个项目名为: 

* listfiles-0.1.war 

示例的整体架构图如下: 



接下来是实施过程: 

制作EIS 

在一般的JCA开发过程中,应该是没有这步的,因为我们是要将已有的EIS通过ResourceAdpator接进Application Server。但是因为这个例子要为大家展示完整的过程,因此我们要首先动手制作一个EIS。 

首先使用maven[1]创建一个webapp: 

Bash代码  收藏代码
  1. $ mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=webapp-javaee6 -DgroupId=org.jboss.jca.sample.eis -DartifactId=services -Dversion=1.0.0 -B  


我们要做一个Servlet,这个Servlet的功能很简单:用户给出一个dir目录,Servlet列出这个目录中的文件,就相当于ls命令: 

Java代码  收藏代码
  1. package org.jboss.jca.sample.eis;  
  2.   
  3. import java.io.File;  
  4. import java.io.IOException;  
  5. import java.io.PrintWriter;  
  6.   
  7. import javax.servlet.ServletException;  
  8. import javax.servlet.annotation.WebServlet;  
  9. import javax.servlet.http.HttpServlet;  
  10. import javax.servlet.http.HttpServletRequest;  
  11. import javax.servlet.http.HttpServletResponse;  
  12.   
  13. @WebServlet(urlPatterns = {"/listfiles"})  
  14. public class ListFilesServlet extends HttpServlet {  
  15.     private static final long serialVersionUID = 1L;  
  16.   
  17.     @Override  
  18.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  19.         String dir = request.getParameter("dir");  
  20.         StringBuilder sb = new StringBuilder();  
  21.         if (dir != null && !dir.isEmpty()) {  
  22.             File file = new File(dir);  
  23.             if (file.exists() && file.canRead() && file.isDirectory()) {  
  24.                 for (File f : file.listFiles()) {  
  25.                     if (f.isDirectory()) {  
  26.                         sb.append("drwx------\t" + f.getName() + "<br />\n");  
  27.                     } else if (f.isFile()) {  
  28.                         sb.append("-rwx------\t" + f.getName() + "<br />\n");  
  29.                     }  
  30.                 }  
  31.             }  
  32.         } else {  
  33.             sb.append("Unkown Directory: " + dir);  
  34.         }  
  35.         request.setCharacterEncoding("UTF-8");  
  36.         PrintWriter out = response.getWriter();  
  37.         out.println(sb.toString());  
  38.         out.flush();  
  39.     }  
  40.   
  41. }  


这就是这个EIS的全部功能了,接下来将项目打包: 

Bash代码  收藏代码
  1. mvn package  


生成services-1.0.0.war,然后我们将它部署到JBoss AS服务器上,这个项目就算弄完了。 

制作ResourceAdapter 

接下来我们要制作核心部分ResourceAdapter。在这里,我们要用到JBoss社区的JCA标准实现框架IronJacamar[2]。 

IronJacamar下载完成后,切换到: 

Bash代码  收藏代码
  1. ironjacamar-1.0.10.Final/doc/codegenerator/  


运行: 

Bash代码  收藏代码
  1. ./codegenerator.sh  


按照提示输入: 

 

在上述提示中, 红色下划线标记的为输入,其他因为采用提示给的默认值,因此直接回车就可以。其中: 

Bash代码  收藏代码
  1. Value: http://192.168.1.103:8080/services/listfiles    


这个配置指向你的EIS所在机器的IP地址。此外注意到我们设置中的Transaction Support和Re-authenticatiion都是No。也就是说,我们不准备在这个ResourceAdapter中实现事务管理contract和认证contract。是一个相当简单的ResourceAdapter。 

完成后,会在当前目录下产生一个叫做out的目录,并生成了一系列的Java代码,下面是out目录结构: 

 

我们看一下相应的类图: 



* 在JCA规范中,暴露给用户的连接管理接口是ConnectionFactory。在本例当中我们的ConnectionFactory为ListFilesConnectionFactory。 
* 通过ListFilesConnectionFactory.getConnection()获取到ListFilesConnection实例。 
* ListFilesConnection 实例通过 ListFilesManagedConnection与相应的EIS 交互。 
* ListFilesMangedConnection代表和EIS的物理连接;ListFilesConnection是这个物理连接的Handler。 

首先我们实现ListFilesConnection接口,定义一个方法: 

Java代码  收藏代码
  1. /**  
  2. * Call the EIS ListFilesServlet and get response 
  3. */  
  4. public String listFiles(String dir);  



然后在ListFilesConnectionImpl中实现它: 

Java代码  收藏代码
  1. ...  
  2. private ListFilesManagedConnection mc;  
  3. ...  
  4. public String listFiles(String dir)  
  5. {     
  6.     return mc.listFiles(dir);  
  7. }  


注意到ListFilesManagedConnection是实际要实现这个方法的地方,因此,接下来我们要在ListFilesManagedConnection中实现与EIS实际交互的逻辑。因为我们的EIS是一个Servlet的Web服务,因此通过网络调用它,并获取返回值,实现EIS的接入: 

Java代码  收藏代码
  1. /** 
  2.  * List Files of directory 'dir' in EIS machine. 
  3.  * 
  4.  * @return a String contains all files in the directory 
  5.  */  
  6. String listFiles(String dir) {  
  7.     ListFilesResourceAdapter ra = (ListFilesResourceAdapter) this.mcf.getResourceAdapter();  
  8.     String listFilesServiceURL = ra.getListFilesServiceURL();  
  9.     String listFilesServiceParam = ra.getListFilesServiceParam();  
  10.     StringBuilder sb = new StringBuilder();  
  11.     java.net.HttpURLConnection conn = null;  
  12.     try {  
  13.         String dirEncoded = java.net.URLEncoder.encode(dir, "UTF-8");  
  14.         String url = listFilesServiceURL + "?" + listFilesServiceParam + "=" + dirEncoded;  
  15.         conn = (java.net.HttpURLConnection) new java.net.URL(url).openConnection();  
  16.         conn.setDoOutput(true);  
  17.         conn.connect();  
  18.   
  19.         java.io.InputStream in = conn.getInputStream();  
  20.         java.io.BufferedReader reader = new java.io.BufferedReader(new java.io.InputStreamReader(in, "UTF-8"));  
  21.         String line = null;  
  22.         while ((line = reader.readLine()) != null) {  
  23.             sb.append(line);  
  24.         }  
  25.     } catch (Exception e) {  
  26.         e.printStackTrace();  
  27.     } finally {  
  28.         if (conn != null) {  
  29.             conn.disconnect();  
  30.         }  
  31.     }  
  32.     return sb.toString();  
  33. }  



Java代码挺简单的,接下来我们要编辑IronJacamar的配置文件: 

Xml代码  收藏代码
  1. src/main/rar/META-INF/ironjacamar.xml  


下面是配置的详细内容,很容易理解: 

Xml代码  收藏代码
  1. <ironjacamar xmlns="http://www.jboss.org/ironjacamar/schema"  
  2.              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  3.              xsi:schemaLocation="http://www.jboss.org/ironjacamar/schema   
  4.         http://www.jboss.org/ironjacamar/schema/ironjacamar_1_0.xsd">  
  5.     <!--这里修改 config property 的值-->  
  6.     <config-property name="listFilesServiceURL">  
  7.         http://192.168.1.103:8080/services/listfiles  
  8.     </config-property>  
  9.     <config-property name="listFilesServiceParam">dir</config-property>  
  10.   
  11.     <transaction-support>NoTransaction</transaction-support>  
  12.   
  13.     <connection-definitions>  
  14.         <connection-definition class-name="org.jboss.jca.sample.listfiles.ListFilesManagedConnectionFactory"  
  15.                                jndi-name="java:/eis/ListFilesConnectionFactory" pool-name="ListFilesConnectionFactory">  
  16.         </connection-definition>  
  17.     </connection-definitions>  
  18. </ironjacamar>  


ResourceAdapter的全部代码工作至此完成了,接下来将项目打包: 

Bash代码  收藏代码
  1. mvn package  


生成listfiles-0.1.rar,这个就是我们需要的RAR文件了。将这个文件部署到Application Server当中。 

创建客户端 

有了EIS,也有了ResourceAdapter来接入这个EIS,接下来我们要写一个客户端应用,来通过ResourceAdapter使用这个EIS。请注意这里面说的客户端并不是最终用户,而是通过ResouceAdapter来使用EIS的应用,我们称其为客户端。 

还是使用mvn来创建一个Web项目: 

Bash代码  收藏代码
  1. $ mvn archetype:generate -DarchetypeGroupId=org.codehaus.mojo.archetypes -DarchetypeArtifactId=webapp-javaee6 -DgroupId=org.jboss.jca.sample.listfiles -DartifactId=listfileweb -Dversion=1.0.0 -B  


仅需要撰写一个jsp文件,打开: 

Xml代码  收藏代码
  1. src/main/webapp/index.jsp  


内容如下: 

Java代码  收藏代码
  1. <%@ page import="org.jboss.jca.sample.listfiles.*" %>  
  2. <html>  
  3. <body>  
  4. <h2>Hello JCA!</h2>  
  5. <form action="index.jsp">  
  6. Directory: <input type="text" name="dir" />&nbsp;&nbsp;&nbsp;&nbsp;<input type="submit" value="List Files"/>  
  7. </form>  
  8. <br />  
  9. <%  
  10.          String dir = request.getParameter("dir");  
  11.          String files = "";  
  12.          if (dir != null && dir.length() != 0){  
  13.              String jndiName = "java:/eis/ListFilesConnectionFactory";  
  14.              javax.naming.InitialContext ctx = null;  
  15.              try  
  16.              {  
  17.                 ctx = new javax.naming.InitialContext();  
  18.                 Object obj = ctx.lookup(jndiName);  
  19.                 if(obj != null){  
  20.                     ListFilesConnectionFactory connFactory = (ListFilesConnectionFactory)obj;  
  21.                     ListFilesConnection conn = connFactory.getConnection();  
  22.                     files = conn.listFiles(dir);  
  23.                     conn.close();  
  24.                 }  
  25.              }  
  26.              catch (Exception e)  
  27.              {  
  28.                 e.printStackTrace();  
  29.              }  
  30.              finally  
  31.              {  
  32.                 try  
  33.                 {  
  34.                    ctx.close();  
  35.                 }  
  36.                 catch (Exception e)  
  37.                 {  
  38.                    e.printStackTrace();  
  39.                 }  
  40.              }  
  41.   
  42. %>  
  43. <div>Files under directory <%= dir %> : <br /> <%= files %></div>  
  44. <%  
  45.          }  
  46. %>  
  47. </body>  
  48. </html>  


功能很简单:给用户一个输入表单->输入需要显示的目录->将用户的请求提交给ResourceAdapter->ResourceAdapter去调用EIS并返回结果。 

虽然功能不难,但是代码当中包含了很多ResourceAdapter的调用方法: 

Java代码  收藏代码
  1. String jndiName = "java:/eis/ListFilesConnectionFactory";  
  2.   
  3. javax.naming.InitialContext ctx = null;  
  4. ctx = new javax.naming.InitialContext();  
  5.   
  6. Object obj = ctx.lookup(jndiName);  
  7.   
  8. ListFilesConnectionFactory connFactory = (ListFilesConnectionFactory)obj;  
  9. ListFilesConnection conn = connFactory.getConnection();  
  10.   
  11. files = conn.listFiles(dir);  
  12.   
  13. conn.close();  


接下来我们需要编辑一下: 

Bash代码  收藏代码
  1. MANIFEST.MF  


这个文件,因为在JBoss AS 7中, 要求这个文件中包含项目所依赖的ResourceAdapter信息,格式如下: 

Xml代码  收藏代码
  1. Dependencies: deployment.<RAR Name>  


因此我们在这个文件中添加内容如下: 

Xml代码  收藏代码
  1. Dependencies: deployment.listfiles-0.1.rar  


指定这个客户端项目依赖于listfiles-0.1.rar。最后还是项目打包: 

Bash代码  收藏代码
  1. mvn package  


生成listfileweb-1.0.0.war。 

部署 

至此为止,我们应该有了三样东西: 

* services.war - EIS 
* listfileweb-1.0.0.rar - RAR 
* listfileweb-1.0.0.war - Client 

我们要部署这些组件: 

将listfileweb-1.0.0.rar和listfileweb-1.0.0.war部署在机器A的JBoss AS上面 

假设 JBoss AS 7 的目录在 ~/softwares/jboss-as/jboss-as-7.1.1.Final/, 那么我们运行命令: 

Bash代码  收藏代码
  1. [lgao@lgao jca]$ cd ~/softwares/jboss-as/jboss-as-7.1.1.Final/  
  2. [lgao@lgao jboss-as-7.1.1.Final]$ bin/standalone.sh  


运行完以上指令, JBoss AS 7 就会启动, 之后我们来部署 listfiles RAR 和 listfileweb WAR,打开另外一个控制台,然后输入: 

Bash代码  收藏代码
  1. [lgao@lgao jboss-as-7.1.1.Final]$ bin/jboss-cli.sh --connect  
  2. [standalone@localhost:9999 /] deploy ~/jca/listfiles-0.1.rar  
  3. [standalone@localhost:9999 /] deploy ~/jca/listfileweb-1.0.0.war  


如果两条指令没有错误提示, 部署就成功了。 我们可以确认下: 

Bash代码  收藏代码
  1. [standalone@localhost:9999 /] deploy -l  
  2. NAME                  RUNTIME-NAME          ENABLED STATUS   
  3. listfiles-0.1.rar     listfiles-0.1.rar     true    OK       
  4. listfileweb-1.0.0.war listfileweb-1.0.0.war true    OK      


将services.war部署在机器B的JBoss AS上面 

部署services.war的方法没什么不同,不再赘述。但是这台机器上面的JBoss AS7的配置要稍做改变,因为我们需要让机器A中的ResourceAdapter能访问到这台机器上面的EIS资源,而AS7默认只侦听localhost,所以要做出配置修改。打开: 

Bash代码  收藏代码
  1. jboss-as-7.1.1.Final\standalone\configuration\standalone.xml  


修改: 

Xml代码  收藏代码
  1. <interface name="public">  
  2.     <inet-address value="${jboss.bind.address:127.0.0.1}"/>  
  3. </interface>  


为: 

Xml代码  收藏代码
  1. <interface name="public">  
  2.     <any-address />  
  3. </interface>  


然后启动AS7服务器: 

Bash代码  收藏代码
  1. bin/standalone.sh  


测试 

万事俱备,接下来进行测试。在机器A上面访问Client: 

Html代码  收藏代码
  1. http://127.0.0.1:8080/listfileweb-1.0.0/  


效果如下: 

 

在输入框里写上要查看的目录文件列表,此时RAR会调用EIS,返回EIS所在的机器B中的目录内容: 

 

以上,我们就完成了这个例子全部内容的展示。 

小结 

本文通过一个例子向大家展示JCA中ResourceAdapter的开发过程,以及对它的使用方式。虽然这个例子非常简单,仅实现了JCA标准中提供的三个contracts中的最基本的Connection Management,但是它的流程是完整的,在此基础上,你可以继续深入阅读JCA的相关资料,进一步学习它,也可以为阅读现有EIS的ResouceAdapter的源代码打下良好基础。相信这会是一个好的起点。 

代码 

本文中用到的三个代码我放在了github上面,有兴趣可以迁出: 

EIS 

Xml代码  收藏代码
  1. https://github.com/gaol/jca-eis-listfiles  


RAR 

Xml代码  收藏代码
  1. https://github.com/gaol/jca-rar-listfiles  


Client 

Xml代码  收藏代码
  1. https://github.com/gaol/jca-client-listfileweb  


文中用到的工具 

Maven 

Maven 是项目管理的工具, 可以很方便的进行项目的编译,打包,测试。可以从以下网址找到下载连接。 

Xml代码  收藏代码
  1. http://maven.apache.org/    


笔者使用的 maven 版本是: 

Bash代码  收藏代码
  1. [lgao@lgao out]$ mvn -version  
  2. Apache Maven 3.0.2 (r1056850; 2011-01-09 08:58:10+0800)  
  3. Java version: 1.7.0, vendor: Oracle Corporation  
  4. Java home: /home/lgao/softwares/java/jdk1.7.0/jre  
  5. Default locale: en_US, platform encoding: UTF-8  
  6. OS name: "linux", version: "3.3.5-2.fc16.i686.pae", arch: "i386", family: "unix"  


IronJacamar 

IronJacamar 是 JBoss 的 JCA 1.6 实现,它提供了生成 JCA 代码的工具和 standalone 的环境用来测试,从以下地址下载 IronJacamar: 

Xml代码  收藏代码
  1. http://www.jboss.org/ironjacamar/downloads  


本文使用的IronJacamar版本为1.0.10.Final。 

JBoss AS 7 

我们在这个例子中使用JBoss AS 7做为应用服务器还有EIS的例子工具。下面是网址: 

Xml代码  收藏代码
  1. http://www.jboss.org/jbossas/downloads/  


笔者使用的 JBoss AS 7 版本是: 7.1.1.Final。 

参考资料 

JSR 322: JavaTM EE Connector Architecture 1.6 - http://jcp.org/en/jsr/detail?id=322 

IronJacamar 1.0 User's Guide - http://docs.jboss.org/ironjacamar/userguide/1.0/en-US/html_single/ 

IronJacamar 1.0 Developer's Guide - http://docs.jboss.org/ironjacamar/developerguide/1.0/en-US/html_single/

展开阅读全文

没有更多推荐了,返回首页