Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JsonDataSource not working good with locales #140

Open
abnud1 opened this issue Jun 28, 2020 · 1 comment
Open

JsonDataSource not working good with locales #140

abnud1 opened this issue Jun 28, 2020 · 1 comment

Comments

@abnud1
Copy link

abnud1 commented Jun 28, 2020

I have a report which has a subreport, the subreport data source is a JsonDataSource from a ByteArrayInputStream containing json bytes passed as parameter to original report.

One of the fields of the json is a double number, I when I try printing report to pdf using jasperreports java lib, I get this exception:

net.sf.jasperreports.engine.JRRuntimeException: net.sf.jasperreports.engine.JRException: Unable to get value for JSON field "GrdDividerArea1" of class java.lang.Double.
at net.sf.jasperreports.engine.fill.JRFillSubreport.prepare(JRFillSubreport.java:962)
at net.sf.jasperreports.engine.fill.JRFillElementContainer.prepareElements(JRFillElementContainer.java:542)
at net.sf.jasperreports.engine.fill.JRFillBand.fill(JRFillBand.java:453)
at net.sf.jasperreports.engine.fill.JRFillBand.fill(JRFillBand.java:428)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillColumnBand(JRVerticalFiller.java:2599)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillDetail(JRVerticalFiller.java:823)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReportStart(JRVerticalFiller.java:264)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:110)
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:615)
at net.sf.jasperreports.engine.fill.BaseReportFiller.fill(BaseReportFiller.java:433)
at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:162)
at net.sf.jasperreports.engine.fill.JRFiller.fill(JRFiller.java:145)
at net.sf.jasperreports.engine.JasperFillManager.fill(JasperFillManager.java:758)
at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:1074)
at com.i4all.controllers.ReportController.report(ReportController.kt:127)
at com.i4all.controllers.ReportController$Module.postReport$reportName$taskId$ctx(com.i4all.controllers.ReportController$Module.java)
at io.jooby.Route$Before.lambda$then$e67b40fd$1(Route.java:133)
at io.jooby.Route$Handler.lambda$then$3a6f0e7d$1(Route.java:268)
at io.jooby.internal.handler.SendDirect.apply(SendDirect.java:22)
at io.jooby.internal.handler.WorkerHandler.lambda$apply$0(WorkerHandler.java:23)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1449)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: net.sf.jasperreports.engine.JRException: Unable to get value for JSON field "GrdDividerArea1" of class java.lang.Double.
at net.sf.jasperreports.engine.data.JsonDataSource.getFieldValue(JsonDataSource.java:277)
at net.sf.jasperreports.engine.fill.JRFillDataset.setOldValues(JRFillDataset.java:1501)
at net.sf.jasperreports.engine.fill.JRFillDataset.next(JRFillDataset.java:1402)
at net.sf.jasperreports.engine.fill.JRFillDataset.next(JRFillDataset.java:1378)
at net.sf.jasperreports.engine.fill.JRBaseFiller.next(JRBaseFiller.java:1194)
at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:108)
at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:615)
at net.sf.jasperreports.engine.fill.BaseReportFiller.fill(BaseReportFiller.java:433)
at net.sf.jasperreports.engine.fill.JRFillSubreport.fillSubreport(JRFillSubreport.java:824)
at net.sf.jasperreports.engine.fill.JRSubreportRunnable.run(JRSubreportRunnable.java:61)
at net.sf.jasperreports.engine.fill.AbstractThreadSubreportRunner.run(AbstractThreadSubreportRunner.java:221)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
... 1 more
Caused by: org.apache.commons.beanutils.ConversionException: Unparseable number: "-8.747558720707385E7"
at org.apache.commons.beanutils.locale.BaseLocaleConverter.convert(BaseLocaleConverter.java:245)
at org.apache.commons.beanutils.locale.LocaleConvertUtilsBean.convert(LocaleConvertUtilsBean.java:286)
at net.sf.jasperreports.engine.data.JRAbstractTextDataSource.convertStringValue(JRAbstractTextDataSource.java:78)
at net.sf.jasperreports.engine.data.JsonDataSource.getFieldValue(JsonDataSource.java:261)
... 13 more
Caused by: java.text.ParseException: Unparseable number: "-8.747558720707385E7"
at java.base/java.text.NumberFormat.parse(NumberFormat.java:431)
at org.apache.commons.beanutils.locale.converters.DecimalLocaleConverter.parse(DecimalLocaleConverter.java:253)
at org.apache.commons.beanutils.locale.converters.DoubleLocaleConverter.parse(DoubleLocaleConverter.java:217)
at org.apache.commons.beanutils.locale.BaseLocaleConverter.convert(BaseLocaleConverter.java:236)
... 16 more

Now looking at this code:

else if (Number.class.isAssignableFrom(valueClass)) {
						//FIXME if the json node is a number, avoid converting to string and parsing back the value
							value = convertStringValue(selectedObject.asText(), valueClass);
							
					}

The problem we have here is that jackson's asText will convert the double number to string using english locale, I'm afraid that the default locale of the JVM is arabic, I've verified this by putting a breakpoint at apache commons-beanutils code here:

/**
     * Convert the specified locale-sensitive input object into an output
     * object of the specified type.
     *
     * @param value The input object to be converted
     * @param pattern The pattern is used for the convertion
     * @return The converted value
     *
     * @throws org.apache.commons.beanutils.ConversionException if conversion
     * cannot be performed successfully
     * @throws ParseException if an error occurs parsing a String to a Number
     */
    @Override
    protected Object parse(final Object value, final String pattern) throws ParseException {

        if (value instanceof Number) {
            return value;
        }

        // Note that despite the ambiguous "getInstance" name, and despite the
        // fact that objects returned from this method have the same toString
        // representation, each call to getInstance actually returns a new
        // object.
        final DecimalFormat formatter = (DecimalFormat) DecimalFormat.getInstance(locale); // breakpoint is set on this line and I confirmed that locale is arabic

        // if some constructors default pattern to null, it makes only sense
        // to handle null pattern gracefully
        if (pattern != null) {
            if (locPattern) {
                formatter.applyLocalizedPattern(pattern);
            } else {
                formatter.applyPattern(pattern);
            }
        } else {
            log.debug("No pattern provided, using default.");
        }

        return formatter.parse((String) value);
    }

at org.apache.commons.beanutils.locale.converters.DecimalLocaleConverter.java

This is what causes the exception, my suggestion is to either fix the //FIXME comment or use english locale for parsing such numbers since the result is a double so locale doesn't matter really here.

Oh I'm using arabic locale since all reports are arabic :).

@shertage
Copy link
Collaborator

shertage commented Aug 3, 2020

Hi,
Could you post a JRXML and data sample demonstrating this problem?
Thank you,
Sanda

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants