Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Accepting java parameters on controllers without conversion to java.lang.String #13

Merged
merged 1 commit into from over 1 year ago

4 participants

Gregório Chalinski Kusowski Marlus Saraiva Diego Plentz David JOULIN
Gregório Chalinski Kusowski

By checking the parent of each instance variable class on the controller, we can
be sure if it's a Rjb::Rjb_JavaClass or Rjb::Rjb_JavaProxy instance.
Example cases like Rjb::Java_lang_String or Rjb::Java_util_HashMap will also be
as they are.
I'm not sure if we can receive a Rjb::Rjb_JavaBridge, but it will work too.

The example present on the specs shows how java parameters can be used.

    title = (Rjb::import 'java.lang.String').new("The Beatles")
    @parameter_that_is_a_java_class = (Rjb::import 'java.util.HashMap').new
    @parameter_that_is_a_java_class.put("title", title)
<parameter name="parameter_that_is_a_java_class" class="java.util.Map"/>
...
<textFieldExpression><![CDATA[$P{parameter_that_is_a_java_class}.get("title")]]></textFieldExpression>

I chose to not convert every Hash to a java.util.HashMap because it can grow up easily if we use a recursive approach. I'll add later a snippet to the wiki or readme with a simple conversion tool.
Improvements and suggestions will be appreciated.

Gregório Chalinski Kusowski gregoriokusowski Accepting java parameters on controllers without conversion to java.l…
…ang.String.

By checking the parent of each instance variable class on the controller, we can
be sure if it's a Rjb::Rjb_JavaClass or Rjb::Rjb_JavaProxy instance.
Example cases like Rjb::Java_lang_String or Rjb::Java_util_HashMap will also be
as they are.
I'm not sure if we can receive a Rjb::Rjb_JavaBridge, but it will work too.
c7896d8
Marlus Saraiva msaraiva merged commit acd4161 into from
Marlus Saraiva
Owner

This solves issue #12.

Thanks Kusowski!

Diego Plentz

I was talking with @gregoriokusowski earlier today and we discussed that this isn't really the best solution for the user. we thought in iterating over all controller's instance variables(ignoring those with @_ since it's used by rails[1] - something like what is done here), and checking class types - if it's an array or an hash, we convert to java's corresponding type, everything else is passed as a string(as it's done today). that way, the user will be able to use

@my_hash = {baz: "zinga!"}
@my_array = ["A","B","C", "easy as", 1, 2, 3, "or simple as", "do re mi"]

which we think is way better then the solution explained in the initial post. what you guys think? cc @msaraiva @rodrigomaia

[1]

1.9.3p327 :002 > x = FooController.new
1.9.3p327 :003 > x.instance_variables
 => [:@_routes, :@_action_has_layout, :@_headers, :@_status, :@_request, :@_response]
Marlus Saraiva
Owner

I don't like the idea of having any Java related code in the controllers. I will probably not use it. But the feature itself is nice. Whatever solution we find to convert the data from ruby to java must face the problem of recursion and custom types. So I agree we should have a solution that convert arrays and hashes automatically (we just need to define how deep in the structure). That will cover the 95% of all the use. However, we can keep the current solution in case the user find himself among the other 5%.
It sounds reasonable. Right?

Diego Plentz

@msaraiva 100% agree. So we try to do our best converting ruby objects to java and if we can't the user still have the workaround.

About the deepness, any suggestion? I can't imagine a case where we can't go all the way in all the levels that the object have, since we're going to do it just in the current controller instance variables. Am I right?

David JOULIN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 1 unique commit by 1 author.

Nov 20, 2012
Gregório Chalinski Kusowski gregoriokusowski Accepting java parameters on controllers without conversion to java.l…
…ang.String.

By checking the parent of each instance variable class on the controller, we can
be sure if it's a Rjb::Rjb_JavaClass or Rjb::Rjb_JavaProxy instance.
Example cases like Rjb::Java_lang_String or Rjb::Java_util_HashMap will also be
as they are.
I'm not sure if we can receive a Rjb::Rjb_JavaBridge, but it will work too.
c7896d8
This page is out of date. Refresh to see the latest.
18 README.md
Source Rendered
@@ -46,9 +46,9 @@ Note: This list will become your datasource inside the report.
46 46
47 47 2) Create your jasper report source file using iReport or any compatible jasper tool.
48 48
49   -3) Set the "Query Text" and "The language for the dataset query" properties of your report.
  49 +3) Set the "Query Text" and "The language for the dataset query" properties of your report.
