Skip to content

Commit

Permalink
Fixes #1095 add marker interface for play controllers
Browse files Browse the repository at this point in the history
it would allow users to use custom implementations of base controller

See #1095
  • Loading branch information
asolntsev committed Feb 8, 2017
1 parent 81e92c7 commit 496e9dc
Show file tree
Hide file tree
Showing 13 changed files with 361 additions and 22 deletions.
4 changes: 4 additions & 0 deletions framework/build.xml
Expand Up @@ -290,6 +290,10 @@
<param name="testAppPath" value="${basedir}/../samples-and-tests/yabe"/>
</antcall>

<antcall target="play-test">
<param name="testAppPath" value="${basedir}/../samples-and-tests/nonstatic-app"/>
</antcall>

<antcall target="test-success" />

</target>
Expand Down
33 changes: 17 additions & 16 deletions framework/src/play/mvc/ActionInvoker.java
Expand Up @@ -218,7 +218,7 @@ public static void invoke(Http.Request request, Http.Response response) {
private static void invokeControllerCatchMethods(Throwable throwable) throws Exception {
// @Catch
Object[] args = new Object[] {throwable};
List<Method> catches = Java.findAllAnnotatedMethods(Controller.getControllerClass(), Catch.class);
List<Method> catches = Java.findAllAnnotatedMethods(getControllerClass(), Catch.class);
ControllerInstrumentation.stopActionCall();
for (Method mCatch : catches) {
Class[] exceptions = mCatch.getAnnotation(Catch.class).value();
Expand Down Expand Up @@ -268,7 +268,7 @@ public static Method findActionMethod(String name, Class clazz) {
}

private static void handleBefores(Http.Request request) throws Exception {
List<Method> befores = Java.findAllAnnotatedMethods(Controller.getControllerClass(), Before.class);
List<Method> befores = Java.findAllAnnotatedMethods(getControllerClass(), Before.class);
ControllerInstrumentation.stopActionCall();
for (Method before : befores) {
String[] unless = before.getAnnotation(Before.class).unless();
Expand Down Expand Up @@ -302,7 +302,7 @@ private static void handleBefores(Http.Request request) throws Exception {
}

private static void handleAfters(Http.Request request) throws Exception {
List<Method> afters = Java.findAllAnnotatedMethods(Controller.getControllerClass(), After.class);
List<Method> afters = Java.findAllAnnotatedMethods(getControllerClass(), After.class);
ControllerInstrumentation.stopActionCall();
for (Method after : afters) {
String[] unless = after.getAnnotation(After.class).unless();
Expand Down Expand Up @@ -348,13 +348,13 @@ private static void handleAfters(Http.Request request) throws Exception {
*/
static void handleFinallies(Http.Request request, Throwable caughtException) throws PlayException {

if (Controller.getControllerClass() == null) {
if (getControllerClass() == null) {
// skip it
return;
}

try {
List<Method> allFinally = Java.findAllAnnotatedMethods(Controller.getControllerClass(), Finally.class);
List<Method> allFinally = Java.findAllAnnotatedMethods(Request.current().controllerClass, Finally.class);
ControllerInstrumentation.stopActionCall();
for (Method aFinally : allFinally) {
String[] unless = aFinally.getAnnotation(Finally.class).unless();
Expand Down Expand Up @@ -455,9 +455,7 @@ public static Object invokeControllerMethod(Method method, Object[] forceArgs) t
if (declaringClassName.endsWith("$class")) {
args[0] = scalaInstance; // Scala trait method
} else {
request.controllerInstance = (Controller) scalaInstance; // Scala
// object
// method
request.controllerInstance = (PlayController) scalaInstance; // Scala object method
}
} catch (NoSuchFieldException e) {
// not Scala
Expand Down Expand Up @@ -500,11 +498,11 @@ static Object invoke(Method method, Object instance, Object ... realArgs) throws

static Object invokeWithContinuation(Method method, Object instance, Object[] realArgs) throws Exception {
// Callback case
if (Http.Request.current().args.containsKey(A)) {
if (Request.current().args.containsKey(A)) {

// Action0
instance = Http.Request.current().args.get(A);
Future f = (Future) Http.Request.current().args.get(F);
instance = Request.current().args.get(A);
Future f = (Future) Request.current().args.get(F);
Scope.RenderArgs renderArgs = (Scope.RenderArgs) Request.current().args.remove(ActionInvoker.CONTINUATIONS_STORE_RENDER_ARGS);
Scope.RenderArgs.current.set(renderArgs);
if (f == null) {
Expand All @@ -520,7 +518,7 @@ static Object invokeWithContinuation(Method method, Object instance, Object[] re
}

// Continuations case
Continuation continuation = (Continuation) Http.Request.current().args.get(C);
Continuation continuation = (Continuation) Request.current().args.get(C);
if (continuation == null) {
continuation = new Continuation(new StackRecorder((Runnable) null));
}
Expand All @@ -541,7 +539,7 @@ static Object invokeWithContinuation(Method method, Object instance, Object[] re
}
Object trigger = pStackRecorder.value;
Continuation nextContinuation = new Continuation(pStackRecorder);
Http.Request.current().args.put(C, nextContinuation);
Request.current().args.put(C, nextContinuation);

if (trigger instanceof Long) {
throw new Suspend((Long) trigger);
Expand All @@ -555,7 +553,7 @@ static Object invokeWithContinuation(Method method, Object instance, Object[] re

throw new UnexpectedException("Unexpected continuation trigger -> " + trigger);
} else {
Http.Request.current().args.remove(C);
Request.current().args.remove(C);
}
} finally {
pStackRecorder.deregisterThread(old);
Expand All @@ -577,10 +575,10 @@ public static Object[] getActionMethod(String fullAction) {
if (controllerClass == null) {
throw new ActionNotFoundException(fullAction, new Exception("Controller " + controller + " not found"));
}
if (!ControllerSupport.class.isAssignableFrom(controllerClass)) {
if (!PlayController.class.isAssignableFrom(controllerClass)) {
// Try the scala way
controllerClass = Play.classloader.getClassIgnoreCase(controller + "$");
if (!ControllerSupport.class.isAssignableFrom(controllerClass)) {
if (!PlayController.class.isAssignableFrom(controllerClass)) {
throw new ActionNotFoundException(fullAction,
new Exception("class " + controller + " does not extend play.mvc.Controller"));
}
Expand Down Expand Up @@ -636,4 +634,7 @@ public static Object[] getActionMethodArgs(Method method, Object o) throws Excep
return rArgs;
}

private static Class<? extends PlayController> getControllerClass() {
return Http.Request.current().controllerClass;
}
}
8 changes: 4 additions & 4 deletions framework/src/play/mvc/Controller.java
Expand Up @@ -69,10 +69,9 @@
* Application controller support: The controller receives input and initiates a
* response by making calls on model objects.
*
* This is the class that your controllers should extend.
*
* This is the class that your controllers should extend in most cases.
*/
public class Controller implements ControllerSupport, LocalVariablesSupport {
public class Controller implements PlayController, ControllerSupport, LocalVariablesSupport {

/**
* The current HTTP request: the message sent by the client to the server.
Expand Down Expand Up @@ -963,8 +962,9 @@ protected static <T extends Annotation> T getControllerInheritedAnnotation(Class
*
* @return Annotation object or null if not found
*/
@SuppressWarnings("unchecked")
protected static Class<? extends Controller> getControllerClass() {
return Http.Request.current().controllerClass;
return (Class<? extends Controller>) Http.Request.current().controllerClass;
}

/**
Expand Down
4 changes: 2 additions & 2 deletions framework/src/play/mvc/Http.java
Expand Up @@ -265,11 +265,11 @@ public static class Request implements Serializable {
/**
* The invoked controller class
*/
public transient Class<? extends Controller> controllerClass;
public transient Class<? extends PlayController> controllerClass;
/**
* The instance of invoked controller in case it uses non-static action methods.
*/
public transient Controller controllerInstance;
public transient PlayController controllerInstance;
/**
* Free space to store your request specific data
*/
Expand Down
10 changes: 10 additions & 0 deletions framework/src/play/mvc/PlayController.java
@@ -0,0 +1,10 @@
package play.mvc;

/**
* Marker interface for play controllers
*
* This is the class that your controllers should implement.
* In most cases, you can extend play.mvc.Controller that contains all needed methods for controllers.
*/
public interface PlayController {
}
23 changes: 23 additions & 0 deletions samples-and-tests/nonstatic-app/app/controllers/Application.java
@@ -0,0 +1,23 @@
package controllers;

import play.mvc.PlayController;
import play.mvc.results.RenderTemplate;
import play.mvc.results.RenderText;
import play.mvc.results.Result;
import play.templates.Template;
import play.templates.TemplateLoader;

import static java.util.Collections.emptyMap;

public class Application implements PlayController {

public Result index() {
Template template = TemplateLoader.load("Application/index.html");
return new RenderTemplate(template, emptyMap());
}

public Result hello() {
return new RenderText("Hello world!");
}

}
@@ -0,0 +1,4 @@
#{extends 'main.html' /}
#{set title:'Home' /}

<h2>Welcome to the non-static world!</h2>
13 changes: 13 additions & 0 deletions samples-and-tests/nonstatic-app/app/views/main.html
@@ -0,0 +1,13 @@
<!DOCTYPE html>

<html>
<head>
<title>#{get 'title' /}</title>
<meta charset="${_response_encoding}">
#{get 'moreStyles' /}
</head>
<body>
#{doLayout /}
#{get 'moreScripts' /}
</body>
</html>

0 comments on commit 496e9dc

Please sign in to comment.