Jump to content
Changes to the Jaspersoft community edition download ×

Localization and resource bundles in a web app


richh

Recommended Posts

After working with IReport for several weeks now, I have found some solutions to problems I have encountered. I am posting it here so that others may benefit from my experience.

 

It seems that localization and resource bundles turn out to be a problem when moving the reports from the IReport development environment to an actual web application.

 

1. The default locale is lost when using the compiled report in a web application. I am not an expert on JasperReports so I might have missed something but I do not see a locale setting in the .jrxml file.

 

2. File path differences between development and web application can be a headache.

 

3. Paths to the scriptlet can also be a problem. This was solved by specifying my own implementation of the class. This is the same as using the built in file except you can specify a package. In report properties for scriptlet class, select, "use this scriptlet class..." and enter the full dotted address of the class. You will need to include the directory where the root of the class is located. Example: the compiled scriptlet class named myScriptlet.class in package com.myco.mytools is in the c:projectsmyReportclasses directory. Enter com.myco.myWeb.myScriptlet as the scriptlet class to use and add "c:projectsmyWebclasses" to the classpath. The class can be deployed normally in your web application.

 

I was never able to solve the rest of the problems in IReport itself. I resorted to using java code to fix the problems.

 

Here is my struts action for printing a PDF report.

 

Code:

/**
* Struts Action for printing a tax assessment PDF.
*
* @author Richard Hart
*
*/
public class TAPrintPDFAction extends BaseAction {
public ActionForward executeAction(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
//Get the tax assessment id.
Integer taid = StringHelper.convert(request
.getParameter("taxassessmentid"«»));
//If no tax assessment id, throw an exception.
if (KeyHelper.isEmpty(taid)) {
throw new AtlasException("no taxreturnid found"«»);
}

//Get a PdfReport ready to use.
PdfReport pdfReport = new PdfReport();
//Map the parameters passed to runPdfReport.
Map parameters = new HashMap();
//Set the tax assessment id mapped parameter.
parameters.put("TAID", taid);
//Find the real path to the tax assessment report.
String filePath = servlet
.getServletContext()
.getRealPath(
"/reporting/xml/reports/taxassessment/taxassessmentReport.jasper"«»);
//Find the real path to the subreport. If this parameter is not set, the subreport will not be found.
String subFilePath = servlet.getServletContext().getRealPath(
"/reporting/xml/reports/taxassessment/"«»)
+ File.separator;
//In my case, the report resource bundle is in the same directory as the reports.
String appResourceBundlePath = subFilePath
+ "taxassessmentReport.properties";
//Set the sub report directory mapped parameter
parameters.put("SUBREPORT_DIR", subFilePath);
//Set the report locale. In this case, Dutch.
parameters.put("REPORT_LOCALE", new Locale("nl", "NL"«»));
try {
//Get the report's resource bundle.
parameters = getResourceBundle(parameters, appResourceBundlePath);
//Run the report
pdfReport.runPdfReport(filePath, "aanslag", parameters, response);
} catch (IOException e) {
e.printStackTrace();
ActionMessages ams = new ActionMessages();
//Retun a struts action message about the exception
ams.add("filenotfound", new ActionMessage(
"taxassessment.pdf.resourcenotfound"«»));
saveMessages(request, ams);
}
return null;
}

/**
* Load the Map parameters with the report's resource bundle.
* @param params Map of parameters
* @param rbPath String of resource bundle file real path
* @return Map of parameters including the REPORT_RESOURCE_BUNDLE parameter
* @throws IOException
*/
protected Map getResourceBundle(Map params, String rbPath)
throws IOException {
FileInputStream fis = null;
try {
fis = new FileInputStream(rbPath);
ResourceBundle rb = new PropertyResourceBundle(fis);
params.put("REPORT_RESOURCE_BUNDLE", rb);
} finally {
try {
fis.close();
} catch (IOException e) {
}
}
return (params);
}
}

 

