rubyonrails:搭上 WebSphere 快车 第 1 部分: 将 Ruby on Rails 和 WebSphere Application Server 结合使用

  引言

  由于采用 Java™ IBM WebSphere Application Server 环境具有出色可伸缩性、安全性和技术支持因此很多组织都将其作为标准配置不过使用 Java 开发动态网页经常非常单调乏味而且极为费时Ruby _disibledevent=>   JRUBY_HOME=C:\jruby-1.0.2

   PATH=%JAVA_HOME%\bin;%JRUBY_HOME%\bin;%PATH%

  JRuby 较早版本运行 IBM JDK 时存在问题

  Ruby 提供了个方便包管理工具称为 gem其功能和 Perl CPAN 类似向您 Rudy 安装添加库将非常有用而且可以使用这个思路方法安装 Rails 和 ActiveRecord-JDBC:

  清单 1

C:\>gem  rails -y --no-rdoc --no-ri 
Bulk updating Gem source index for: http://gems.rubyforge.org 
Successfully ed rails-1.2.5 
Successfully ed activesupport-1.4.4 
Successfully ed activerecord-1.15.5 
Successfully ed actionpack-1.13.5 
Successfully ed actionmailer-1.3.5 
Successfully ed actionwebservice-1.2.5 
 
C:\projects\wishlist\WEB-INF\gems\specications> 
gem  activerecord-jdbc-adapter --no-rdoc --no-ri 
Successfully ed activerecord-jdbc-adapter-0.6


  Rails 中包含 ActiveRecord可支持各种数据库但并不直接支持 JDBCActiveRecord-JDBC gem 提供了连接适配器使 ActiveRecord 看起来似乎直接支持 JDBCActiveRecord-JDBC 支持 IBM DB2®、MySQL、Oracle、Microsoft® SQL Server 和其他数据库但本文举例中使用是 Derby这主要是此数据库可免费使用而且可以方便地迁移到 DB2这在以后需要承担较为繁重任务时非常方便

  Ruby 和 Jruby:有什么区别?

  JRuby 是原始 Rudy 解释(最初使用 C 编写)纯 Java 实现其相对于 Rudy 主要优势似乎是您可以在 Java 代码和 Rudy 代码的间进行相互尽管这非常有用但并不是考虑使用 JRuby 替代 Ruby 原因

  Rudy 标准 C 实现使用绿色线程即某个用户长期运行进程可以阻塞所有其他用户假定某个用户请求信息量大报告需要分钟才能完成这将阻塞所有其他用户而其他用户可能只是尝试查看通常显示所需时间少于秒钟网页尽管这点可能在发布 Ruby 2.0 时发生变化但在这种情况下标准 Rudy 实现所有用户可能会被阻塞长达分钟等待这个用户长时间跨度请求完成

  对于 JRuby 并不会这样 JRudy 基于 Java 线程实现 Rudy 线程而 Java 线程使用是本机操作系统线程JRuby 几乎可以随时切换上下文因此在处理负载较重情况下在 JRudy 上运行 Rails 应用响应能力通常比使用标准 Ruby 实现时更好

  部署 Rails 项目

  您要进行个大步骤将是详细了解在 WebSphere Application Server 上部署包含 Rails 项目 WAR 基本步骤在此部分您将首先部署其中仅包含 Rails 欢迎页面空白 Rails 应用具体来说您将设置目录结构、将其打包为 WAR 文件然后将其部署到正在运行 WebSphere Application Server 上

  创建 Rails 项目

  通过 Rails 可以非常方便地设置项目基本目录结构运行 rails 命令以创建所有必要文件:

  清单 2

C:\>mkdir projects 
 
C:\>cd \projects 
 
C:\projects>jruby -S rails wishlist 
   create 
   create app/controllers 
   create app/helpers 
   create app/models 
   create app/views/layouts 
 <continued...>


  您可能注意到了在上面命令中并不是标准 Ruby rails而是 jruby -S rails-S 标志告知 JRuby 在 Jruby bin 目录中查找脚本否则将在用户当前目录中查找脚本

  安装 Goldspike

  Goldspike 是 Rails 插件提供充实构建系统所需任务和模板以便从新创建 Rails 项目创建 WAR 文件Rake 是 Ruby 构建工具用于自动执行类似于 shell 命令如打包和部署 Ruby 代码以及执行数据库迁移对于 Java 开发人员基本上可以将其视为和 Ant 等效工具;而对于 C/C 开发人员基本上可以将其视为和 make 等效工具它和 2者都相似不过 Rake 实际上是 Rudy 代码对于本文您只需要了解 Rake 用于创建构建系统即可

  运行清单 3 中所示命令以安装 Goldspike

  清单 3

C:\projects\wishlist>jruby script\plugin  
http://jruby-extras.rubyforge.org/svn/trunk/rails-egration/plugins/goldspike 
+ ./goldspike/README 
+ ./goldspike/Rakefile 
+ ./goldspike/generators/goldspike/goldspike_generator.rb 
+ ./goldspike/generators/goldspike/templates/war.rb 
+ ./goldspike/generators/goldspike/templates/web.xml.erb 
+ ./goldspike/init.rb 
+ ./goldspike/.rb 
+ ./goldspike/lib/create_war.rb 
+ ./goldspike/lib/java_library.rb 
+ ./goldspike/lib/packer.rb 
+ ./goldspike/lib/run.rb 
+ ./goldspike/lib/util.rb 
+ ./goldspike/lib/war_config.rb 
+ ./goldspike/tasks/war.rake 
+ ./goldspike/test/test_create_war.rb 
+ ./goldspike/test/test_java_library.rb 
+ ./goldspike/test/test_maven_library.rb 
+ ./goldspike/test/war_config_test_config.rb 
   exists config 
   create config/war.rb 
   create WEB-INF 
   create WEB-INF/web.xml.erb


  Goldspike 将在 source 树中创建两个新文件:

  config/war.rb:通过此文件可以限制将打包在 WAR 文件中 Jruby、Rails 和其他插件版本

  WEB-INF/web.xml.erb:这是 WAR 中最终生成 WEB-INF/web.xml 文件模板

  创建 lib\java 目录并将此目录用于存储在 JRudy 代码中将引用任何 JAR 文件lib\java 中 JAR 内任何类都将打包到 Goldspike 所创建 WAR 中这些新目录将在首次运行 Rake 任务来创建 WAR 时创建:

  WEB-INF/es:Rudy 代码所引用任何 Java 类都包含在此目录中

  WEB-INF/gems:Goldspike 将自动对安装到此目录中所有 gems 进行捆绑以便在 WebSphere Application Server 内提供

  不要在这里添加新 JAR;将自动从 lib\java 复制此类文件

  创建 WAR 文件

  为了确保基础结构正常工作请使用 JRuby 和 Goldspike 创建您个 WAR 文件:

  清单 4

C:\projects\wishlist>jruby -S rake war:standalone:create 
 (in C:/projects/wishlist) 
 info: Assembling web application 
 info: Packing needed Java libraries ... 
 info: Packing needed Ruby gems ... 
 info:  adding Ruby gem ActiveRecord-JDBC version 0.5 
 info: Packing needed files ... 
 info: Creating web archive


  新创建 WAR 文件大小应该略微大于 7 MB不要看到空 Rails 项目这么大而感到惊慌:Goldspike 还将 JRuby 和 Rails 打包到了 WAR 文件中(或者您可以让 Goldspike 通过 web.xml 将 JRudy 和 Rails 安装位置告知 WebSphere Application Server以避免将其包含在这些包中但这不在本文讨论范围的内)

  部署 WAR 文件

  要部署新 WAR:

  导航到 http://localhost:9060/admin打开 WebSphere 管理控制台

  在左侧导航菜单中展开 Applications 并单击 Install New Application

  单击 Browse以选择最近创建 WAR 文件:C:\projects\wishlist\wishlist.war(图 1)

  图 1. 准备应用安装



  将 Context root 设置为 wishlist然后单击 Next

  在 Deployment 向导中接受缺省设置并单击 Next直到进入步骤 4然后单击 Finish

  搜索所显示 Installing... 面板上消息确定没有报警和然后单击 Save

  在导航窗格中 Applications 下选择 Enterprise Applications

  选中 wishlist_war 旁边复选框然后单击 Start 按钮

  或者如果您计划在整个开发周期中进行重新部署则可以考虑设置个 Jython wsadmin 脚本尽管脚本详细信息不在本文讨论范围内但我在下面给出了个举例不过要注意只需要针对您环境修改 # Customize these: 注释的后 6行代码

  清单 5

import re 
import os 
 
# Customize these: 
WAR_FILE = "C:/projects/wishlist/wishlist.war" 
WAR_NAME = "wishlist_war" 
WAR_CONTEXT_ROOT = "/wishlist" 
SERVER_NAME = "server1"; 
NODE_NAME = "rshillington-ltNode01" 
CELL_NAME = "rshillington-ltNode01Cell" 
 
# No need to customize the rest. 
def log(text): 
  pr "---- " + text; 
 
appList = AdminApp.list 
log("Apps ed before un: \n" + appList + "\n\n") 
 
log("Find the appManager...") 
appManager = AdminControl.queryNames 
      ("cell=" + CELL_NAME + ",node=" + NODE_NAME + 
",type=ApplicationManager,process=" + SERVER_NAME + ",*") 
 
containsApp = re.compile("\\b" + WAR_NAME + "\\b", 0).search(appList) != None 
 
 containsApp: 
  log("Stop the application...") 
  try: 
    AdminControl.invoke(appManager, "stopApplication", WAR_NAME) 
  except: 
    # This is okay - it just wasn't started. 
    log("\tApplication not started."); 
 
  log("Un the application...") 
  AdminApp.un(WAR_NAME) 
 
  log("Save the changes...") 
  AdminConfig.save 
 
 
log("Install the application...") 
AdminApp.(WAR_FILE, "-appname " + WAR_NAME + " -server " + SERVER_NAME + 
" -contextroot " + WAR_CONTEXT_ROOT + " -usedefaultbindings") 
AdminConfig.save 
 
log("Start the application...") 
AdminControl.invoke(appManager, "startApplication", WAR_NAME) 
 
log("Save the changes..."); 
AdminConfig.save 
 
appList = AdminApp.list 
log("Apps ed after : \n" + appList + "\n\n")


  将脚本保存为 deployWishlist.py并使用 wsadmin 工具运行您应该看到和下面所示类似内容:

  清单 6

C:\WAS\bin>wsadmin.bat -f c:\moveit\deployWishlist.py 
-user admin -password <your password> 
WASX7209I: Connected to process "server1" on node rshillington-ltNode01 
using SOAP 
connector; The type of process is: UnManagedProcess 
---- Apps ed before un: 
DefaultApplication 
ivtApp 
 
 
---- Find the appManager... 
---- Install the application... 
WASX7327I: Contents of was.policy file: 
 // 
// Template policy file for enterprise application. 
// Extra permissions can be added  required by the enterprise application. 
// 
// NOTE: Syntax errors in the policy files will cause the enterprise 
//    application FAIL to start. Extreme care should be taken when  
//    editing these policy files. It is advised to use the policytool 
//    editing the policy files provided by the JDK for 
//    (WAS_HOME/java/jre/bin/policytool). 
 
grant codeBase "file:${application}" { 
}; 
 
grant codeBase "file:${jars}" { 
}; 
 
grant codeBase "file:${connectorComponent}" { 
}; 
 
grant codeBase "file:${webComponent}" { 
}; 
 
grant codeBase "file:${ejbComponent}" { 
}; 
 
 
ADMA5016I: Installation of wishlist_war started. 
ADMA5058I: Application and module versions are validated with versions 
of deployment targets. 
ADMA5062W: An error occurred while reusing the existing deployment.xml file. 
The original deployment tings are not reused." 
ADMA5005I: The application wishlist_war is configured in the WebSphere 
Application Server repository. 
ADMA5053I: The library references for the ed optional package 
are created. 
ADMA5005I: The application wishlist_war is configured in the WebSphere 
Application Server repository. 
ADMA5001I: The application binaries are saved in 
C:\WAS\profiles\AppSrv01\wstemp\Script116c5288827\workspace\cells\rshillington- 
ltNode01Cell\applications\wishlist_war.ear\wishlist_war.ear 
ADMA5005I: The application wishlist_war is configured in the WebSphere 
Application Server repository. 
SECJ0400I: Successfuly updated the application wishlist_war with the 
appContextIDForSecurity information. 
ADMA5011I: The cleanup of the temp directory for application wishlist_war 
is complete. 
ADMA5013I: Application wishlist_war ed successfully. 
---- Start the application... 
---- Save the changes... 
---- Apps ed after : 
DefaultApplication 
ivtApp 
wishlist_war


  现在将您浏览器指向 http://locahost:9080/wishlist您将看到和图 2 所示类似网页

  图 2. 应用欢迎页面



  图片看不清楚?请点击这里查看原图(大图)

  编写“愿望列表”应用

  接下来您将开发简洁生日愿望列表应用可以在其中输入想要礼物名称让其他人买来送给您:

  Rails 需要知道如何连接到数据库对于本文您将使用基于文件 Derby 数据库其具体路径以硬编码形式提供更改 config\database.yml以包含以下代码:

  清单 7

development: 
 adapter: jdbc 
 driver: org.apache.derby.jdbc.EmbeddedDriver 
 url: jdbc:derby:c:\projects\wishlist\db\wishlist_dev;create=true 
 
test: 
 adapter: jdbc 
 driver: org.apache.derby.jdbc.EmbeddedDriver 
 url: jdbc:derby:c:\projects\wishlist\db\wishlist_test;create=true 
 
production: 
 adapter: jdbc 
 driver: org.apache.derby.jdbc.EmbeddedDriver 
 url: jdbc:derby:c:\projects\wishlist\db\wishlist_prod;create=true 


  测试和生产部分和开发部分完全相同不过它们配置为在 URL 中使用数据库 wishlist_test 和 wishlist_prod而不是 wishlist_dev测试数据库将用于运行您测试以避免影响开发环境生产环境最好指向承载应用位置对于本文生产环境用于将应用部署到 WebSphere Application Server就目前而言数据库为空也无大碍Derby URL 上 create=true 标志告知 Derby如果目录和数据库不存在则进行创建

  为了识别 ActiveRecord JDBC请将清单 8 中 RUBY_PLATFORM 块中前 5个语句添加到 environment.rb 中 Rails::Initializer.run 块的前位置从而加载 activerecord-jdbc-adapter gem config\environment.rb 将和以下所示类似:

  清单 8

# Be sure to restart your web server when you mody this file. 
 
# Uncomment below to force Rails o production mode when 
# you don't control web/app server and can't  it the proper way 
# ENV['RAILS_ENV'] ||= 'production' 
 
# Species gem version of Rails to use when vendor/rails is not present 
RAILS_GEM_VERSION = '1.2.5' unless d? RAILS_GEM_VERSION 
 
# Bootstrap the Rails environment, frameworks, and default configuration 
require File.join(File.dirname(__FILE__), 'boot') 
 
 RUBY_PLATFORM =~ /java/ 
  require 'rubygems' 
  gem 'activerecord-jdbc-adapter' 
  require 'jdbc_adapter' 
end 
 
Rails::Initializer.run do |config| 
 # Settings in config/environments/* take precedence over those specied here 
...


  要在 JRuby 类路径和 WAR 中包括 Derby JDBC JAR请将其添加到系统 CLASSPATH 中要将其包括到 WAR 中请将 derby.jar 复制到 lib\java 中

  清单 9

C:\projects\wishlist>cd lib\java 
 
C:\projects\wishlist\lib\java>copy C:\WAS\derby\lib\derby.jar derby-10.1.3.jar 
    1 file(s) copied. 
 
C:\projects\wishlist\lib\java> CLASSPATH=C:\projects\wishlist\lib\java\ 
derby-10.1.3.jar


  请特别注意所添加版本号Goldspike 仅仅识别 Maven 样式依赖关系因此不能识别没有版本号 JAR 文件不过Goldspike 并不会扫描 lib\java 目录并选取其中所有 JAR 文件因此您需要将 config\war.rb 修改为和以下所示类似样子:

  清单 10

# Goldspike configuration 
 
# Set the version of JRuby and GoldSpike to use: 
maven_library 'org.jruby', 'jruby-complete', '1.0.2' 
 
# Add the Derby library to the WAR 
_library 'derby', '10.1.3'; 
 
# Add the ActiveDirectory-JDBC adapter to the WAR 
add_gem 'activerecord-jdbc-adapter', '0.6'; 
 
# Uncomment this to have the war run in the rails 'development' environment 
(against wishlist_dev) when run in WebSphere 
#@result.rails_env= 'development';


  Goldspike 允许有系列很大程度上未公开选项可以在 vendor\plugins\goldspike\lib\war_config.rb 中找到这些选项例如要更改所生成 WAR 文件路径和名称请将以下代码行添加到 config/war.rb 结束位置:

  清单 11

@result.war_file= 'c:/temp/funnyName.war';

  运行 Rails 生成脚本以创建“愿望列表”编辑器代码Rails 提示问题时请回答 Y(代表是)

  清单 12

C:\projects\wishlist>jruby script\generate controller Editor 
   exists app/controllers/ 
   exists app/helpers/ 
   create app/views/editor 
   create test/functional/ 
   create app/controllers/editor_controller.rb 
   create test/functional/editor_controller_test.rb 
   create app/helpers/editor_helper.rb 
 
C:\projects\wishlist>jruby script\generate model Wish 
   exists app/models/ 
   exists test/unit/ 
   exists test/fixtures/ 
   create app/models/wish.rb 
   create test/unit/wish_test.rb 
   create test/fixtures/wishes.yml 
   exists db/migrate 
   create db/migrate/001_create_wishes.rb 
 
C:\projects\wishlist>jruby script\generate scaffold Wish Editor 
   exists app/controllers/ 
   exists app/helpers/ 
   exists app/views/editor 
   exists app/views/layouts/ 
   exists test/functional/ 
 dependency model 
   exists  app/models/ 
   exists  test/unit/ 
   exists  test/fixtures/ 
  identical  app/models/wish.rb 
  identical  test/unit/wish_test.rb 
  identical  test/fixtures/wishes.yml 
   create app/views/editor/_form.rhtml 
   create app/views/editor/list.rhtml 
   create app/views/editor/show.rhtml 
   create app/views/editor/.rhtml 
   create app/views/editor/edit.rhtml 
overwrite app/controllers/editor_controller.rb? [Ynaqd] 
    force app/controllers/editor_controller.rb 
overwrite test/functional/editor_controller_test.rb? [Ynaqd] 
    force test/functional/editor_controller_test.rb 
  identical app/helpers/editor_helper.rb 
   create app/views/layouts/editor.rhtml 
   create public/stylesheets/scaffold.css


Tags:  rubyonrails安装 rubyonrails实例 rubyonrails教程 rubyonrails

延伸阅读

最新评论

发表评论