Raible's Wiki

Raible Designs
Wiki Home
News
Recent Changes

AppFuse

Homepage
  - Korean
  - Chinese
  - Italian
  - Japanese

QuickStart Guide
  - Chinese
  - French
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish
  - Japanese

User Guide
  - Korean
  - Chinese

Tutorials
  - Chinese
  - German
  - Italian
  - Korean
  - Portuguese
  - Spanish

FAQ
  - Korean

Latest Downloads

Other Applications

Struts Resume
Security Example
Struts Menu

Set your name in
UserPreferences


Referenced by
...nobody




JSPWiki v2.2.33

[RSS]


Hide Menu

AppFuseJasperReports


Difference between version 63 and version 60:

At line 2 changed 1 line.
This tutorial will show you how to add a Controller to generate reports from AppFuse database using JasperReports.
This tutorial will show you how to use JasperReports in appfuse based applications. As an example, a report listing all registered users will be created.
At line 5 changed 4 lines.
* [1] Create the UserReportController Controller
* [2] Configuring JasperReports on AppFuse
* [3] Designing Reports
* [4] Putting all together
* [1] Configuring JasperReports on AppFuse
* [2] Designing Reports
* [3] SpringMVC integration
* [4] JSF integration
At line 10 changed 1 line.
!!Create the UserReportController Controller [#1]
!!Configuring JasperReports on AppFuse [#1]
Below are the steps to (<a href="http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseAddLibrary">AppFuseAddLibrary</a>) set up <a href="http://jasperreports.sourceforge.net/">JasperReports</a> on AppFuse. For that, we will include the lastest release version of <a href="http://jasperreports.sourceforge.net/">JasperReports</a>, which in the hour of this writing was 1.2.0. <a href="http://jasperreports.sourceforge.net/">JasperReports</a> itself depends on the following projects:
* BeanShell
* Commons BeanUtils - it comes with AppFuse
* Commons Collections - it comes with AppFuse
* Commons Digester - it comes with AppFuse
* Commons Logging - it comes with AppFuse
* iText
* POI
__1.__ Create a new folder for your library in {{/lib}} using the pattern ''libname-version'' (e.g. {{/lib/iText-1.1}}).
{{
/jasper-reports-1.2.0
/itext-1.1.4
/poi-2.5.1
/bsh-2.0b2
}}
__2.__ Add all required {{.jar}}'s into the folder you created. (e.g. {{/lib/iText-1.1/iText.jar}})
{{
/lib/jasper-reports-1.2.0/jasperreports-1.2.0.jar
/lib/jasper-reports-1.2.0/jr-bsh-compiler.jar
/lib/itext-1.1.4/itext-1.1.4.jar
/lib/poi-2.5.1/poi-2.5.1.jar
/lib/bsh-2.0b2/bsh-2.0b2.jar
}}
__3.__ Edit {{/lib/lib.properties}} to include a section like the following for your library.
{{{
#
# JasperReports - http://jasperreports.sourceforge.net/
#
jasperreports.version=1.2.0
jasperreports.dir=${lib.dir}/jasper-reports-${jasperreports.version}
jasperreports.jar=${jasperreports.dir}/jasperreports-${jasperreports.version}.jar
}}}
{{{
#
# BeanShell - http://www.beanshell.org
#
bsh.version=2.0b2
bsh.dir=${lib.dir}/bsh-${bsh.version}
bsh.jar=${bsh.dir}/bsh-${bsh.version}.jar
}}}
{{{
#
# Poi - http://jakarta.apache.org/poi/index.html
#
poi.version=2.5.1
poi.dir=${lib.dir}/poi-${poi.version}
poi.jar=${poi.dir}/poi-${poi.version}.jar
}}}
{{{
# Itext - http://www.lowagie.com/iText/
#
itext.version=1.1.4
itext.dir=${lib.dir}/itext-${itext.version}
itext.jar=${itext.dir}/itext-${itext.version}.jar
}}}
__4.__ Add library to the necessary classpaths in {{/properties.xml}}.
{{{
<path id="web.compile.classpath">
...
<fileset dir="${jasperreports.dir}" includes="*.jar"/>
<pathelement location="${itext.jar}"/>
<pathelement location="${poi.jar}"/>
</path>
}}}
__5.__ The last step is making sure the library gets added to your deployed webapp. In the {{package-web}} target of {{/build.xml}} look for the {{<war>}} element and add another {{<lib>}} element.
{{{
<target name="package-web" depends="compile-web,jsp-2">
...
<lib dir="${jasperreports.dir}" includes="*.jar"/>
<lib file="${itext.jar}"/>
<lib file="${poi.jar}"/>
</war>
</target>
}}}
!!Designing Reports [#2]
The amused part arrived! With the aid of the designing tool <a href="http://ireport.sourceforge.net/">iReports</a>, we will construct a report based on the list of users of the AppFuse. We will use the lastest release of <a href="http://ireport.sourceforge.net/">iReports</a>, which in the hour of this writing was 1.2.0. It will not be a complex report, only a list of accounts of users with the following columns:
* UserName
* Name
* Country
* Province
* City
See the result of designing time:
%%
[http://raibledesigns.com/wiki/attach/AppFuseJasperReports/userreport.png]
%%
And execution time:
%%
[http://raibledesigns.com/wiki/attach/AppFuseJasperReports/userreportview.png]
%%
!!SpringMVC integration [#3]
!Create the UserReportController Controller
At line 118 changed 1 line.
!!Configuring JasperReports on AppFuse [#2]
!Putting all together
At line 120 changed 9 lines.
Now the necessary steps to (<a href="http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseAddLibrary">AppFuseAddLibrary</a>) set up <a href="http://jasperreports.sourceforge.net/">JasperReports</a> on AppFuse. For that, we will include the lastest release version of <a href="http://jasperreports.sourceforge.net/">JasperReports</a>, which in the hour of this writing was 1.2.0. <a href="http://jasperreports.sourceforge.net/">JasperReports</a> itself depends on the following projects:
* BeanShell
* Commons BeanUtils - it comes with AppFuse
* Commons Collections - it comes with AppFuse
* Commons Digester - it comes with AppFuse
* Commons Logging - it comes with AppFuse
* iText
* POI
Finally we will configure the jrxml file and the resolver for pdf, xsl, csv and HTML formats.
At line 130 changed 1 line.
__1.__ Create a new folder for your library in {{/lib}} using the pattern ''libname-version'' (e.g. {{/lib/iText-1.1}}).
__1.__ Create a new folder for your reports in {{/web/WEB-INF}} with the name {{reports}}.
At line 132 changed 6 lines.
{{
/jasper-reports-1.2.0
/itext-1.1.4
/poi-2.5.1
/bsh-2.0b2
}}
__2.__ Add the files in the format {{jrxml}} in the directory that you created.
At line 139 changed 1 line.
__2.__ Add all required {{.jar}}'s into the folder you created. (e.g. {{/lib/iText-1.1/iText.jar}})
{{{/WEB-INF/reports/userList.jrxml}}}
At line 141 changed 7 lines.
{{
/lib/jasper-reports-1.2.0/jasperreports-1.2.0.jar
/lib/jasper-reports-1.2.0/jr-bsh-compiler.jar
/lib/itext-1.1.4/itext-1.1.4.jar
/lib/poi-2.5.1/poi-2.5.1.jar
/lib/bsh-2.0b2/bsh-2.0b2.jar
}}
__3.__ Edit {{/WEB-INF/action-servlet.xml}} file to include the following section for the resolver and view, that we will use. You should have noted that in the UserReportController' method, we're using one parameter to define the format of the report's result at runtime. That is, we will use JasperReportsMultiFormatView view. First the resolver:
At line 149 changed 1 line.
__3.__ Edit {{/lib/lib.properties}} to include a section like the following for your library.
[{Java2HtmlPlugin
At line 151 changed 8 lines.
{{{
#
# JasperReports - http://jasperreports.sourceforge.net/
#
jasperreports.version=1.2.0
jasperreports.dir=${lib.dir}/jasper-reports-${jasperreports.version}
jasperreports.jar=${jasperreports.dir}/jasperreports-${jasperreports.version}.jar
}}}
<!-- If a JasperReports view requires more complex configuration then use the BeanNameViewResolver to map a given view name to a given view bean -->
<bean id="nameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
At line 160 changed 8 lines.
{{{
#
# BeanShell - http://www.beanshell.org
#
bsh.version=2.0b2
bsh.dir=${lib.dir}/bsh-${bsh.version}
bsh.jar=${bsh.dir}/bsh-${bsh.version}.jar
}}}
}]
At line 169 changed 8 lines.
{{{
#
# Poi - http://jakarta.apache.org/poi/index.html
#
poi.version=2.5.1
poi.dir=${lib.dir}/poi-${poi.version}
poi.jar=${poi.dir}/poi-${poi.version}.jar
}}}
And then the view:
At line 178 changed 7 lines.
{{{
# Itext - http://www.lowagie.com/iText/
#
itext.version=1.1.4
itext.dir=${lib.dir}/itext-${itext.version}
itext.jar=${itext.dir}/itext-${itext.version}.jar
}}}
[{Java2HtmlPlugin
At line 186 changed 1 line.
__4.__ Add library to the necessary classpaths in {{/properties.xml}}.
<bean id="userMultiFormatReport" class="org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView">
<property name="contentDispositionMappings">
<props>
<prop key="html">inline; filename=report.html</prop>
<prop key="csv">inline; filename=report.csv</prop>
<prop key="pdf">inline; filename=report.pdf</prop>
<prop key="xls">inline; filename=report.xls</prop>
</props>
</property>
<property name="url" value="/WEB-INF/reports/userList.jrxml" />
</bean>
At line 188 changed 7 lines.
{{{
<path id="web.compile.classpath">
...
<fileset dir="${jasperreports.dir}" includes="*.jar"/>
<pathelement location="${itext.jar}"/>
<pathelement location="${poi.jar}"/>
</path>
}]
At line 196 changed 1 line.
}}}
Run ant test-web -Dtestcase=UserReportController again. Make the deploy and access the url /appfuse/userReport.html?action=userReport&format=pdf. AppFuse rocks!
At line 198 removed 1 line.
__5.__ The last step is making sure the library gets added to your deployed webapp. In the {{package-web}} target of {{/build.xml}} look for the {{<war>}} element and add another {{<lib>}} element.
At line 200 changed 9 lines.
{{{
<target name="package-web" depends="compile-web,jsp-2"
...
<lib dir="${jasperreports.dir}" includes="*.jar"/>
<lib file="${itext.jar}"/>
<lib file="${poi.jar}"/>
</war>
</target>
}}}
!!JSF integration [#4]
At line 210 changed 1 line.
!!Designing Reports [#3]
!Add a JSF bean to your faces-config.xml
This bean should be in request scope and have the userManager injected to be able to get the list from the database:
At line 212 changed 1 line.
The amused part arrived! With the aid of the designing tool <a href="http://ireport.sourceforge.net/">iReports</a>, we will construct a report based on the list of users of the AppFuse. We will use the lastest release of <a href="http://ireport.sourceforge.net/">iReports</a>, which in the hour of this writing was 1.2.0. It will not be a complex report, only a list of accounts of users with the following columns:
[{Java2HtmlPlugin
At line 214 changed 5 lines.
* UserName
* Name
* Country
* Province
* City
<managed-bean>
<managed-bean-name>reports</managed-bean-name>
<managed-bean-class>org.appfuse.webapp.action.Reports</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>userManager</property-name>
<value>#{userManager}</value>
</managed-property>
</managed-bean>
At line 220 changed 1 line.
See the result of designing time:
}]
At line 222 changed 3 lines.
%%
[http://raibledesigns.com/wiki/attach/AppFuseJasperReports/userreport.png]
%%
! JSF Bean implementation
Depending on requirements we can implement a different behaviour for the bean when the user clicks the report link:
At line 226 changed 1 line.
And execution time:
* The report is saved on the server file system for further download.
* The report is opened directly on the client side without being saved (regenerated every time!).
At line 228 changed 3 lines.
%%
[http://raibledesigns.com/wiki/attach/AppFuseJasperReports/userreportview.png]
%%
Here is an implementation for the "saving file" behaviour:
At line 232 changed 1 line.
!!Putting all together [#4]
[{Java2HtmlPlugin
At line 234 changed 1 line.
Finally we will configure the jrxml file and the resolver for pdf, xsl, csv and HTML formats.
package org.appfuse.webapp.action;
import ...
public class Reports extends BasePage implements Serializable {
At line 236 changed 1 line.
__1.__ Create a new folder for your reports in {{/web/WEB-INF}} with the name {{reports}}.
private String format = "pdf";
private String WebDir = null;
public String getFormat() {
return format;
}
At line 238 changed 1 line.
__2.__ Add the files in the format {{jrxml}} in the directory that you created.
public void setFormat(String format) {
this.format = format;
}
At line 240 changed 1 line.
{{{/WEB-INF/reports/userList.jrxml}}}
public String getWebDir() {
return WebDir;
}
At line 242 changed 1 line.
__3.__ Edit {{/WEB-INF/action-servlet.xml}} file to include the following section for the resolver and view, that we will use. You should have noted that in the UserReportController' method, we're using one parameter to define the format of the report's result at runtime. That is, we will use JasperReportsMultiFormatView view. First the resolver:
// used only in during junit test
public void setWebDir(String webDir) {
WebDir = webDir;
}
At line 329 added 35 lines.
public String users() {
List results = userManager.getUsers(null);
Map parameters = new HashMap();
String ctxPath = getServletContext().getRealPath("/");
parameters.put("format", "pdf");
if (WebDir != null){
parameters.put("WEBDIR", WebDir);
}
try{
// prepare report and data
InputStream is = getServletContext().getResourceAsStream("/WEB-INF/reports/userList.jrxml");
JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(results);
// generate pdf file
JasperDesign jasperDesign = JRXmlLoader.load(is);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters,
ds);
JasperExportManager.exportReportToPdfFile(jasperPrint, ctxPath + "/resources/userList.pdf");
addMessage("errors.detail", "file created: " + ctxPath + "/resources/userList.pdf");
}
catch(Exception e){
log.error(e);
}
return null;
}
}
}]
It is pretty difficult to unit test this class correctly and the only thing I could think off was checking that the file is actually generated. Be sure to update the hard coded value in the report to load images from the correct location during the test.
At line 246 changed 2 lines.
<!-- If a JasperReports view requires more complex configuration then use the BeanNameViewResolver to map a given view name to a given view bean -->
<bean id="nameViewResolver" class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
package org.appfuse.webapp.action;
At line 368 added 31 lines.
import java.io.File;
public class ReportsTest extends BasePageTestCase {
private Reports bean;
protected void setUp() throws Exception {
super.setUp();
bean = (Reports) getManagedBean("reports");
// to use hard coded value in report
bean.setWebDir(null);
}
public void testSearch() throws Exception {
String ctxPath = bean.getServletContext().getRealPath("/");
// ensures resources directory is present
File f = new File(ctxPath + "/resources");
f.mkdir();
// generates report
assertNull(bean.users());
// checks the file is present
f = new File(ctxPath + "/resources/userList.pdf");
assertTrue(f.exists());
assertFalse(bean.hasErrors());
}
}
At line 251 removed 1 line.
And then the view:
At line 402 added 2 lines.
Here is the implementation for the "open in browser" behaviour:
At line 255 changed 11 lines.
<bean id="userMultiFormatReport" class="org.springframework.web.servlet.view.jasperreports.JasperReportsMultiFormatView">
<property name="contentDispositionMappings">
<props>
<prop key="html">inline; filename=report.html</prop>
<prop key="csv">inline; filename=report.csv</prop>
<prop key="pdf">inline; filename=report.pdf</prop>
<prop key="xls">inline; filename=report.xls</prop>
</props>
</property>
<property name="url" value="/WEB-INF/reports/userList.jrxml" />
</bean>
package org.appfuse.webapp.action;
import ...
public class Reports extends BasePage implements Serializable {
At line 410 added 26 lines.
public String users() {
List results = userManager.getUsers(null);
Map parameters = new HashMap();
parameters.put("format", "pdf");
parameters.put("WEBDIR", getServletContext().getRealPath("/"));
try{
InputStream is = getServletContext()
.getResourceAsStream("/WEB-INF/reports/userList.jrxml");
JRBeanCollectionDataSource ds = new JRBeanCollectionDataSource(results);
getResponse().setContentType("application/pdf");
getResponse().addHeader("Content-Disposition", "attachment; filename=userList.pdf");
JasperDesign jasperDesign = JRXmlLoader.load(is);
JasperReport jasperReport = JasperCompileManager.compileReport(jasperDesign);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, parameters, ds);
JasperExportManager.exportReportToPdfStream(jasperPrint, getResponse().getOutputStream());
getFacesContext().getApplication().getStateManager()
.saveSerializedView(getFacesContext());
getFacesContext().responseComplete();
}
catch(Exception e){
log.error(e);
}
return null;
}
}
At line 269 changed 1 line.
Run ant test-web -Dtestcase=UserReportController again. Make the deploy and access the url /appfuse/userReport.html?action=userReport&format=pdf. AppFuse rocks!
I have no unit test for this class, if you have one let us know.
At line 440 added 9 lines.
!Add a link to generate the report on the jsp page
It is as simple as :
[{Java2HtmlPlugin
<h:commandLink value="get pdf report" action="#{reports.users}"/>
}]

Back to AppFuseJasperReports, or to the Page History.