I know there are problems with this. For example, the purpose of resource bundles and locale is to support more than one language. If you think about it though, this is a struts action class. It would not be difficult to obtain the web browser locale and set the bundle and locale appropriately. In my case we have no plans to internationalize but it is still appropriate to store the text in a resource bundle.

 

Here is the code for the PdfReport. This was lifted and modified from another posting.

 

 

Code:
[code]
package com.pwc.compliance.business.pdf.writer;
/**
* This class uses JasperReport to generate a PDF file.
*/
import java.io.IOException;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Category;

import com.pwc.compliance.business.pdf.JasperRunner;
import com.pwc.compliance.exception.PDFWriterException;
import com.pwc.tts.framework.exception.AtlasDataException;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperExportManager;

/**
* Generates a pdf file to a http servlet response output stream.
*
* @author Richard Hart
*
*/
public class PdfReport {
private static Category cat = Category.getInstance(PdfReport.class);

/**
* runPdfReport
*
* Use this method to generate the PDF report.
*
* @param report String of report name [Ex: myReport.jasper].
* @param filename String of file name to save as.
* @param parameters Map of parameter names and values.
* @param response HttpServletResponse to use the output stream.
* @throws PDFWriterException
* @throws AtlasDataException
*/
public void runPdfReport(String report, String filename, Map parameters,
HttpServletResponse response) throws PDFWriterException,
AtlasDataException {
JasperRunner jr = new JasperRunner();
JasperPrint reportout = null;
reportout = jr.makereport(parameters, report);
byte[] pdf = null;

try {
pdf = JasperExportManager.exportReportToPdf(reportout);
} catch (JRException ex3) {
ex3.printStackTrace();
cat.error(ex3.getMessage(), ex3);
throw new PDFWriterException("Couldn't create PDF: " + ex3.getMessage());
}

response.setContentType("application/pdf"«»);
response.setContentLength(pdf.length);
response.setHeader("Content-disposition", "attachment; filename=""
+ filename + ".pdf""«»);
ServletOutputStream out = null;
try {
out = response.getOutputStream();
out.write(pdf);
} catch (IOException qw) {
qw.printStackTrace();
cat.error(qw.getMessage(), qw);
throw new PDFWriterException("Could not output file " + filename + ": "
+ qw.getMessage());
} finally {
try {
out.flush();
out.close();
} catch (IOException e) {
}
}
}
}

 

Code:
[code]
package com.pwc.compliance.business.pdf;

import java.sql.Connection;
import java.util.Map;

import org.apache.log4j.Category;


import com.pwc.compliance.exception.PDFWriterException;
import com.pwc.tts.framework.exception.AtlasDataException;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.util.JRLoader;
/**
* JasperRunner class is used to make a JasperReport object.
* It obtains a DB connection and fills the compiled report file,
* returning the resulting JasperReport class.
*
* @author Richard Hart
*
*/
public class JasperRunner extends com.pwc.tts.framework.base.DataModule {
private static Category cat = Category.getInstance(JasperRunner.class);

// datamodule myDataModule = new datamodule();
JasperReport jasperReportsub[] = { null, null, null, null, null, null,
null, null, null, null };

int subReportCount = 0;

public JasperPrint makereport(Map params, String report)
throws PDFWriterException, AtlasDataException {
JasperReport jasperReport = null;

JasperPrint jasperPrint = null;

Connection conn = null;
Connection con = null;
try {
conn = getConnection("compliance"«»);
jasperReport = (JasperReport) JRLoader.loadObject(report);
jasperPrint = JasperFillManager.fillReport(jasperReport, params, conn);
} catch (JRException e) {
e.printStackTrace();
cat.error(e.getMessage(), e);
throw new PDFWriterException(e.getMessage());
} finally {
finallyCloseConnection(con);
}
return jasperPrint;
}

}
Link to comment
Share on other sites

  • 2 weeks later...
  • Replies 2
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

I have discovered a work around for the resource bundle problem between the development environment (iReport) and a web application. Rather than using iReports internationalization tool, edit the XML directly. The first tag is <jasperReport> with a bunch of key value pairs. Either add or modify the key value pair resourceBundle="dotted.file.path.fileName". Do not add the .properties extention to this value. Use a dotted file path from the myWebApp/WEB-INF/classes directory. Add this directory to your classpath in iReport. Both the web application and iReport will find the resource bundle. If you have subreports, do the same with them. You can use the same or different resource bundles for the subreports. You won't see the localization setting in iReport, i.e. you can not edit the file from within iReport.
Link to comment
Share on other sites

  • 2 weeks later...

Hi

This is Atanu. I am very new in ireport and also in java environment. In the ireport I have designed a template .like this.

please look on attach file

size=150C:Documents and SettingsAtanuMy Documentsgraph.jpeg[/img]

Now I want to plot a line graph on the basis of the each data like t1 t2 ---t5 and lcl, ucl, actual value for each row.

That I have done. Now my problem is that I have to change the color of points of t1 t2 ---t5 on the basis of Lcl and Ucl . If the value of t1 ,or t2 or ----t5 are between Ucl and Lcl the color will be blue. And if it out side of Lcl and Ucl then it will be red..

I want the following figure. Where the upper bold line is Ucl and lower bold line isLcl

size=150C:Documents and SettingsAtanuMy Documentsdata.jpeg[/img]

Actually I have got a information that for that I have to write a customizer class for chart. Also I have write it .

 

Code:

import net.sf.jasperreports.engine.*;
import net.sf.jasperreports.view.JasperViewer;
import net.sf.jasperreports.engine.JREmptyDataSource;
import java.util.*;
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import net.sf.jasperreports.engine.JRAbstractChartCustomizer;
import javax.sql.*;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.*;
import org.jfree.chart.renderer.*;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.chart.renderer.category.LevelRenderer;
import org.jfree.chart.renderer.category.LayeredBarRenderer;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.util.HashMap;
import java.util.Map;
import java.lang.String;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.view.JasperViewer;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.design.JasperDesign;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.JRChartDataset;
import net.sf.jasperreports.engine.JRChartPlot;
import org.jfree.chart.renderer.category.BarRenderer3D;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.axis.CategoryLabelPositions;


import org.jfree.chart.renderer.category.LineRenderer3D;
import java.awt.*;
import net.sf.jasperreports.engine.JRChart;
import net.sf.jasperreports.engine.JRChartCustomizer;
import org.jfree.chart.JFreeChart;
import net.sf.jasperreports.engine.*;
import java.awt.Color;
import net.sf.jasperreports.engine.JRChart;
import net.sf.jasperreports.engine.JRChartCustomizer;

import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.CategoryLabelPositions;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.renderer.category.BarRenderer3D;
import java.lang.Object;



public class LineChartCustomizer extends JRAbstractChartCustomizer {

public void customize(JFreeChart chart, JRChart jasperChart) {

LineAndShapeRenderer renderer = (LineAndShapeRenderer) chart.getCategoryPlot().getRenderer();


renderer.setSeriesPaint(1, Color.green);
renderer.setSeriesPaint(4, Color.orange);

chart.setTitle("Setting the title "«»);
}


}

Now this customize class ok running successfully with creating jar files.

Now I want to create a logic to check the value of t1 t2 t3 t5 with respect to UCL and LCL. How can I fetch data from report.

Or is there any other way to do this.

Is there any way to pass value from iReport to customizer class ?

 

What should I do. Please please help me. It’s urget for me.

 

Any help would be greatly appreciated.

Thanks in advance.

[file name=query-37ab101e3a539a71be9c962f72749d92.doc size=49152]http://www.jasperforge.org/components/com_joomlaboard/uploaded/files/query-37ab101e3a539a71be9c962f72749d92.doc[/file]

 

Post edited by: atanupanda, at: 2007/02/06 10:06

Post edited by: atanupanda, at: 2007/02/06 10:07

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...