Javascript functions in rptLibrary not always seen by Rhino

Jerome Jadoulle
edited February 11, 2022 in Analytics #1
Good day!<br />
<br />
We have developed a test setup based on Birt V3.7.1?s report engine which allows ensuring that the data we fetch from our datasources - and potentially compute - stays valid whatever the updates we apply to our reports (i.e. a non-regression testing environment for our Birt reports).<br />
<br />
We are facing a problem with <strong class='bbc'>some </strong>of the reports (the fact that it does not occur with all reports might be a hint) which can?t make use of in-house developed JavaScript functions, this only in case of usage in our test setup (everything goes fine in production).<br />
<br />
The error is the following:<br />
<pre class='_prettyXprint _lang-auto _linenums:0'>org.eclipse.birt.data.engine.core.DataException: A BIRT exception occurred. See next exception for more information.
Error evaluating Javascript expression. Script engine error: ReferenceError: "formatDuration" is not defined.
Script source: null, line: 0, text:
<compiled script>
at org.eclipse.birt.data.engine.core.DataException.wrap(DataException.java:123)
at org.eclipse.birt.data.engine.expression.BytecodeExpression.evaluate(BytecodeExpression.java:54)
at org.eclipse.birt.data.engine.expression.ExprEvaluateUtil.evaluateCompiledExpression(ExprEvaluateUtil.java:205)
at org.eclipse.birt.data.engine.expression.ExprEvaluateUtil.evaluateCompiledExpression(ExprEvaluateUtil.java:219)
at org.eclipse.birt.data.engine.expression.ExprEvaluateUtil.evaluateExpression(ExprEvaluateUtil.java:76)
at org.eclipse.birt.data.engine.impl.BindingColumnsEvalUtil.evaluateValue(BindingColumnsEvalUtil.java:201)
at org.eclipse.birt.data.engine.impl.BindingColumnsEvalUtil.getColumnsValue(BindingColumnsEvalUtil.java:161)
at org.eclipse.birt.data.engine.impl.ResultIterator.prepareCurrentRow(ResultIterator.java:778)
at org.eclipse.birt.data.engine.impl.ResultIterator.<init>(ResultIterator.java:168)
at org.eclipse.birt.data.engine.impl.QueryResults.getResultIterator(QueryResults.java:208)
at org.eclipse.birt.report.engine.api.impl.ExtractionResults.nextResultIterator(ExtractionResults.java:74)
?
Caused by: org.eclipse.birt.core.exception.CoreException: Error evaluating Javascript expression. Script engine error: ReferenceError: "formatDuration" is not defined.
Script source: null, line: 0, text:
<compiled script>
at org.eclipse.birt.core.script.JavascriptEvalUtil.wrapRhinoException(JavascriptEvalUtil.java:303)
at org.eclipse.birt.data.engine.expression.BytecodeExpression.evaluate(BytecodeExpression.java:55)
... 37 more
Caused by: org.mozilla.javascript.EcmaError: ReferenceError: "formatDuration" is not defined.
at org.mozilla.javascript.ScriptRuntime.constructError(ScriptRuntime.java:3654)
at org.mozilla.javascript.ScriptRuntime.constructError(ScriptRuntime.java:3632)
at org.mozilla.javascript.ScriptRuntime.notFoundError(ScriptRuntime.java:3717)
at org.mozilla.javascript.ScriptRuntime.nameOrFunction(ScriptRuntime.java:1758)
at org.mozilla.javascript.ScriptRuntime.getNameFunctionAndThis(ScriptRuntime.java:2135)
at org.mozilla.javascript.Interpreter.interpretLoop(Interpreter.java:3134)
at org.mozilla.javascript.Interpreter.interpret(Interpreter.java:2487)
at org.mozilla.javascript.InterpretedFunction.call(InterpretedFunction.java:164)
at org.mozilla.javascript.ContextFactory.doTopCall(ContextFactory.java:398)
at org.mozilla.javascript.ScriptRuntime.doTopCall(ScriptRuntime.java:3065)
at org.mozilla.javascript.InterpretedFunction.exec(InterpretedFunction.java:175)
at org.eclipse.birt.data.engine.expression.BytecodeExpression.evaluate(BytecodeExpression.java:49)
... 37 more</pre>
<br />
?where the ?formatDuration? variable that seems not to be defined varies. <br />
<br />
In this specific example, ?formatDuration? is actually a JavaScript function contained in the only .js file referenced in the rptLibrary used by all our designs.<br />
<br />
The major difference between the production environment and the test one is that the production environment performs a runAndRender task, thus everything from the report execution and rendering (to a pdf document in our case) in one Birt Engine instance whereas in the case of the test setup, a first Birt Engine ? the one running on the production system ? generates a temporary .rptDocument (in order to extract all data from datasources & so on) and another one , on another system ? our test environment ? takes on by opening the .rptDocument and outputting its raw data to a .csv file<br />
<br />
The ultimate goal of the system is to test the content of the generated .csv file against a reference .csv file that we know is correct.<br />
<br />
We have tried all the following without success:<br />
<ul class='bbc'><li>Setting a specific resource locator for both our engine configs (using EngineConfig.setResourceLocator()). This seemed like the most obvious thing to do.<br />
Note that his stays valid for all the other tests explained here below.<br />
<br />
We know for a fact that the implementation of the production site is used (as it simply works!) but we are not certain that the version implemented in the test environment is actually called (the log messages written in there don?t seem to be displayed anywhere? maybe that?s the problem already).<br />
</li><li>Directly include the .js file in the .rptDesign (although it is already imported by the .rptLibrary):<br />
To do this, we copy-pasted the inclusion of the .js from the .rptLibrary to the .rptDocument by using the xml view of both files:<br />
<list-property name="includeScripts"><br />
<property>myScript.js</property><br />
</list-property><br />
</li><li>In the .js containing the ?formatDuration? method, we added:<br />
reportContext.setPersistentGlobalVariable("formatDuration", formatDuration);<br />
In order to have it usable by everything everywhere? No luck there<br />
</li><li>Added the same line in the ?initialize? script hook of the root component of the .rptDesign report file.<br />
</li><li>When calling the method, instead of simply writing formatDuration([SOME_PARAM]), we wrote:<br />
formatDuration = reportContext.getPersistentGlobalVariable('formatDuration');<br />
formatDuration([SOME_PARAM]);</li></ul>
<br />
As said already, nothing from here above worked. Please kindly note that I am no Birt expert but simply ?the one? in charge of trying to find a solution for the problem. What I tried here above might look stupid because of that (if that?s the case, I?m sorry!).<br />
<br />
Let me also remind you that this only occurs with some of the reports (.rptDesign) we test. For some others, the non-working methods simply work! (DIFFing the reports didn?t enlighten us a bit unfortunately).<br />
<br />
Thank you very much in advance for any help you will provide,<br />
<br />
J?r?me Jadoulle

