Rendering PDF not working on prod environment - pdf

I have a very strange problem with rendering PDF working everywhere, but not on prod. Developer and test environments are working without problems, but prod just can't handle it. The only changes that are now on prod: higher Grails version than the last war (2.1.0->2.3.8 [but this change has been introduced to the test environment ~2 months ago and all the problems were resolved then]) with few upgraded plugins, especially
compile ":rendering:0.4.3"
changed to
compile ":rendering:1.0.0"
Stacktrace I get on prod:
java.lang.NullPointerException
at org.xhtmlrenderer.swing.NaiveUserAgent.getBinaryResource(NaiveUserAgent.java:228)
at org.xhtmlrenderer.pdf.ITextFontResolver.importFontFaces(ITextFontResolver.java:97)
at org.xhtmlrenderer.pdf.ITextRenderer.setDocument(ITextRenderer.java:178)
at org.xhtmlrenderer.pdf.ITextRenderer.setDocument(ITextRenderer.java:142)
at grails.plugin.rendering.pdf.PdfRenderingService.doRender(PdfRenderingService.groovy:36)
at grails.plugin.rendering.RenderingService.render(RenderingService.groovy:43)
at grails.plugin.rendering.RenderingService.render(RenderingService.groovy:37)
at grails.plugin.rendering.RenderingService.render(RenderingService.groovy:35)
at grails.plugin.rendering.RenderingService.render(RenderingService.groovy:65)
at GrailsMelodyGrailsPlugin$_closure4_closure16_closure17.doCall(GrailsMelodyGrailsPlugin.groovy:184)
at RenderingGrailsPlugin$_closure3.doCall(RenderingGrailsPlugin.groovy:59)
at com.my.app.ReportController$_closure8.doCall(ReportController.groovy:169)
at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:200)
at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
at net.bull.javamelody.JspWrapper.invoke(JspWrapper.java:150)
at net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler.invoke(JdbcWrapper.java:285)
at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:198)
at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:176)
My ReportController method for generating pdfs (nothing's really happening here and, yes, pdfShow file starts with an underscore):
def generatePdf = {
if (!params.id) {
throw new IllegalArgumentException("PDF Generation: an instance identifier has not been passed.")
}
def reportInstance = Report.findById(params.id)
renderPdf(template: "pdfShow", model: [reportInstance: reportInstance], filename: reportInstance?.reportFilename + '.pdf')
}
I have already done quite some research and found indications that it might be the problem with fonts declared in .css file which is used by the pdf template.
Well, this is the .css:
#font-face {
src: url("../fonts/DejaVuSansCondensed.ttf");
-fs-pdf-font-embed: embed;
-fs-pdf-font-encoding: Identity-H;
}
#font-face {
src: url(../fonts/DejaVuSansCondensed-Bold.ttf);
-fs-pdf-font-embed: embed;
-fs-pdf-font-encoding: Identity-H;
}
body {
font-family: "DejaVu Sans Condensed", Arial, sans-serif;
}
And the fonts are there, both on test and prod. And did not change their location.
I have tried downgrading rendering plugin back to 0.4.3, but it didn't work, complaining about not available classes:
plugins\rendering-0.4.3\grails-app\services\grails\plugin\rendering\document\XhtmlDocumentService.groovy: 20: unable to resolve class org.xhtmlrenderer.resource.XMLResource
(...)\plugin\rendering\pdf\PdfRenderingService.groovy: 25: unable to resolve class com.lowagie.text.pdf.BaseFont
(...)\plugin\rendering\pdf\PdfRenderingService.groovy: 19: unable to resolve class org.xhtmlrenderer.pdf.ITextRenderer
...and few others etc.
setting in the BuildConfig.groovy
legacyResolve true
inside grails.project.dependency.resolution { ... also did not work.
Do you have any idea what could be wrong?

The thing which solved the problem, was adding one line to the Config.groovy:
environments {
production {
(...)
grails.resources.processing.enabled = false
We had this line in the test and development environments, but before, with Grails 2.1.0 it worked anyway.

Related

requirejs loading file from different path

I've a webpage , where I've included the requirejs via script tag like -
<script data-main="/media/course-book-app/courses.require.main.js" src="/media/common/vendor/requirejs/require.js"></script>
On Safari browser, I'm getting error like -
What is causing this issue?
This issue is very frequent on Safari but on chrome it is less frequent.
Testing URL
From https://requirejs.org/docs/errors.html#scripterror (which is linked right there in the error). Follow the instructions and look at the script that caused the error
This occurs when the script.onerror function is triggered in a
browser. This usually means there is a JavaScript syntax error or
other execution problem running the script. To fix it, examine the
script that generated the error in a script debugger.
This error may not show up in IE, just other browsers, and instead, in
IE you may see the No define call for ... error when you see "Script
error". This is due to IE's quirks in detecting script errors.
Here is the way to use requirejs correctly. This ensures the configuration gets loaded before loading any module -
define('requireconfig', function(){
require.config({
paths: {
"jquery": "/common/vendor/jquery/jquery-1.9.1.min",
"backbone": "/common/vendor/backbone/backbone.min-1.1.2",
"underscore": mediaPath + "/common/vendor/underscore/underscore.min-1.7.0"
},
shim: {
backbone : {
deps: ["jquery","underscore"],
exports: "Backbone"
},
}
});
});
define('main', ['requireconfig'], function () {
'use strict';
});
// loading main module which loads the requirejs configuration
requirejs(['main'],()=>{
requirejs(['jquery'], ($)=>{//jquery loaded});
}, ()=>{//error loading module})

Timing of AppVeyor build steps

I'm driving an AppVeyor build with an appveyor.yml file, in this instance an Angular CLI build. This is a part of my file:
test_script:
- npm run lint
- npm test
- npm run e2e
- npm run build
Those are all npm scripts that delegate actual work to the ng cli.
How can I properly get timings for each step? My real build is even a bit bigger, and for starters I'd like to see (preferably as a summary) how long each step took.
I tried adding - ps: Get-Date -Format "o" in between each step, which is a workaround, but not really a nice one.
Can this be done in a more convenient manner?
Since the information is available in the tooltip, why not use CSS? That also works while the build is being updated. This is within my GreaseMonkey script (but I suppose you can also use the Style Editor in dev tools, Stylus or similar):
((css) => {
let style = document.createElement("style");
style.textContent = css;
document.body.appendChild(style);
})(`
/* Stretch the log, do not limit its width */
body > div > div.row {
max-width: initial;
}
/* Prepend mm:ss before every line */
div#job-console > div:before {
visibility: visible;
content: attr(title);
color: gold;
margin-top: 0;
margin-left: -5rem;
margin-right: 4em;
height: auto;
display: inline;
}
`);
I use -5rem such that the hour part is exactly hidden (many tests do not take an hour to run, so provides you three more characters for the actual log message).
The other answer was helpful, because it mentioned that the console output line numbers have a tooltip with timing info. You can use this snippet as a bookmarklet (or paste it in your console) to get a quick overview:
for (let d of document.querySelectorAll('#job-console > div')) {
x = document.createElement('span');
x.innerHTML = d.title;
x.style.marginRight = '2.5rem';
x.style.color = 'yellow';
d.insertBefore(x, d.firstChild);
}
I prefer this over creating a lot of boilerplate inside my steps like the answer or my workaround from the question (even though that would work too, I suppose).
I still hope there will turn out to be a way to do this with just a setting in the .yml file or in AppVeyor itself, but until then this is probably what I'll stick with.
Here's a bookmarklet function you can put straight into the URL of a bookmark in at least Chrome and Firefox:
javascript:(function() { for (let d of document.querySelectorAll('#job-console > div')) { x = document.createElement('span'); x.innerHTML = d.title; x.style.marginRight = '2.5rem'; x.style.color = 'yellow'; d.style.whiteSpace = 'nowrap'; d.insertBefore(x, d.firstChild); } })()
Using advice from this comment:
Verbose:
test_script:
- powershell $sw = [Diagnostics.Stopwatch]::StartNew(); npm run lint; $sw.Stop(); Write-host "Time taken: " $sw.Elapsed.totalseconds
Silent:
test_script:
- powershell (Measure-Command { npm run lint } -Verbose).totalseconds
Few notes:
You might not need it at all because if you hover mouse to the line
number on UI, you will see timestamp (relative to the build start).
Or you can download log and it has all timestamps.
Verbose output takes longer.
I call powershell from cmd mode (not ps), because npm writes
output to stdErr which makes custom PowerShell host on AppVeyor
unhappy (I assume you run Windows, not Linux builds)

Embed font in PDF rendering plugin in Grails

I want to embed 'HelveticaNeueLTCom-BdCn.ttf' in a PDF document. I'm using Grails rendering 0.4.4 Plugin to generate PDF file.
I tried following,
#font-face {
font-family: 'Helvetica';
src: url('${grailsApplication.config.grails.serverURL}/fonts/HelveticaNeueLTCom-BdCn.ttf');
-fs-pdf-font-embed: embed;
-fs-pdf-font-encoding: Identity-H;
}
but it doesn't work.
The font embedding requires the below steps to be followed. This worked for me.
Try and tell me your feedback
The PdfRenderingService class present inside the plugin should be
edited for this font simulation as below.
protected doRender(Map args, Document document, OutputStream outputStream)
{
def renderer = new ITextRenderer()
// add the real font path from the server to be deployed to.
//I have it in the assets folder of my project
def path=servletContext.getRealPath("/")+"assets/HelveticaNeueLTCom-BdCn.ttf"
ITextFontResolver fontResolver=renderer.getFontResolver();
//add the encoding and embedded types to the font
fontResolver.addFont(path,BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
configureRenderer(renderer)
renderer.setDocument(document, args.base)
renderer.layout()
renderer.createPDF(outputStream)
outputStream.close();
}
Add the below code in your template file
#font-face {
font-family: "Helvetica";
src: url("${grailsApplication.config.grails.serverURL}/assets/HelveticaNeueLTCom-BdCn.ttf") format("truetype"),
url("${grailsApplication.config.grails.serverURL}/assets/HelveticaNeueLTCom-BdCn.woff") format("woff"),
url("${grailsApplication.config.grails.serverURL}/assets/HelveticaNeueLTCom-BdCn.svg#HelveticaNeueLTCom-BdCn") format("svg");
-fs-pdf-font-embed: embed;
-fs-pdf-font-encoding: Identity-H;
}
#font-face { src:url(${grailsApplication.config.app.serverUrl}/arialuni.ttf) ; -fs-pdf-font-embed: embed; -fs-pdf-font-encoding: Identity-H; }
This worked for me.
Probably the problem is that you have your url value surrounded by ' instead of ".
The difference between them is that, though in Groovy string literals can be made with both, only the ones surrounded by " create GString, which evaluates statements between ${}
This worked for me
#font-face {
src: url("path/to/KF-Kiran.ttf");
-fs-pdf-font-embed: embed;
-fs-pdf-font-encoding: cp1250;
}
div {
font-family: 'KF-Kiran'; // here give the same name of .ttf file.
}

gulp-less not creating output css

I've been struggling with this for a few hours now. I have the following in my gulpfile:
gulp.task('styles', function() {
gulp.src('C:\\TeamCity\\buildAgent\\work\\5003e8de5901599\\dev\\Content\\css\\less\\dealer-landing.less')
.pipe(less())
.pipe(gulp.dest('C:\\TeamCity\\buildAgent\\work\\5003e8de5901599\\dev\\Content\\css'));
});
I run 'gulp styles' which completes with no errors, but the .css is never created. I tried simply commenting out the middle line as seen below and that works as expected; the less file gets copied to the dest directory:
gulp.task('styles', function() {
gulp.src('C:\\TeamCity\\buildAgent\\work\\5003e8de5901599\\dev\\Content\\css\\less\\dealer-landing.less')
//.pipe(less())
.pipe(gulp.dest('C:\\TeamCity\\buildAgent\\work\\5003e8de5901599\\dev\\Content\\css'));
});
Any idea why gulp-less doesn't generate the css? If I use just less, the file is generated correctly.
I experienced this due to an undefined class in my less file.
I discovered the undefined class through logging.
Gulp may not throw errors unless you explicitly log them. To log, require gulp-util in your gulpfile:
var util = require('gulp-util');
And then add logging:
.pipe(less().on('error', util.log)),
Run gulp style to see the error (possibly an undefined class).
Fix it and your style task should generate the css.

sails.js less livereload with grunt watch not working

I got my less files compiled in css perfectly by grunt and I see result in .tmp/public/styles
So now livereload with grunt-contrib-watch should be made naturally in sails generated project ?
Or do I have to make a special configuration ?
I found that in tasks/pipeline.js file but not sure of what to do.
// CSS files to inject in order
//
// (if you're using LESS with the built-in default config, you'll want
// to change `assets/styles/importer.less` instead.)
var cssFilesToInject = [
'styles/**/*.css'
];
I saw in the file tasks/README.md :
###### `sails lift`
Runs the `default` task (`tasks/register/default.js`).
And in the file default.js we got :
module.exports = function (grunt) {
grunt.registerTask('default', ['compileAssets', 'linkAssets', 'watch']);
};
But watch.js file is missing in the folder...
What should it be ?
Watch does only looking for files that have changed and execute less, sass, injection and so on - but it doesn't make a reload.
You can add this in task/config/watch.js