Absolute URL in jobs

Enonic version: 6.10.3
OS: Docker

Hi !

I’m trying to build URL for email newsletter. My code looks like this :

  • libs.portal.pageUrl({ id: object._id, type: ‘absolute’ })

And in logs I found this error:

at com.enonic.xp.portal.impl.url.PortalUrlBuilder.getBaseUri(PortalUrlBuilder.java:41) ~[na:na]
at com.enonic.xp.portal.impl.url.PortalUrlBuilder.buildErrorUrl(PortalUrlBuilder.java:199) ~[na:na]
at com.enonic.xp.portal.impl.url.PortalUrlBuilder.buildErrorUrl(PortalUrlBuilder.java:192) ~[na:na]
at com.enonic.xp.portal.impl.url.PortalUrlBuilder.build(PortalUrlBuilder.java:136) ~[na:na]
at com.enonic.xp.portal.impl.url.PortalUrlServiceImpl.lambda$build$0(PortalUrlServiceImpl.java:106) ~[na:na]
at com.enonic.xp.context.ContextImpl.callWith(ContextImpl.java:101) ~[core-api-6.10.3.jar:6.10.3]
at com.enonic.xp.portal.impl.url.PortalUrlServiceImpl.runWithAdminRole(PortalUrlServiceImpl.java:137) ~[na:na]
at com.enonic.xp.portal.impl.url.PortalUrlServiceImpl.build(PortalUrlServiceImpl.java:106) ~[na:na]
at com.enonic.xp.portal.impl.url.PortalUrlServiceImpl.pageUrl(PortalUrlServiceImpl.java:53) ~[na:na]
at com.enonic.xp.lib.portal.url.PageUrlHandler.buildUrl(PageUrlHandler.java:14) ~[na:na]
at com.enonic.xp.lib.portal.url.AbstractUrlHandler.createUrl(AbstractUrlHandler.java:32) ~[na:na]
at com.enonic.xp.lib.portal.url.AbstractUrlHandler.createUrl(AbstractUrlHandler.java:26) ~[na:na]
at jdk.nashorn.internal.scripts.Script$Recompilation$874$4456A$portal.L:1#pageUrl(com.company.site:/site/lib/xp/portal.js:106) ~[na:na]

All operations are running in “admin” context.
Is there any option to get absolute object URL in job ?

Thanks !


Is this job a task launched using task-lib or from app-cronjob?
What do you mean that all operations are running in admin context?

It is not possible to generate URLs from outside a controller that is executed in the context of an HTTP request.
In general all the functions in portal-lib may only be executed from an HTTP controller. This is because the system doesn’t know which vhost to apply in the URL generation.

What you could do is have a configurable base URL and concatenate the content path.
If you do this, it is recommended to put the URL in a configuration file, not hard-coded. So you can use different URLs for different environments (dev, qa, prod).

var baseUrl = app.config['base.url'];
var pageUrl = baseUrl + object._path;

In XP_HOME/config/com.your.app.cfg:

See app configuration here.


To the base URL well explained by aro, you concatenate the path of the content but with the site path removed from the beginning

function pageUrl(object) {
  var baseUrl = app.config['base.url'];
  var site = contentLib.site({key: object._id});
  if (site) {
    return baseUrl + object._path.substring(site._path.length);
  return null;
1 Like

Hi aro and gri !

Thank you very much. I was able to make it work with app config. However looks like it’s not possible to use portal functions at all. For example I can use portal.localize in email template. Do you know if we have workaround ?

Thanks !

The localize function needs:

  • an application, to find the resource bundles (site/i18n/phrases*.properties)
  • a locale or language code, which it takes from the language configured on the site

Both of these are obtained from the current HTTP request.
So currently portal.localize won’t work when called from a template that is rendered from main.js, or from a background task.

I think to make it work in this case we would have to add optional parameters: an application-key and a site path or locale code (“en_US”).

How did you want to use localize from the job? How did you expect to indicate the language?

Hmm. Aren’t tasks also running in a context i.e. the code comes from a specific application? Also, there is a parameter to set language for the localize function i.e. if you want to override the contextual language.

Tasks are not running with an HTTP request in context. And the localize function expects the PortalRequest object in the current context.
Yes, the locale can be overridden with a parameter, but the function will still fail because it expects the PortalRequest in the context.
It can be improved, but at this moment it does not work outside an HTTP request.

Hi !

Unfortunately it doesn’t work in cronjob. This is not a bit problem, because I can send language and use plain if else.

Thanks :slight_smile: