Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1197 support non-static dependencies #1198

Merged
merged 2 commits into from
Aug 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions framework/src/play/inject/DefaultBeanSource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package play.inject;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class DefaultBeanSource implements BeanSource {
@Override
public <T> T getBeanOfType(Class<T> clazz) {
try {
Constructor<T> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
return constructor.newInstance();
} catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
throw new RuntimeException("Cannot instantiate " + clazz, e);
}
}
}
18 changes: 18 additions & 0 deletions framework/src/play/inject/Injector.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@

public class Injector {

private static BeanSource beanSource = new DefaultBeanSource();

public static void setBeanSource(BeanSource beanSource) {
Injector.beanSource = beanSource;
}

public static <T> T getBeanOfType(String className) {
try {
return getBeanOfType((Class<T>) Class.forName(className));
} catch (ClassNotFoundException e) {
throw new RuntimeException("Cannot instantiate " + className, e);
}
}

public static <T> T getBeanOfType(Class<T> clazz) {
return beanSource.getBeanOfType(clazz);
}

/**
* For now, inject beans in controllers and any classes that include @RequireInjection.
*
Expand Down
31 changes: 15 additions & 16 deletions framework/src/play/jobs/JobsPlugin.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
package play.jobs;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import play.Logger;
import play.Play;
import play.PlayPlugin;
import play.exceptions.PlayException;
import play.exceptions.UnexpectedException;
import play.inject.Injector;
import play.libs.CronExpression;
import play.libs.Expression;
import play.libs.Time;
import play.mvc.Http.Request;
import play.utils.Java;
import play.utils.PThreadFactory;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.*;

public class JobsPlugin extends PlayPlugin {

public static ScheduledThreadPoolExecutor executor;
Expand Down Expand Up @@ -158,7 +154,7 @@ public void afterApplicationStart() {
if (clazz.isAnnotationPresent(Every.class)) {
try {
Job job = createJob(clazz);
String value = job.getClass().getAnnotation(Every.class).value();
String value = clazz.getAnnotation(Every.class).value();
if (value.startsWith("cron.")) {
value = Play.configuration.getProperty(value);
}
Expand All @@ -174,7 +170,10 @@ public void afterApplicationStart() {
}

private Job<?> createJob(Class<?> clazz) throws InstantiationException, IllegalAccessException {
Job<?> job = (Job<?>) clazz.newInstance();
Job<?> job = (Job<?>) Injector.getBeanOfType(clazz);
if (!job.getClass().equals(clazz)) {
throw new RuntimeException("Enhanced job are not allowed: " + clazz.getName() + " vs. " + job.getClass().getName());
}
scheduledJobs.add(job);
return job;
}
Expand Down
5 changes: 3 additions & 2 deletions framework/src/play/mvc/ActionInvoker.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import play.exceptions.JavaExecutionException;
import play.exceptions.PlayException;
import play.exceptions.UnexpectedException;
import play.inject.Injector;
import play.mvc.Http.Request;
import play.mvc.Router.Route;
import play.mvc.results.NoResult;
Expand Down Expand Up @@ -445,7 +446,7 @@ public static Object invokeControllerMethod(Method method, Object[] forceArgs) t
Http.Request request = Http.Request.current();

if (!isStatic && request.controllerInstance == null) {
request.controllerInstance = request.controllerClass.newInstance();
request.controllerInstance = Injector.getBeanOfType(request.controllerClass);
}

Object[] args = forceArgs != null ? forceArgs : getActionMethodArgs(method, request.controllerInstance);
Expand All @@ -465,7 +466,7 @@ public static Object invokeControllerMethod(Method method, Object[] forceArgs) t

Object methodClassInstance = isStatic ? null :
(method.getDeclaringClass().isAssignableFrom(request.controllerClass)) ? request.controllerInstance :
method.getDeclaringClass().newInstance();
Injector.getBeanOfType(method.getDeclaringClass());

return invoke(method, methodClassInstance, args);
}
Expand Down
8 changes: 6 additions & 2 deletions framework/src/play/mvc/Scope.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import play.data.validation.Validation;
import play.exceptions.UnexpectedException;
import play.i18n.Messages;
import play.inject.Injector;
import play.libs.Codec;
import play.libs.Crypto;
import play.utils.Utils;
Expand All @@ -36,10 +37,13 @@ public class Scope {

private static SessionStore createSessionStore() {
String sessionStoreClass = Play.configuration.getProperty("application.session.storeClass");
if (sessionStoreClass == null) return new CookieSessionStore();
if (sessionStoreClass == null) {
return Injector.getBeanOfType(CookieSessionStore.class);
}

try {
Logger.info("Storing sessions using " + sessionStoreClass);
return (SessionStore) Class.forName(sessionStoreClass).newInstance();
return (SessionStore) Injector.getBeanOfType(sessionStoreClass);
}
catch (Exception e) {
throw new UnexpectedException("Cannot create instance of " + sessionStoreClass, e);
Expand Down
20 changes: 4 additions & 16 deletions framework/src/play/plugins/PluginCollection.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import play.data.binding.RootParamNode;
import play.db.Model;
import play.exceptions.UnexpectedException;
import play.inject.Injector;
import play.libs.F;
import play.mvc.Http;
import play.mvc.Router;
Expand Down Expand Up @@ -165,7 +166,7 @@ public void loadPlugins() {
for (LoadingPluginInfo info : pluginsToLoad) {
Logger.trace("Loading plugin %s", info.name);
try {
PlayPlugin plugin = (PlayPlugin) Play.classloader.loadClass(info.name).newInstance();
PlayPlugin plugin = (PlayPlugin) Injector.getBeanOfType(Play.classloader.loadClass(info.name));
plugin.index = info.index;
if (addPlugin(plugin)) {
Logger.trace("Plugin %s loaded", plugin);
Expand Down Expand Up @@ -220,21 +221,8 @@ public void reloadApplicationPlugins() throws Exception {
// Is this plugin an application-supplied-plugin?
if (isLoadedByApplicationClassloader(plugin)) {
// This plugin is application-supplied - Must reload it
String pluginClassName = plugin.getClass().getName();
Class pluginClazz = Play.classloader.loadClass(pluginClassName);

// First look for constructors the old way
Constructor<?>[] constructors = pluginClazz.getConstructors();

if (constructors.length == 0) {
// No constructors in plugin
// using getDeclaredConstructors() instead of
// getConstructors() to make it work for plugins without
// constructor
constructors = pluginClazz.getDeclaredConstructors();
}

PlayPlugin newPlugin = (PlayPlugin) constructors[0].newInstance();
Class pluginClazz = Play.classloader.loadClass(plugin.getClass().getName());
PlayPlugin newPlugin = (PlayPlugin) Injector.getBeanOfType(pluginClazz);
newPlugin.index = plugin.index;
// Replace this plugin
replacePlugin(plugin, newPlugin);
Expand Down
3 changes: 3 additions & 0 deletions samples-and-tests/nonstatic-app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
lib
modules
tmp
23 changes: 0 additions & 23 deletions samples-and-tests/nonstatic-app/app/controllers/Application.java

This file was deleted.

9 changes: 9 additions & 0 deletions samples-and-tests/nonstatic-app/app/controllers/Module.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package controllers;

import com.google.inject.AbstractModule;

public class Module extends AbstractModule {
@Override
protected void configure() {
}
}
19 changes: 19 additions & 0 deletions samples-and-tests/nonstatic-app/app/jobs/CounterUpdaterJob.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package jobs;

import play.jobs.Every;
import play.jobs.Job;
import play.jobs.On;
import services.Counter;

import javax.inject.Inject;

@Every("1s")
public class CounterUpdaterJob extends Job<Void> {
@Inject
private Counter counter;

@Override
public void doJob() {
counter.inc("counter.job.every");
}
}
19 changes: 19 additions & 0 deletions samples-and-tests/nonstatic-app/app/jobs/CounterUpdaterJob2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package jobs;

import play.jobs.Every;
import play.jobs.Job;
import play.jobs.OnApplicationStart;
import services.Counter;

import javax.inject.Inject;

@OnApplicationStart
public class CounterUpdaterJob2 extends Job<Void> {
@Inject
private Counter counter;

@Override
public void doJob() {
counter.inc("counter.job.onApplicationStart");
}
}
19 changes: 19 additions & 0 deletions samples-and-tests/nonstatic-app/app/jobs/CounterUpdaterJob3.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package jobs;

import play.jobs.Job;
import play.jobs.On;
import play.jobs.OnApplicationStart;
import services.Counter;

import javax.inject.Inject;

@On("cron.counterUpdater")
public class CounterUpdaterJob3 extends Job<Void> {
@Inject
private Counter counter;

@Override
public void doJob() {
counter.inc("counter.job.on");
}
}
23 changes: 23 additions & 0 deletions samples-and-tests/nonstatic-app/app/plugins/DebugPlugin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package plugins;

import play.PlayPlugin;
import play.mvc.Http;
import play.mvc.Scope;
import services.Mathematics;

import javax.inject.Inject;
import java.lang.reflect.Method;
import java.math.BigDecimal;

public class DebugPlugin extends PlayPlugin {
@Inject private Mathematics mathematics;

@Override
public void beforeActionInvocation(Method actionMethod) {
Scope.RenderArgs renderArgs = Scope.RenderArgs.current();
Http.Request request = Http.Request.current();
renderArgs.put("actionName", request.action);
renderArgs.put("actionMethod", actionMethod.getName());
renderArgs.put("math", ": SQRT(2)=" + mathematics.sqrt(new BigDecimal(2)));
}
}
19 changes: 19 additions & 0 deletions samples-and-tests/nonstatic-app/app/services/Counter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package services;

import javax.inject.Singleton;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

@Singleton
public class Counter {
private final Map<String, AtomicLong> namedCounters = new HashMap<>();

public void inc(String name) {
namedCounters.computeIfAbsent(name, k -> new AtomicLong()).incrementAndGet();
}

public long get(String name) {
return namedCounters.get(name).get();
}
}
11 changes: 11 additions & 0 deletions samples-and-tests/nonstatic-app/app/services/Mathematics.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package services;

import javax.inject.Singleton;
import java.math.BigDecimal;

@Singleton
public class Mathematics {
public BigDecimal sqrt(BigDecimal number) {
return new BigDecimal(Math.sqrt(number.doubleValue()));
}
}

This file was deleted.

1 change: 1 addition & 0 deletions samples-and-tests/nonstatic-app/conf/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,4 @@ mail.smtp=mock
%test.jpa.ddl=create
%test.mail.smtp=mock

cron.counterUpdater=*/2 * * * * ?
9 changes: 9 additions & 0 deletions samples-and-tests/nonstatic-app/conf/dependencies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,12 @@

require:
- play
- play-codeborne -> guice 1.9
- com.google.guava -> guava 23.0

repositories:
- codeborne:
type: http
artifact: https://repo.codeborne.com/play-[module]/[module]-[revision].zip
contains:
- play-codeborne -> *
2 changes: 2 additions & 0 deletions samples-and-tests/nonstatic-app/conf/play.plugins
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
500:plugins.DebugPlugin
1000:play.modules.guice.GuicePlugin
4 changes: 2 additions & 2 deletions samples-and-tests/nonstatic-app/conf/routes
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
# ~~~~

# Home page
GET / Application.index
GET /hello Application.hello
GET / NonstaticHello.index
GET /hello NonstaticHello.hello

# Ignore favicon requests
GET /favicon.ico 404
Expand Down
Loading