Mato Mato - 5 months ago 85
Javascript Question

Working with promises in J2V8

Im trying to use the inline-css NPM package in a Java project through J2V8 to inline stylesheets into style attributes.

final NodeJS nodeJS = NodeJS.createNodeJS();
final V8Object inlineCss = nodeJS.require(new File(
final V8 jsRuntime = nodeJS.getRuntime();

final Map<String, Object> inlineOptions = new HashMap<>();
inlineOptions.put("applyLinkTags", false);
inlineOptions.put("removeStyleTags", false);
inlineOptions.put("url", "");

jsRuntime.add("inlineCss", inlineCss);
jsRuntime.add("inlineOptions", V8ObjectUtils.toV8Object(jsRuntime, inlineOptions));

try (FileInputStream inputStream = new FileInputStream(pageFile)) {
byte[] data = new byte[(int) pageFile.length()];;

String pageContent = new String(data, "UTF-8");

JavaVoidCallback successCallback = new JavaVoidCallback() {
public void invoke(V8Object v8Object, V8Array v8Array) {

JavaVoidCallback errorCallback = new JavaVoidCallback() {
public void invoke(V8Object v8Object, V8Array v8Array) {

jsRuntime.add("pageContent", pageContent);
jsRuntime.registerJavaMethod(successCallback, "onSuccess");
jsRuntime.registerJavaMethod(errorCallback, "onError");

jsRuntime.executeObjectScript("inlineCss(pageContent, inlineOptions).then(onSuccess).catch(onError)");
} catch (IOException | V8ScriptExecutionException | V8ScriptCompilationException e) {

But neither the success nor the error callback gets invoked and no error are thrown. I couldn't find any proper documentation for J2V8 and the provided examples are not really helpful here. Has anyone used J2V8 to work with JavaScript promises? Or does someone see an error?

Also, if you know a good Java library to inline CSS that would also be helpful. The ones I came across so far don't really work reliably when you have multiple classes and an id on elements. CSSBox looked like a promising solution but it doesn't seem to handle vendor prefixed rules properly.

An alternative would be the to use a CLI script but that's the last resort for me, since it would mean I also need to deploy NodeJS next to my Java application.


You must pump the Node.js message loop:

while(nodeJS.isRunning()) {

Add this to the bottom of you code and it should work. Also, I noticed that you have onSuccess(c), I think c should be pageContent.