`
wuhuizhong
  • 浏览: 693886 次
  • 性别: Icon_minigender_1
  • 来自: 中山
社区版块
存档分类
最新评论

How to Integrate JasperReports with Ruby on Rails

    博客分类:
  • ROR
阅读更多

Introduction

JasperReports is a powerful—and even more important—well known open source Java reporting tool that has the ability to deliver rich content in formats such as PDF, RTF, HTML, CSV and XML. It is widely used and appreciated in the Java community because of its flexibility and the availability of various GUI tools for rapid report design.

The following paragraphs explain how to interface Rails and JasperReports.

Interface

JasperReports is no more than a Java library that offers the ability to fill previously designed and compiled reports with some data and to save these reports in a specified file format. Valid data sources are JDBC connecti***** and XML files (using JRXmlDatasource), amongst others. Reading the data for the report from a database using raw SQL commands is of course possible but introduces duplicate logic, database vendor-specific code and concurrency issues. Besides that, there is no elegant way of reporting data that is not stored in a database but managed in Rails. There are no such problems if we use the XML data source and generate XML data in Rails using Builder templates—which is extremely easy and comfortable. For these reas*****, the XML data source is used for feeding Rails data into JasperReports.

JasperReports is integrated into Rails by execution of a simple Java application that receives the XML data for the reports through an IO pipe, creates the report and passes the results back trough the pipe right into the Rails application. The whole interface c*****ists of the following parts:

  • JasperReports library
  • Java interface application that takes XML data and produces reports
  • Shell script to invoke the Java application
  • Rails code that builds an appropriate CLASSPATH, executes the Java interface application, and reads/writes through an IO pipe
  • Rails code that generates the XML data (using Builder templates)
  • Some rails code that sends the generated report to the browser or stores it somewhere

This might seem like a lot of work but actually it is not. At least, if you don’t have to write all the code yourself ;).

Code

I added a directory jasper to my rails application root. It contains three subfolders

  • bin – the Java class file of the interface application
  • src – the Java source file of the interface application
  • lib – the JasperReports library and every 3rd-party library that is needed

Apart from that, I added a reports directory to the rails application root that contains the precompiled Jasper reports.

The rails code that builds the CLASSPATH, executes the Java app and handles the IO pipe looks like the following:

# document.rb fAs:[  
class Document b�Y>Ug{O;  
  include Config 6]Jv3Re'(I  
  def self.generate_report(xml_data, report_design, output_type, select_criteria) 	CqoL5qt	  
    report_design << '.jasper' if !report_design.match(/\.jasper$/) C$bK!]a  
    interface_classpath=Dir.getwd+"/jasper/bin"  Z|W=.RdA;  
    case CONFIG['host'] *%O1d.,  
      when /mswin32/ r
(uM$R$o  
        Dir.foreach("jasper/lib") do |file| B$bsh.  
          interface_classpath << ";#{Dir.getwd}/jasper/lib/"+file if (file != '.' and file != '..' and file.match(/.jar/)) !rWib`%  
        end d
>%_<pw  
      else 1Jahu!c?  
        Dir.foreach("jasper/lib") do |file| 2d._X$fx7  
          interface_classpath << ":#{Dir.getwd}/jasper/lib/"+file if (file != '.' and file != '..' and file.match(/.jar/)) sJr$[?  
        end {b?)|@)is  
    end 
@.})nU  
    pipe = IO.popen "java -cp \"#{interface_classpath}\" XmlJasperInterface -o#{output_type} -freports/#{report_design} -x#{select_criteria}", "w+b"  eN$~@'w  
    pipe.write xml_data gFKQm(0g2  
    pipe.close_write y?rsfIth`  
    result = pipe.read yR`-rJb V  
    pipe.close l-	X|3�,  
    result u&qdrKx  
  end _uBf.Qfs  
end

As you can see from this code, there is no need to call any Windows batch file or Bash script. It has not been thoroughly tested but works in Windows and Linux (check that ‘java’ binary path though). Three parameters are passed to XmlJasperInterface:

  • -o the report output type (supported types are pdf, rtf, xml, xls and csv; even though I only really tested pdf and rtf)
  • -f the path and filename of the precompiled report
  • -x an XML select path (refer to Using the XML datasource for further information)

The data returned by generate_report is the final report that can be passed to a browser for example. Include the following module in every controller that needs to create and send reports:

require "document.rb"  #NqA5QR  
  PXkPC%j  
module SendDoc D1w_Vpz  
  protected $]Q_x?  
  def cache_hack 
&pCKz[Yf+  
    if @request.env['HTTP_USER_AGENT'] =~ /msie/i q%JV"9,  
      @headers['Pragma'] = '' toQn]MT  
      @headers['Cache-Control'] = '' ZFRKh:|  
    else 5'o.v^l  
      @headers['Pragma'] = 'no-cache' ^)
