Ruby から JasperReports でPDF帳票を出す(PDF出力処理をサーバ化)
Railsをpassengerで動かしている時に、RJBでJavaのライブラリJasperReportsを呼び出そうとすると
うまくいかなかった。
なので、一つの解決法としてJasperReportsの呼び出し部分をRailsとは切り離す仕組みとしてDRubyを採用する。
サンプルは別途リンクを張りますが、ここでは主要なソースのみ書き出します。
まずは、実際にPDFを作成する部分から
gen/WritePdf.java:
package gendosu; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.sql.Connection; import java.sql.DriverManager; import java.util.HashMap; import java.util.List; import net.sf.jasperreports.engine.JRException; import net.sf.jasperreports.engine.JRPrintPage; import net.sf.jasperreports.engine.JasperExportManager; import net.sf.jasperreports.engine.JasperFillManager; import net.sf.jasperreports.engine.JasperPrint; import net.sf.jasperreports.engine.JasperRunManager; import net.sf.jasperreports.engine.util.JRLoader; public class WritePdf { private String _hostName = "localhost"; private String _databaseName = "jasper_report_on_rails_development"; private String _userName = "root"; private String _password = "root"; public WritePdf(String hostName, String databaseName, String userName, String password) { _hostName = hostName; _databaseName = databaseName; _userName = userName; _password = password; } public void runTest(String jasperName, String jasperName2, String pdfName, HashMap paramMap){ Connection con = null; try { con = getConnection(); List pages = null; OutputStream outstream = null; // メインになる帳票を取得 JasperPrint jasperPrint = JasperFillManager.fillReport(jasperName, paramMap, con); // 追加する帳票を取得 JasperPrint jasperPrint2 = JasperFillManager.fillReport(jasperName2, paramMap, con); // 追加する帳票をメイン帳票に追加 pages = jasperPrint2.getPages(); for(JRPrintPage page : pages ){ jasperPrint.addPage(page); } // 帳票をPDFファイルに出力 JasperExportManager.exportReportToPdfFile(jasperPrint, pdfName); } catch (JRException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } finally { closeConnection(con); } } private Connection getConnection(){ Connection con = null; try { Class.forName("com.mysql.jdbc.Driver"); String jdbcValue = String.format("jdbc:mysql://%s/%s", _hostName, _databaseName); con = DriverManager.getConnection(jdbcValue, _userName, _password); } catch (Exception e) { e.printStackTrace(); } return con; } private void closeConnection(Connection con){ try { con.close(); } catch (Exception e) { } } }
このJavaのメソッド「runTest」をrubyから呼び出します。
つづいて、この「runTest」を呼び出すrubyソース
create_pdf.rb:
require 'rubygems' require 'drb/drb' require 'rjb' require 'erb' require 'yaml' CURRENT_PATH = File.dirname(File.expand_path(__FILE__)) classpaths = Dir.glob( File.join(CURRENT_PATH, 'java/lib/*.jar')) classpaths.concat(Dir.glob(File.join(CURRENT_PATH, 'java/dist/*.jar'))) Rjb::load(classpath = classpaths.join(':'), jvmargs=[]) HashMap = Rjb::import("java.util.HashMap") FileInputStream = Rjb::import('java.io.FileInputStream') FileOutputStream = Rjb::import('java.io.FileOutputStream') WritePdf = Rjb::import('gendosu.WritePdf') class CreatePdf def initialize(stream=$stdout) @stream = stream @database = YAML::load(ERB.new(IO.read(File.join(CURRENT_PATH, 'config/database.yml'))).result) end def run_test(pdfName, outputDate, print_record_id) jasperName = File.join(CURRENT_PATH, 'java/reports/report1.jasper') jasperName2 = File.join(CURRENT_PATH, 'java/reports/report1.jasper') @write_pdf = WritePdf.new(@database[@stream]['host'], @database[@stream]['database'], @database[@stream]['username'], @database[@stream]['password']) hash_map = HashMap.new hash_map.put("OUTPUT_DATE", outputDate); hash_map.put("PRINT_RECORD_ID", print_record_id); @write_pdf.runTest(jasperName, jasperName2, pdfName, hash_map) end end @port = YAML::load(ERB.new(IO.read(File.join(CURRENT_PATH, 'config/pdf_server.yml'))).result) rails_env = ARGV.shift uri = "druby://localhost:#{@port[rails_env]['port']}" DRb.start_service(uri, CreatePdf.new(rails_env)) puts DRb.uri sleep
これで、RubyからRJBを使ってJavaのインスタンスを起動し、JasperReportsでPDF出力することが出来ます。
ここまでの修正で、実行テストは
create_pdf_client.rb:
require 'drb' pdfName = 'test.pdf' there = DRbObject.new_with_uri("druby://localhost:8787") there.run_test(pdfName, "TEST", 1)
とし、このcreate_pdf_client.rbファイルを実行すると、PDFファイルが作成されます。