#2170 new
santos

Action context access from error templates

Reported by santos | April 29th, 2018 @ 02:30 PM

FRAMEWORK VERSION

1.5.1

PLATFORM

Ubuntu 16.04.4 LTS, Java 1.8.0_171-b11

DESCRIPTION

In previous Play 1 versions (e.g. 1.2.1), it was possible to access action context items such as

${session}
${session?.id}
${controllers.Security.isConnected()}
${controllers.Security.connected()}

from within error templates i.e. templates associated with HTTP errors (e.g. 404, 500). This was pretty handy as it allowed for error handling operations to be performed. For example, session and user identifiers could be logged/e-mailed (making it easier to trace and follow up errors) and error page layouts could be adjusted depending on whether the user was logged in or not. Unfortunately, this isn't possible anymore: even if there is a session cookie, the implicit session object is not available to error templates (it is null) and calling controllers.Security.isConnected()/connected() from an error template results in a NPE which in turn causes an HTTP 500 error to be returned.

The fix itself is not too complicated. Please see TECHNICAL DETAILS below.

REPRODUCTION STEPS

  1. Create a brand new Play! 1.5.1 app

  2. Add the secure module dependency (play -> secure) in conf/dependencies.yml and execute play dependencies

  3. Include the following code in app/views/Application/index.html and app/views/errors/404.html:

<p>isConnected: ${controllers.Security.isConnected()}</p>
<p>Connected: ${controllers.Security.connected()}</p>
  1. Start the app

  2. Open a browser at the root URL (e.g. http://localhost:9000)

  3. The returned page successfully displays isConnected/Connected

  4. Point the browser to an unavailable URL (e.g. http://localhost:9000/notfound)

  5. An HTTP 500 is returned and logs show a NPE:

Execution exception (In {module:secure}/app/controllers/Secure.java around line 167)
NullPointerException occurred : null

play.exceptions.JavaExecutionException
    at play.templates.BaseTemplate.throwException(BaseTemplate.java:87)
    at play.templates.GroovyTemplate.internalRender(GroovyTemplate.java:307)
    at play.templates.Template.render(Template.java:28)
    at play.templates.GroovyTemplate.render(GroovyTemplate.java:230)
    at play.server.PlayHandler.serve404(PlayHandler.java:696)
    at Invocation.HTTP Request(Play!)

TECHNICAL DETAILS

There seems to be 2 phases when handling a request:

  1. Phase 1 - Resolving the request to a controller
  2. Phase 2 - Invoking the controller

This logic is available in class play.mvc.ActionInvoker. Earlier (at least in Play! 1.2.1), method resolve (Phase 1) started with setting the action context and therefore making it available to any templates:

@SuppressWarnings("unchecked")
public static void resolve(Http.Request request, Http.Response response) {

  if (!Play.started) {
    return;
  }

  Http.Request.current.set(request);
  Http.Response.current.set(response);

  Scope.Params.current.set(request.params);
  Scope.RenderArgs.current.set(new Scope.RenderArgs());
  Scope.RouteArgs.current.set(new Scope.RouteArgs());
  Scope.Session.current.set(Scope.Session.restore());
  Scope.Flash.current.set(Scope.Flash.restore());

  ControllersEnhancer.currentAction.set(new Stack<String>());
    ...

Now (at least in Play! 1.5.0 and 1.5.1), a similar code block can be found in method initActionContext. This method is called by invoke (Phase 2), not by resolve (Phase 1). This means that if the resolution phase fails (e.g. upon HTTP 404) the action context is not set and therefore is not made available to error templates.

The fix consists in restoring the previously available behaviour by calling the action context initialisation code during the resolution phase, so that any (non-error or error) template can have access to action context items.

No comments found

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

<h2>Play framework</h2>

Play makes it easier to build Web applications with Java. It is a clean alternative to bloated Enterprise Java stacks. It focuses on developer productivity and targets RESTful architectures. Learn more on the <a href="http://www.playframework.org">http://www.playframework.org</a> website.<br><br>

<h2>Source code is hosted on github</h2>Check out our repository at <a href="http://github.com/playframework/play">http://github.com/playframework/play</a><br><br>

<h2>Contributing, creating a patch</h2> Please read the <a href="http://play.lighthouseapp.com/projects/57987/contributor-guide">contributor guide</a><br><br>

<h2>Reporting Security Vulnerabilities</h2> Since all bug reports are public, please report any security vulnerability directly to <em>guillaume dot bort at gmail dot com</em>.<br><br>

<h2>Creating a bug report</h2> Bug reports are incredibly helpful, so take time to report bugs and request features in our ticket tracker. We’re always grateful for patches to Play’s code. Indeed, bug reports with attached patches will get fixed far quickly than those without any.<br><br>

Please include as much relevant information as possible including the exact framework version you're using and a code snippet that reproduces the problem.<br><br>

Don't have too much expectations. Unless the bug is really a serious "everything is broken" thing, you're creating a ticket to start a discussion. Having a patch (or a branch on Github we can pull from) is better, but then again we'll only pull high quality branches that make sense to be in the core of Play.

Referenced by

Pages