Comments

  • JasonW
    edited December 31, 1969 #2
    Can you post one of the reports that do not work? Is it failing in the designer or a deployed viewer?

    Jason
  • Jerome Jadoulle
    edited December 31, 1969 #3
    Good afternoon Jason,
    I am busy preparing an archive containing a report that does not work.
    In the meantime, please have a look at the 2 small diagrams I have quickly created exposing where the problem occurs.

    It is not failing in the designer. I get this error on my test server when I perform a DataExtractionTask on an rptDocument that comes from a distant production server.
  • Jerome Jadoulle
    edited December 31, 1969 #4
    Jason,

    please find here attached a report structure that fails.
    The rptLibary, the js and the rptDesign are all included.

    Hope it helps,

    J?r?me
  • Jerome Jadoulle
    edited December 31, 1969 #5
    Good day.

    It has been a while since my last post on this topic but I'm still stuck with this one. Did you, by any chance, have some time to check into it?
  • JasonW
    edited December 18, 2012 #6
    There may be an issue with script context. Can you try to dynamically load the script from the resource folder?

    importPackage(Packages.java.io);
    importPackage(Packages.java.lang);
    ist = reportContext.getResource("myjsfile.js").openStream();

    myjsstring="nothing";

    bytesa = new ByteArrayOutputStream();
    var c;
    while((c=ist.read()) != -1){
    bytesa.write( c );
    }
    ist.close();
    data = bytesa.toByteArray();
    value = new String(data);
    myjsstring = reportContext.evaluate(value);

    //getMyValue is the function defined in myjsfile.js
    this.text = getMyValue();

    Jason