Expand my Community achievements bar.

Debugging Server Side JavaScript

Avatar

Employee

It is important to understand that Adobe uses open source Rhino to convert JavaScript into Java. Therefore all the regular Java libraries are available to Server Side JavaScript simply be using the class path in your JavaScript. However, Server Side JavaScript is slower than using Java. It is best to use Server Side JavaScript if components will be cached in the dispatcher.

In order to enable the server side debugging for Rhino, open the sling.properties file in crx-quickstart/conf and set the org.apache.sling.scripting.javascript.debug to true.

This will open up a Swing window for Rhino and you should be able to debug your code using breakpoints etc.

Let us know if you need further information.

Thank you

3 Replies

Avatar

Level 1

This works great on pages having a page component which includes JS with data-sly-use.

But on pages including some other components or assets (e.g. a simple Image) with

<div data-sly-resource="${@path='par1', resourceType='wcm/foundation/components/parsys'}">d1</div>

I always get some errors like:

Error Message:

org.apache.sling.scripting.sightly.SightlyException: org.mozilla.javascript.EcmaError: ReferenceError: "granite" is not defined. (/libs/wcm/foundation/components/page/head.html#40)

Those pages are working fine with "debug=false"

Any idea how to solve this problem?

Avatar

Employee

Hello,

The way I debug such code is simply by logging, for e.g. with log.error("message").


Usually, the server JS should be quite straight-forward and therefore not too much of a problem if breakpointing isn't possible, but Rhino has one trick that is important to know:


one must not use strict comparison, because the Java APIs will return variables that have types that won't strictly match the JS primary types.

For e.g. if you have a boolean JCR property you should do:

var isCompleted = properties.get('completed') == true;

Instead of:

var isCompleted = properties.get('completed') === true;


Also, unlike some of the foundation components and Geometrixx reference code, don't use the asynchronous APIs that need complex promises, but use the much more straightforward Java APIs instead. This means that you should avoid all JS methods that are located in the wcm or in the granite namespaces, and instead use the same APIs as you'd use in JSPs, because the exact same variables are available in JS as are in JSP after including the global.jsp.

For e.g. do:

var parent = currentPage.getParent(level);

Instead of:

wcm.currentPage.getParent(0, function(parent) { /* ... */ });


There are two annoying bugs that constitute an exception to that, depending on the version of AEM you're using: the resourceResolver variable might be missing and resource.listChildren might not work. The workaround is to access the resourceResolver through resource.resourceResolver, and to use the listChildren method of resourceResolver instead:

var children = resource.resourceResolver.listChildren(resource);


Also, if from JS you use these synchronous Java APIs, then you also don't suffer much performance loss compared to JSP/Java as the current Geometrixx Outdoors implementation has with the promises. Still, I'd recommend any larger pieces of logic to be implemented in Java, which can then still be tweaked in JS to the specific needs of the template:

var myService = sling.getService(Packages.com.my.class.name);



Avatar

Level 2

Is there a way to debug this javascript server side code on IntelliJ or Eclipse?