50 50
51   -Note: If you're using iReport, you can find those properties in the "Properties panel".
  51 +Note: If you're using iReport, you can find those properties in the "Properties panel".
52 52 Don't forget to select the report root node in your "Report inspector".
53 53
54 54 Example: If you have a list of people, you should have something like:
@@ -60,7 +60,7 @@ Example: If you have a list of people, you should have something like:
60 60 5) Save the report source file in your views folder (just like any other html view file):
61 61
62 62 Example:
63   -
  63 +
64 64 * app/views/people/index.jrxml
65 65
66 66 ## Parameters
@@ -78,7 +78,7 @@ Example:
78 78
79 79 All you have to do now is to create, in iReport, a parameter called "user" (yes, without the "@") and drop it in your report!
80 80
81   -Limitation: By now, all parameters are converted to java String. We intend to change this in the near future.
  81 +Limitation: By now, all parameters that aren't manually converted to Rjb java classes/instances are converted to java String. We intend to change this in the near future.
82 82
83 83 ## RSpec integration
84 84 Check out: [jasper-rails-rspec](http://github.com/fortesinformatica/jasper-rails-rspec).
@@ -88,14 +88,14 @@ For a running example, just clone: [jasper-rails-demo](http://github.com/fortesi
88 88
89 89 ## History
90 90 This project was first developed at Grupo Fortes in 2011 and we have been using it in several projects since then.
91   -Pay attention that all the features it supports right now were based in those project's especific needs. Therefore you might find a lot of
92   -JasperResports' features that are not yet supported.
93   -
  91 +Pay attention that all the features it supports right now were based in those project's especific needs. Therefore you might find a lot of
  92 +JasperResports' features that are not yet supported.
  93 +
94 94 ## LICENSE
95 95
96 96 Copyright (C) 2012 Marlus Saraiva, Rodrigo Maia
97 97
98   -Permission is hereby granted, free of charge, to any person obtaining
  98 +Permission is hereby granted, free of charge, to any person obtaining
99 99 a copy of this software and associated documentation files (the
100 100 "Software"), to deal in the Software without restriction, including
101 101 without limitation the rights to use, copy, modify, merge, publish,
@@ -108,7 +108,7 @@ included in all copies or substantial portions of the Software.
108 108
109 109 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
110 110 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
111   -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  111 +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
112 112 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
113 113 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
114 114 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
46 lib/jasper-rails.rb
... ... @@ -1,20 +1,20 @@
1   -#
  1 +#
2 2 # Copyright (C) 2012 Marlus Saraiva, Rodrigo Maia
3   -#
4   -# Permission is hereby granted, free of charge, to any person obtaining
  3 +#
  4 +# Permission is hereby granted, free of charge, to any person obtaining
5 5 # a copy of this software and associated documentation files (the
6 6 # "Software"), to deal in the Software without restriction, including
7 7 # without limitation the rights to use, copy, modify, merge, publish,
8 8 # distribute, sublicense, and/or sell copies of the Software, and to
9 9 # permit persons to whom the Software is furnished to do so, subject to
10 10 # the following conditions:
11   -#
  11 +#
12 12 # The above copyright notice and this permission notice shall be
13 13 # included in all copies or substantial portions of the Software.
14   -#
  14 +#
15 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 16 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17   -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17 +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 19 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 20 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
@@ -30,7 +30,7 @@
30 30 end
31 31
32 32 module JasperRails
33   -
  33 +
34 34 class << self
35 35 attr_accessor :config
36 36 end
@@ -39,7 +39,7 @@ class << self
39 39 Dir["#{File.dirname(__FILE__)}/java/*.jar"].each do |jar|
40 40 classpath << File::PATH_SEPARATOR + File.expand_path(jar)
41 41 end
42   -
  42 +
43 43 Dir["lib/*.jar"].each do |jar|
44 44 classpath << File::PATH_SEPARATOR + File.expand_path(jar)
45 45 end
@@ -67,14 +67,13 @@ class << self
67 67 self.config = {
68 68 :report_params=>{
69 69 "REPORT_LOCALE" => Locale.new('en', 'US'),
70   - "XML_LOCALE" => Locale.new('en', 'US'),
  70 + "XML_LOCALE" => Locale.new('en', 'US'),
71 71 "XML_DATE_PATTERN" => 'yyy-MM-dd'
72 72 }
73 73 }
74   -
  74 +
75 75 module Jasper
76 76 module Rails
77   -
78 77 def self.render_pdf(jasper_file, datasource, parameters, options)
79 78 options ||= {}
80 79 parameters ||= {}
@@ -86,11 +85,12 @@ def self.render_pdf(jasper_file, datasource, parameters, options)
86 85 JasperRails.config[:report_params].each do |k,v|
87 86 jasper_params.put(k, v)
88 87 end
89   -
90   - # Convert the ruby parameters' hash to a java HashMap.\
91   - # Pay attention that, for now, all parameters are converted to string!
92   - parameters.each do |k,v|
93   - jasper_params.put(JavaString.new(k.to_s), JavaString.new(v.to_s))
  88 +
  89 + # Convert the ruby parameters' hash to a java HashMap, but keeps it as
  90 + # default when they already represent a JRB entity.
  91 + # Pay attention that, for now, all other parameters are converted to string!
  92 + parameters.each do |key, value|
  93 + jasper_params.put(JavaString.new(key.to_s), parameter_value_of(value))
94 94 end
95 95
96 96 # Compile it, if needed
@@ -106,7 +106,7 @@ def self.render_pdf(jasper_file, datasource, parameters, options)
106 106 # This is here to avoid the "already initialized constant DOCUMENT_POSITION_*" warnings.
107 107 JRXmlUtils._invoke('parse', 'Lorg.xml.sax.InputSource;', input_source)
108 108 end
109   -
  109 +
110 110 jasper_params.put(JRXPathQueryExecuterFactory.PARAMETER_XML_DATA_DOCUMENT, data_document)
111 111 jasper_print = JasperFillManager.fillReport(jasper_file, jasper_params)
112 112 else
@@ -125,6 +125,18 @@ def self.render_pdf(jasper_file, datasource, parameters, options)
125 125 raise e
126 126 end
127 127 end
  128 +
  129 + # Returns the value without conversion when it's converted to Java Types.
  130 + # When isn't a Rjb class, returns a Java String of it.
  131 + def self.parameter_value_of(param)
  132 + # Using Rjb::import('java.util.HashMap').new, it returns an instance of
  133 + # Rjb::Rjb_JavaProxy, so the Rjb_JavaProxy parent is the Rjb module itself.
  134 + if param.class.parent == Rjb
  135 + param
  136 + else
  137 + JavaString.new(param.to_s)
  138 + end
  139 + end
128 140 end
129 141 end
130 142
60 spec/controllers/people_controller_spec.rb
... ... @@ -1,79 +1,89 @@
1 1 require 'spec_helper'
2 2
3 3 describe PeopleController do
4   -
  4 +
5 5 describe "GET index" do
6 6 before do
7 7 Person.stub(:all).and_return([
8   - Person.new(:name=>'john' , :email=>'lennon@beatles.com'),
  8 + Person.new(:name=>'john' , :email=>'lennon@beatles.com'),
9 9 Person.new(:name=>'george', :email=>'harrison@beatles.com')
10 10 ])
11 11 end
12   -
  12 +
13 13 it "should respond success" do
14 14 get :index, :format => :pdf
15   -
  15 +
16 16 response.should be_success
17 17 end
18   -
  18 +
19 19 it "should not contain nulls" do
20 20 get :index, :format => :pdf
21   -
  21 +
22 22 response.should_not contain("null")
23 23 end
24 24
25 25 it "should show all fields in the report" do
26 26 get :index, :format => :pdf
27   -
  27 +
28 28 response.should contain("john")
29 29 response.should contain("lennon@beatles.com")
30 30 response.should contain("george")
31 31 response.should contain("harrison@beatles.com")
32 32 end
33   -
  33 +
34 34 it "should clip the text if it's larger than the Text Field" do
35 35 Person.stub(:all).and_return([
36   - Person.new(:name=>'jonh' , :email=>'a_very_long_text_that_is_larger_than_the_text_field_in_the_report')
  36 + Person.new(:name=>'jonh' , :email=>'a_very_long_text_that_is_larger_than_the_text_field_in_the_report')
37 37 ])
38   -
  38 +
39 39 get :index, :format => :pdf
40   -
  40 +
41 41 response.should_not contain("a_very_long_text_that_is_larger_than_the_text_field_in_the_report")
42 42 response.should contain("a_very_long_text_that_is_larger_than_the_text_field_in_the_")
43 43 end
44   -
  44 +
45 45 it "should show the parameters defined in the controller" do
46 46 get :index, :format => :pdf
47   -
  47 +
48 48 response.should contain("I'm a parameter. I was defined in the controller")
49 49 end
50 50
51 51 end
52   -
  52 +
53 53 describe "GET compile_time_error_report" do
54   -
  54 +
55 55 it "should raise a RuntimeError if the report's design is not valid" do
56 56 expect { get :compile_time_error_report, :format => :pdf }.to raise_error(RuntimeError, /Report design not valid/)
57 57 end
58   -
  58 +
59 59 end
60   -
  60 +
61 61 describe "GET runtime_error_report" do
62   -
  62 +
63 63 it "should raise a RuntimeError if the report could not be filled due to a runtime error" do
64 64 expect { get :runtime_error_report, :format => :pdf }.to raise_error(RuntimeError)
65 65 end
66   -
  66 +
67 67 end
68   -
  68 +
69 69 describe "GET nil_datasource" do
70   -
  70 +
71 71 it "should treat nil datasources" do
72 72 get :nil_datasource, :format => :pdf
73   -
  73 +
74 74 response.should contain("I'm a parameter. I was defined in the controller")
75 75 end
76   -
  76 +
  77 + end
  78 +
  79 + describe "GET java_parameter" do
  80 +
  81 + it "accepts java parameter without converting it to string" do
  82 + get :java_parameter, :format => :pdf
  83 +
  84 + response.should contain("The Beatles")
  85 + end
  86 +
77 87 end
78   -
79   -end
  88 +
  89 +end
18 spec/internal/app/controllers/people_controller.rb
@@ -3,17 +3,17 @@ class PeopleController < ActionController::Base
3 3
4 4 def index
5 5 @people = Person.all
6   -
  6 +
7 7 @parameter_defined_in_the_controller = "I'm a parameter. I was defined in the controller"
8   -
  8 +
9 9 respond_with @people
10 10 end
11 11
12   - def compile_time_error_report
  12 + def compile_time_error_report
13 13 respond_with []
14 14 end
15   -
16   - def runtime_error_report
  15 +
  16 + def runtime_error_report
17 17 respond_with []
18 18 end
19 19
@@ -22,4 +22,12 @@ def nil_datasource
22 22 respond_with nil
23 23 end
24 24
  25 + def java_parameter
  26 + title = (Rjb::import 'java.lang.String').new("The Beatles")
  27 + @parameter_that_is_a_java_class = (Rjb::import 'java.util.HashMap').new
  28 + @parameter_that_is_a_java_class.put("title", title)
  29 +
  30 + respond_with nil
  31 + end
  32 +
25 33 end
118 spec/internal/app/views/people/java_parameter.jrxml
... ... @@ -0,0 +1,118 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="index" language="groovy" pageWidth="595" pageHeight="842" columnWidth="535" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="311ea5a2-cc66-43bf-9af3-b2e0a552b1de">
  3 + <property name="ireport.zoom" value="1.0"/>
  4 + <property name="ireport.x" value="0"/>
  5 + <property name="ireport.y" value="0"/>
  6 + <style name="Title" forecolor="#FFFFFF" fontName="Arial" fontSize="26" isBold="true" pdfFontName="Helvetica-Bold"/>
  7 + <style name="SubTitle" forecolor="#666666" fontName="Arial" fontSize="18"/>
  8 + <style name="Column header" forecolor="#666666" fontName="Arial" fontSize="12" isBold="true"/>
  9 + <style name="Detail" fontName="Arial" fontSize="12"/>
  10 + <parameter name="parameter_that_is_a_java_class" class="java.util.Map"/>
  11 + <queryString language="xPath">
  12 + <![CDATA[/people/person]]>
  13 + </queryString>
  14 + <field name="name" class="java.lang.String">
  15 + <fieldDescription><![CDATA[name]]></fieldDescription>
  16 + </field>
  17 + <field name="email" class="java.lang.String">
  18 + <fieldDescription><![CDATA[email]]></fieldDescription>
  19 + </field>
  20 + <background>
  21 + <band splitType="Stretch"/>
  22 + </background>
  23 + <title>
  24 + <band height="70" splitType="Stretch">
  25 + <image>
  26 + <reportElement uuid="0b15b501-e65d-4f8b-b890-759a6d279efe" x="-20" y="0" width="595" height="64"/>
  27 + <imageExpression><![CDATA["wood.jpg"]]></imageExpression>
  28 + </image>
  29 + <staticText>
  30 + <reportElement uuid="dfeee47e-d32e-4525-a708-7cc3d6ec3f91" style="Title" x="0" y="5" width="263" height="33"/>
  31 + <textElement verticalAlignment="Middle"/>
  32 + <text><![CDATA[jasper-rails]]></text>
  33 + </staticText>
  34 + <textField>
  35 + <reportElement uuid="91699025-171b-40b4-ae45-eb9cdca69b2b" x="97" y="38" width="358" height="20" forecolor="#FFFFFF"/>
  36 + <textElement>
  37 + <font size="15"/>
  38 + </textElement>
  39 + <textFieldExpression><![CDATA[$P{parameter_that_is_a_java_class}.get("title")]]></textFieldExpression>
  40 + </textField>
  41 + </band>
  42 + </title>
  43 + <pageHeader>
  44 + <band splitType="Stretch"/>
  45 + </pageHeader>
  46 + <columnHeader>
  47 + <band height="36" splitType="Stretch">
  48 + <line>
  49 + <reportElement uuid="6a63817d-d338-4966-9432-96e7baffc7f8" positionType="FixRelativeToBottom" x="0" y="35" width="555" height="1"/>
  50 + <graphicElement>
  51 + <pen lineWidth="0.5" lineColor="#999999"/>
  52 + </graphicElement>
  53 + </line>
  54 + <staticText>
  55 + <reportElement uuid="89d037e3-230c-4845-b0aa-a43920c60dc2" x="48" y="15" width="100" height="20"/>
  56 + <textElement/>
  57 + <text><![CDATA[name]]></text>
  58 + </staticText>
  59 + <staticText>
  60 + <reportElement uuid="6920786b-3719-4243-bee2-9e4073274cb1" x="245" y="15" width="100" height="20"/>
  61 + <textElement/>
  62 + <text><![CDATA[email]]></text>
  63 + </staticText>
  64 + </band>
  65 + </columnHeader>
  66 + <detail>
  67 + <band height="21" splitType="Stretch">
  68 + <textField>
  69 + <reportElement uuid="63d9b6a9-caa5-40d8-8bb0-41822dd43364" x="48" y="0" width="185" height="20"/>
  70 + <textElement/>
  71 + <textFieldExpression><![CDATA[$F{name}]]></textFieldExpression>
  72 + </textField>
  73 + <textField>
  74 + <reportElement uuid="83b41533-c6ed-4de6-8c48-5545c9c78e43" x="245" y="0" width="290" height="20"/>
  75 + <textElement/>
  76 + <textFieldExpression><![CDATA[$F{email}]]></textFieldExpression>
  77 + </textField>
  78 + </band>
  79 + </detail>
  80 + <columnFooter>
  81 + <band height="45" splitType="Stretch">
  82 + <line>
  83 + <reportElement uuid="9642b713-530f-4d6e-a4dd-b6e7b4d07e2b" positionType="FixRelativeToBottom" x="0" y="3" width="555" height="1"/>
  84 + <graphicElement>
  85 + <pen lineWidth="0.5" lineColor="#999999"/>
  86 + </graphicElement>
  87 + </line>
  88 + </band>
  89 + </columnFooter>
  90 + <pageFooter>
  91 + <band height="20" splitType="Stretch">
  92 + <textField>
  93 + <reportElement uuid="06b23f1b-7ac0-4c70-bb2e-2aeb039f67a3" style="Column header" x="433" y="0" width="80" height="20"/>
  94 + <textElement textAlignment="Right">
  95 + <font size="10" isBold="false"/>
  96 + </textElement>
  97 + <textFieldExpression><![CDATA["Page "+$V{PAGE_NUMBER}+" of"]]></textFieldExpression>
  98 + </textField>
  99 + <textField evaluationTime="Report">
  100 + <reportElement uuid="b8b7868e-fe9c-4e1b-8a24-75b97450ef73" style="Column header" x="513" y="0" width="40" height="20"/>
  101 + <textElement>
  102 + <font size="10" isBold="false"/>
  103 + </textElement>
  104 + <textFieldExpression><![CDATA[" " + $V{PAGE_NUMBER}]]></textFieldExpression>
  105 + </textField>
  106 + <textField pattern="EEEEE dd MMMMM yyyy">
  107 + <reportElement uuid="f924a532-c0df-4366-baad-4126ffb1462f" style="Column header" x="0" y="0" width="197" height="20"/>
  108 + <textElement>
  109 + <font size="10" isBold="false"/>
  110 + </textElement>
  111 + <textFieldExpression><![CDATA[new java.util.Date()]]></textFieldExpression>
  112 + </textField>
  113 + </band>
  114 + </pageFooter>
  115 + <summary>
  116 + <band splitType="Stretch"/>
  117 + </summary>
  118 +</jasperReport>
1  spec/internal/config/routes.rb
@@ -4,6 +4,7 @@
4 4 get 'compile_time_error_report'
5 5 get 'runtime_error_report'
6 6 get 'nil_datasource'
  7 + get 'java_parameter'
7 8 end
8 9 end
9 10 end

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.