SvH		  
      @headers['Cache-Control'] = 'no-cache, must-revalidate' pZH
bj2~  
    end R	~cc]kp0  
  end N+r~\[N\9  
  
wHAh6lm  
  def send_doc(xml, xml_start_path, report, filename, output_type = 'pdf') _-D(N/  
    case output_type -<|Ebh	d3  
    when 'rtf' rf9RG!  
      extension = 'rtf' bk8IGhO|m!  
      mime_type = 'application/rtf' `dj/Uk  
      jasper_type = 'rtf' sG\=_-"v(  
    else # pdf s#d>yx_b  
      extension = 'pdf' ~zuMX;[  
      mime_type = 'application/pdf' MHgS5b2  
      jasper_type = 'pdf' 0AaN	  
    end $mpfr#!&3o  
  [%b<%m}L-  
    cache_hack wPV`j:?'  
    send_data Document.generate_report(xml, report, jasper_type, xml_start_path), 
D$j`+`  
        :filename => "#{filename}.#{extension}", :type => mime_type, :disposition => 'inline' Q,s,EooIx  
  end :
\.v\.wm  
end

The controller code could be as follows:

class ReportController < ApplicationController $+
?6U  
  include SendDoc ntj
Und&v\  
  zis-}K<  
  def report <q_H 3|  
    @course = Course.find(params[:id]) @m(\f  
    @user = User.find(session[:user_id]) |ejrE,~1vb  
    send_doc(render_to_string(:template => 'xml_course_report', :layout => false), YrB-;R1+  
      '/Courses', 'course_report', "course#{@course.id}", 'pdf') ~kYF/B2*  
  end U;;Har  
  6_9w1
,WE  
end

In the above code we render the Builder template xml_course_report into a string and pass this string to the send_doc method. course_report is the filename of the precompiled report and course#{@course.id} is the filename of the PDF document that gets sent to the browser. The extension .pdf is added automatically in send_doc.

The Builder template could look as follows:

xml.instruct! S?D2`b  
xml.Course do 8y+Gvk:  
  xml.MetaInformation do t[3Upe%  
    xml.GeneratedAt(Time.now) {VI%]n{M  
    xml.GeneratedBy do 
I2zSoQ1P  
      xml.Name(@user.name) :S,#*rPKBK  
      xml.UserName(@user.user_name) ^ 41p+  
      xml.Email(@user.email) gAR];(*  
    end n)pBK>+  
  end RPLr7Lb  
  xml.Information do xv1$,|^ts  
    xml.Name(@course.name) `UeF3~)>E  
    xml.Participants do !WDdq_n*v  
      @course.participants.each do |p| {\	.2h  
        xml.Participant do 4u:{PN  
          xml.Name(p.name) 
GZO,]%z  
          xml.Phone(p.phone) #Xsby  
          xml.City(:zip => p.city.zip, :name => p.city.name) p|W:;(  
        end NbgP,-  
      end 7O"T`>  
    end S$V'_  
  end @Wdnc/o]  
end

Voilà, that’s it.

Performance Issues

JasperReports itself is very fast, but bringing up a Java Virtual Machine for each call of generate_doc takes its time (about 2 seconds on my machine). It would be much faster, if the Java interface application would run as a server application all the time and listening on a specific TCP port for incoming report generation requests. Then, the performance issue would be gone. I haven’t found the time to implement a JasperReport server yet. But, if somebody does, please let me know!

I think an option for better performance would be to use Apache Cocoon and call this pages from ruby. This way one could either use Apache FOP and XML/XSLT to generate PDF pages or integrate JasperReports or Eclipse BIRT into Cocoon. When Cocoon is then executed as Tomcat-Webapp the startuptime is nearly null. (markusw@nmmn.com)

What is quite interesting concerning the usage of JasperReports ist Jasper Intelligence, from http://jasperintel.sourceforge.net. They provide JasperReports as a Webservice.

RE:JasperReports as a Webservice. Although their website advertises support for PHP, Python and other scripting languages, this is not entirely true. Scouring through the Net as well as JasperSoft’s documentation does not yield any useful information about the server’s Web Service API. A quick look at their forums reveals that this isn’t fully implemented yet. A workaround to this would probably be to use WWW::Mechanize to get those document formats from the JasperServer. —relaxdiego

Download

You can download the Java interface application, the shell script as well as the required 3rd-party libraries (including XmlJasperInterface.class) bundled here.

Discussion

Jeff Dean, 2009/06/24 21:27

Comment pulled from doc: “Including the JasperReport source file for this sample data would make this much easier to understand.”

 
Jmini, 2009/08/06 08:18

The mentioned Jasper Intelligence project is integrated to JasperServer (http://jasperforge.org/projects/jasperserver or http://jasperforge.org/projects/jasperserver)

A JasperServer running on Tomcat (for example) is able to serve compiled report through SOAP queries. This enable you to integrate JasperReport in “PHP, Python and other scripting languages”.

Example of PHP integration is provided in the JasperServer distribution in the samples/ directory http://jasperforge.org/scm/viewvc.php/branches/js-3.5.0/samples/php-sample/?root=jasperserver Or for newer PHP version attached to this ticket: http://jasperforge.org/plugins/mantis/view.php?id=4038

I have seen people using the same approach with Ruby. (browse the forum, I think there is also an example somewhere)

Documentation for this SOAP request can be found here: http://jasperforge.org/espdocs/docsbrowse.php?id=74&type=docs&group_id=112&fid=305

分享到:
评论

相关推荐

    How to integrate BIEE with Oracle SSO Portal.doc

    【整合BIEE与Oracle SSO门户的详细步骤】 在企业级IT环境中,实现单点登录(SSO)是提高用户便利性和系统安全性的重要手段。本文档将详细讲解如何将Oracle Business Intelligence Enterprise Edition(BIEE)与...

    flex on rails

    The title "Flex on Rails" suggests an in-depth exploration of integrating Adobe Flex with Ruby on Rails (RoR), focusing specifically on Flex 3 and Rails 2. This integration allows for the creation of ...

    Hello! Flex 4

    He is the co-creator of the Ruboss Framework, the RESTful way to develop Flex and AIR applications that easily integrate with Ruby on Rails. Peter is also the author of the Manning book Flexible ...

    How to Integrate E2E in MICROSAR

    ### 如何在MICROSAR中集成End-to-End保护 #### 概述 本文档旨在指导用户如何在VECTOR AUTOSAR软件MICROSAR中集成End-to-End (E2E)保护功能。E2E保护是一项重要的安全措施,用于确保在汽车电子控制单元(ECU)之间的...

    Learning Redux

    The book starts with a short introduction to the principles and the ecosystem of Redux, then moves on to show how to implement the basic elements of Redux and put them together. Afterward, you are ...

    [Kendo UI] 移动应用开发 Kendo UI Mobile 实现 英文版

    Get started with Kendo UI Mobile and learn how to integrate it with HTTP based services built using ASP NET Web API Overview Learn the basics of developing mobile applications using ...

    Hands-On Cybersecurity for Architects

    You will then move on to learning how to plan and design robust security architectures, along with practical approaches to performing various security assessments. Once you have grasped all this, you...

    Integrate_E2E_in_MICROSAR.pdf

    《集成E2E在MICROSAR中的技术参考》 本文档详细介绍了如何在基于AUTOAR 4.2的MICROSAR环境中实现端到端(E2E)保护,主要涉及两种方案:E2E Protection Wrapper(E2E保护包装器)和E2E Transformer(E2E转换器)。...

    Big Data Analytics with Hadoop 3 1st Edition

    You will then move on to learning how to integrate Hadoop with the open source tools, such as Python and R, to analyze and visualize data and perform statistical computing on big data. As you get ...

    Packt.Hands-On.Spring.Security.5.for.Reactive.Applications

    You will then learn about a variety of authentication mechanisms and how to integrate them easily with the Spring MVC application. You will also understand how to achieve authorization in a Spring ...

    Compile to integrate with whatsap, receive and send direct msg

    Compile to integrate with whatsap, receive and send direct msg in your application delphi fully full component. see the video below for you to see how the component works ...

    How to ISAPI_Hikvision_HikvisionISAPI_

    How to integrate with Hikvision LPR function via ISAPI

    Big Data Analytics with Hadoop 3

    You will then move on to learning how to integrate Hadoop with the open source tools, such as Python and R, to analyze and visualize data and perform statistical computing on big data. As you get ...

    Django By Example(PACKT,2015)

    Django is a powerful ...After reading this book, you will have a good understanding of how Django works and how to integrate it with other technologies to build practical, advanced, web applications.

    Packt.Learning.Apache.Kafka.2nd.Edition

    how to integrate Kafka with Camus, Apache Camel, Amazon Cloud, and so on.Chapter 6, Kafka Integrations, provides a short introduction to both Storm and Hadoop and discusses how Kafka integration works...

    Web Development with Django Cookbook (2nd)

    You will also learn how to integrate your own functionality in Django CMS. The next step will be to learn how to use hierarchical structures. You will find out that collecting data from different ...

    ActiveMQ in Action

    HIGHLIGHT ActiveMQ in Action is an example-rich tutorial that shows Java developers how to implement distributed messaging using ActiveMQ, and how to integrate ActiveMQ with Java and non-Java ...

Global site tag (gtag.js) - Google Analytics