Printing NG Client with Velocity

Hi
I am trying to print a report using the Velocity Reports Plugin within servoy NG Client.

works as expected and previews the report
plugins.VelocityReport.previewReport(template,context)

show the printer dialogue but fails to print
plugins.VelocityReport.printReport(template, context)

Is there a problem with printing from NG Client and if so is there any workaround ? The solution is needed for an exhibition and one of the features is to print the customers order so print is kind of critical.

IF this is not possible is there a way to print from a headless client as we will have a mini server on the stand

Cheers
Gordon

You cannot print directly in a browser, you will not see the printer dialog there. This would be true of a web client where Velocity usually renders a html page and send it back, for the user to use the “print” option of the browser.

What happens in your cae is that velocity doesn’t understand that it is called from a NGClient (it has no knowledge of it) so it “believes” it is handled from a Smart client instead, and the printer dialog is actually called from developer. This will never work on a server.

What you need to do is to generate a PDF, using plugins.VelocityReport.getPDFReport(template, context) to generate the PDF bytes and then send it back to the client using the file plugin for example.

ok thank you understood, I did wonder why the print dialogue was triggered and that makes sense. So in this case the challenge it either to save it and get the server to print it with a script or more normally save it and display the result in a separate tab in the browser.

Many thanks
Gordon

Hi

Despite all the helpful information, I cannot get the “print” to work as expected.

I call getPDFReport with the same template used for preview in smart client. And the same context.
The image-url of the diagram, which I want to print, is valid, if I embed it in a html page, the image of the diagram is displayed correctly.

After generating the pdf, I save it as a file. The PDF looks, as if the content is not rendered: The data is just added inline, no format, no tag resolved, the image url is just text.

Any idea, what is wrong?

Thank you and kind regards
Birgit

When html tags are added as is, it is generally because Velocity treats any text data as text, and transforms <, >, & into their html entities.
To prevent that on specific values, you can use the htmlize helper object, in the template, or use the #h() macro which is a shortcut for it *

Say the context object provided to getPDFReport is something like { img: ‘’ }

You will need to use
$htmlize.get($img) or $htmlize[$img]
or
#h($img)
in your template to render it as true html.

* Note that the definition for that macro is in the VM_global_library.vm file provided with the Velocity plugin, this file should be placed at the root of the reports folder you are pointing to with velocityreport.reportFolder.

Dear Patrick

That was the trick! htmlize solved it, the chart is displayed as expected.
Thank you so much! After spending hours and hours that was a 1 minute task now.

Best regards
Birgit

Hi

On Servoy 2024.3 with Velocity v3.7.8 I find $htmlize in the template raising an exception while generating a pdf with getPDFReport():

500: The plugin encountered an internal error and was unable to complete your request...
Exception Message: The reference to entity "cht" must end with the ';' delimiter.

Any idea, how to solve this?

Thank you and regards
Birgit

The problem is that in your data you have the string “&cht”, which the parser tries to interpret as an HTML entity, and fails because 1/ it is not properly closed with a “;” and 2/ because &cht; is not even a known entity…

To fix this, in the data you push in the context object to fill your template, you need to make sure you don’t have any “&” character, meaning you need to replace all occurrences of “&” by the HTML entity “&”.

Dear Patrick

Thank you again, for helping.
Actually, that is, what I already did try. And it did not help.
But maybe I did something wrong, I’ll give it another try.

Best regards
Birgit

Hi Patrick

I do generate the Image with getChart(…). Result is an image string like “”. I did experiment with different character encodings in this string:

  • Original (works in Servoy 2022.06 with Velocity Plugin v3.5.94)
<img src="http://127.0.0.1:8184/eastwood/chart?chbh=r&cht=bvg&chxt=y,x&chs=1000x480&chd=t%3A53.0%7C20. ... &ewr=1" border="0" class="chart" width="1000" height="480"></img>

Exception Message: The reference to entity “cht” must end with the ‘;’ delimiter. org.xml.sax.SAXParseException; lineNumber: 37; columnNumber: 66; The reference to entity “cht” must end with the ‘;’ delimiter.

  • Encode the image string with encodeURI()
%3Cimg%20src=%22http://127.0.0.1:8184/eastwood/chart?chbh=r&cht=bvg&chxt=y,x&chs=1000x480&chd=t%253A53.0%2...&ewr=1%22%20border=%220%22%20class=%22chart%22%20width=%221000%22%20height=%22480%22%3E%3C/img%3E

Same exception

  • Replace & with &
<img src="http://127.0.0.1:8184/eastwood/chart?chbh=r&cht=bvg&chxt=y,x&chs=1000x480&chd=t%3A53.0%7C20.0%7C25.0%7C8.0% ... &ewr=1" border="0" class="chart" width="1000" height="480"></img>

Same exception

  • Replace & with %26
<img src="http://127.0.0.1:8184/eastwood/chart?chbh=r%26cht=bvg%26chxt=y,x%26chs=1000x480%26chd=t%3A53.0%7C20.0%7C25.0%7C8.0%7C6 ... %26ewr=1" border="0" class="chart" width="1000" height="480"></img>

No exception but no chart in PDF.

In the template I use $htmlize.get($myChart) to render the image.
Any idea how I can generate the pdf with the chart?

Best regards
Birgit

I did a quick test with the latest Velocity plugin, and it worked fine.

Now, I didn’t know the html containing the offending tag was actually generated by getChart(). If eastwood is returning an image, you don’t even have to use $htmlize() or try to replace any characters. Just place the variable in your template and it should work (in my template below: $!pieChart). This is because the PDF will be produced AFTER the image was retrieved and has been embedded, so no $ character should be in the html…

So my guess is that the image was not found, and couldn’t replace the img tag, which means you probably don’t have the eastwood.war installed.

FYI. the template I tested was:

<html><body style="width: 100%; height: 100%;">$!pieChart</body></html>

The chart object definition was:

{"width":400,"height":280,"title":"Title","titleSize":18,"threeD":true,"shadow":false,"proportional":true,"labelFontSize":10,"slices":[{"percent":29.5,"color":"#FF0000","label":"Thirty","legend":"Thirty"},{"percent":25,"color":"#00FF00","label":"Twenty-Five","legend":"Twenty-Five"},{"percent":15.5,"color":"#0000FF","label":"Fifteen","legend":"Fifteen"},{"percent":10.2,"color":"#FF00FF","label":"Five","legend":"Five"},{"percent":19.8,"color":"#00FFFF","label":"Twenty","legend":"Twenty"}],"orientation":45,"transparency":100}

The html rendered for the PDF was:

<html><body style="width: 100%; height: 100%;"><img src="http://localhost:8183/eastwood/chart?cht=p3&chp=45.0&chtt=Title&chs=400x280&chts=000000,18&chd=e%3AS4QAJ7GiMr&chco=FF0000,00FF00,0000FF,FF00FF,00FFFF&chl=Thirty%7CTwenty-Five%7CFifteen%7CFive%7CTwenty&chdl=Thirty%7CTwenty-Five%7CFifteen%7CFive%7CTwenty&lfs=10&xp=1&ewr=1" border="0" class="chart" width="400" height="280"></img></body></html>

See the attached PDF for the result.

So my guess is that you don’t have eastwood.war installed. You need to put it in /application_server/server/webapps/
You can test it by opening a browser and testing the URL produced by the object returned by getChart() (in your case “http://127.0.0.1:8184/eastwood/chart?chbh=r&cht=bvg&chxt=y.etc.”)

test.pdf (11.3 KB)

Hi Patrick

I did try to enter the image in an html file before. Works fine.
I attach now

  • an x.html file which includes the image tag and string generated with getChart(). And it includes a variable for the chart passed in getPDFReport().
  • The resulting pdf. The image is visible, Eastwood is running, though. The image tag is not rendered. With htmlize I receive the error.

What is wrong here? I don’t see it.

Regards
Birgit

Archive.zip (13.6 KB)

I have tried with v3.5.94 and it works.

Can you try updating your eastwood.war? You can find the latest here: https://www.servoyforge.net/attachments/download/2498/eastwood.war

Also what is the definition of your boxPlotChart1 variable?
I noticed that the img tag in the x.html file is not the same as what is seen in the pdf (which is your $boxPlotChart1).
Could you share the code for that variable?

Dear Patrick

Solved!!!

  • New war did not make any difference.
  • htmlize still raises an exception → removed
  • What made the difference, was the type of the chart variable in my code. It was a String before and must be of type net.stuff.servoy.plugin.velocityreport.charts.ChartWrapper.

Unbelievable, it was a type thing
Thank you for sticking with it!
Best regards
Birgit

Glad to know you solved it!

It makes sense though, because Velocity will use the ChartWrapper object methods to embed the image in the pdf, but if it’s a String it will render it as String, and will not process it further… And then if the String rendered contains & characters which are not HTML entities, the xml parser will not accept it and you get these exceptions.

Dear Patrick

Thank you for the response and the explanation of the data type consequence.

It helped, that you asked for the code. I did put the code pieces together (SQL query, chart definition, chart and printing), which were split into functions. Before sending the whole code to you, I tested it and noticed, that it worked. Because the chart variable was no longer a form variable of type string.

I’m so glad, it finally works, after so many hours searching. Thanks again and regards
Birgit

I remember something similar happening in a client code:
There was a form variable that had been annotated with /** @type {String} */, then later used in a function, where it was assigned a number and used in a calculation.
The result was not as expected even though both values were numbers, it was instead a concatenated String.

Something like this:

/** @type {String} */
var frm_var = null;

function aFunction() {
    frm_var = 10; // <- here Servoy cast it to a String and assigned frm_var to "10"
    ...
    var total = frm_var + 50; // <- here total was assigned "1050", not 60
}

So my advice is to be very consistent with types.
And be aware that if a variable is annotated as String some automatic casting will be done (basically a call to .toString() on the java value).

Dear Patrick

Thank you, an interesting example. With surprising effects!
It’s just difficult to come up with the idea of a type problem, when code has worked for years.
I hope, I remember next time ;-)

Best regards
Birgit