Skip to content

Commit 0d19b94

Browse files
committed
env refactor
- remove thread local - late init for env - allow app initializer to set the env - allow custom name for application.properties
1 parent 99de19d commit 0d19b94

File tree

5 files changed

+81
-96
lines changed

5 files changed

+81
-96
lines changed

jooby/src/main/java/io/jooby/Env.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public static PropertySource parse(String... args) {
129129
return new PropertySource("args", conf);
130130
}
131131

132-
public static PropertySource load(ClassLoader loader, String filename) {
132+
private static PropertySource load(ClassLoader loader, String filename) {
133133
return load(loader, filename, (name, stream) -> {
134134
try {
135135
Properties properties = new Properties();
@@ -141,7 +141,7 @@ public static PropertySource load(ClassLoader loader, String filename) {
141141
});
142142
}
143143

144-
public static PropertySource load(ClassLoader loader, String filename,
144+
private static PropertySource load(ClassLoader loader, String filename,
145145
BiFunction<String, InputStream, PropertySource> propertyLoader) {
146146
AtomicReference<String> fullpath = new AtomicReference<>();
147147
InputStream stream = findProperties(loader, filename, fullpath::set);
@@ -167,19 +167,20 @@ public static PropertySource systemEnv() {
167167
return new PropertySource("systemEnv", System.getenv());
168168
}
169169

170-
public static Env defaultEnvironment(String... args) {
171-
ClassLoader classLoader = Env.class.getClassLoader();
170+
public static Env defaultEnvironment(ClassLoader loader) {
171+
return defaultEnvironment(loader, "application");
172+
}
173+
174+
public static Env defaultEnvironment(ClassLoader loader, String filename) {
172175
LinkedList<PropertySource> sources = new LinkedList<>();
173-
PropertySource argMap = parse(args);
174176

175177
sources.add(systemEnv());
176178
sources.add(systemProperties());
177-
sources.add(argMap);
178179

179180
String env = fromSource(sources, "application.env", "dev").toLowerCase();
180181
Stream
181-
.of("application." + env + ".properties", "application.properties")
182-
.map(filename -> load(classLoader, filename))
182+
.of(filename + "." + env + ".properties", filename + ".properties")
183+
.map(it -> load(loader, it))
183184
.filter(props -> props.properties().size() > 0)
184185
.forEach(sources::addFirst);
185186

jooby/src/main/java/io/jooby/Jooby.java

Lines changed: 44 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,10 @@
2626
import java.nio.file.Path;
2727
import java.nio.file.Paths;
2828
import java.util.ArrayList;
29-
import java.util.HashMap;
29+
import java.util.Arrays;
3030
import java.util.Iterator;
3131
import java.util.LinkedList;
3232
import java.util.List;
33-
import java.util.Map;
3433
import java.util.NoSuchElementException;
3534
import java.util.ServiceLoader;
3635
import java.util.Spliterator;
@@ -47,6 +46,8 @@
4746

4847
public class Jooby implements Router, Registry {
4948

49+
private static final String ENV_KEY = "application.env";
50+
5051
private RouterImpl router;
5152

5253
private ExecutionMode mode;
@@ -61,27 +62,12 @@ public class Jooby implements Router, Registry {
6162

6263
private LinkedList<Throwing.Runnable> stopCallbacks;
6364

64-
/**
65-
* Not ideal but useful. We want to have access to environment properties from instance
66-
* initializer. So external method before creating a new Jooby instance does a call to
67-
* {@link Jooby#setEnv(Env)} this makes available the env instance in any other Jooby instance
68-
* created.
69-
*/
70-
private static ThreadLocal<Env> ENV = new ThreadLocal<>();
71-
72-
protected Env environment;
65+
private Env environment;
7366

7467
private Registry registry;
7568

7669
public Jooby() {
7770
router = new RouterImpl(new RouteAnalyzer(getClass().getClassLoader(), false));
78-
environment = ENV.get();
79-
if (environment == null) {
80-
// TODO: fallback for now, but probably better if we throws a specific error
81-
environment = Env.defaultEnvironment();
82-
}
83-
tmpdir = Paths.get(environment.get("application.tmpdir").value()).toAbsolutePath();
84-
8571
}
8672

8773
public @Nonnull Env environment() {
@@ -340,14 +326,20 @@ private <T> T require(AttributeKey<T> key) {
340326
if (serverConfigurer != null) {
341327
serverConfigurer.accept(server);
342328
}
329+
if (environment == null) {
330+
environment = Env.defaultEnvironment(getClass().getClassLoader());
331+
}
332+
if (tmpdir == null) {
333+
tmpdir = Paths.get(environment.get("application.tmpdir").value()).toAbsolutePath();
334+
}
343335
return server.start(this);
344336
}
345337

346338
public @Nonnull Jooby start(@Nonnull Server server) {
347339
/** Start router: */
348340
ensureTmpdir(tmpdir);
349-
Logger log = log();
350-
log.debug("environment:\n{}", environment);
341+
342+
log().debug("environment:\n{}", environment);
351343

352344
if (mode == null) {
353345
mode = ExecutionMode.DEFAULT;
@@ -399,55 +391,51 @@ private <T> T require(AttributeKey<T> key) {
399391
return router.toString();
400392
}
401393

402-
public static void setEnv(@Nonnull Env environment) {
403-
ENV.set(environment);
404-
}
405-
406394
public static void run(@Nonnull Supplier<Jooby> provider, String... args) {
407395
run(provider, ExecutionMode.DEFAULT, args);
408396
}
409397

410398
public static void run(@Nonnull Supplier<Jooby> provider, @Nonnull ExecutionMode mode,
411399
String... args) {
412-
Server server;
413-
try {
414-
Env environment = Env.defaultEnvironment(args);
415-
setEnv(environment);
416400

417-
logback(environment);
401+
/** Dump command line as system properties. */
402+
Env.parse(args).properties().forEach(System::setProperty);
418403

419-
Jooby app = provider.get();
420-
if (app.mode == null) {
421-
app.mode = mode;
422-
}
423-
server = app.start();
424-
} finally {
425-
// clear env
426-
setEnv(null);
404+
/** Fin application.env: */
405+
String env = System.getProperty(ENV_KEY, System.getenv().getOrDefault(ENV_KEY, "dev"))
406+
.toLowerCase();
407+
408+
logback(env);
409+
410+
Jooby app = provider.get();
411+
if (app.mode == null) {
412+
app.mode = mode;
427413
}
414+
Server server = app.start();
428415
server.join();
429416
}
430417

431-
public static void logback(@Nonnull Env env) {
432-
String setfile = env.get("logback.configurationFile").value((String) null);
433-
if (setfile != null) {
434-
System.setProperty("logback.configurationFile", setfile);
435-
return;
418+
public static void logback(@Nonnull String env) {
419+
String logfile = System
420+
.getProperty("logback.configurationFile", System.getenv().get("logback.configurationFile"));
421+
if (logfile != null) {
422+
System.setProperty("logback.configurationFile", logfile);
423+
} else {
424+
Path userdir = Paths.get(System.getProperty("user.dir"));
425+
Path conf = userdir.resolve("conf");
426+
String logbackenv = "logback." + env + ".xml";
427+
String fallback = "logback.xml";
428+
Stream.of(
429+
/** Env specific inside conf or userdir: */
430+
conf.resolve(logbackenv), userdir.resolve(logbackenv),
431+
/** Fallback inside conf or userdir: */
432+
conf.resolve(fallback), userdir.resolve(fallback)
433+
).filter(Files::exists)
434+
.findFirst()
435+
.map(Path::toAbsolutePath)
436+
.ifPresent(
437+
logback -> System.setProperty("logback.configurationFile", logback.toString()));
436438
}
437-
String name = env.name();
438-
Path userdir = Paths.get(System.getProperty("user.dir"));
439-
Path conf = userdir.resolve("conf");
440-
String logbackenv = "logback." + name + ".xml";
441-
String fallback = "logback.xml";
442-
Stream.of(
443-
/** Env specific inside conf or userdir: */
444-
conf.resolve(logbackenv), userdir.resolve(logbackenv),
445-
/** Fallback inside conf or userdir: */
446-
conf.resolve(fallback), userdir.resolve(fallback)
447-
).filter(Files::exists)
448-
.findFirst()
449-
.map(Path::toAbsolutePath)
450-
.ifPresent(logback -> System.setProperty("logback.configurationFile", logback.toString()));
451439
}
452440

453441
private static void ensureTmpdir(Path tmpdir) {

jooby/src/test/java/io/jooby/EnvTest.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import java.util.HashMap;
1010
import java.util.List;
1111
import java.util.Map;
12+
import java.util.Properties;
1213
import java.util.function.Consumer;
1314

1415
import static java.util.Arrays.asList;
@@ -62,15 +63,15 @@ private void env(String dir, Consumer<Env> consumer) {
6263
}
6364

6465
private void env(String dir, Map<String, String> args, Consumer<Env> consumer) {
65-
Path file = Paths.get("env", dir);
66-
System.setProperty("env.dir", file.toString());
67-
consumer.accept(Env.defaultEnvironment(toArray(args)));
68-
}
69-
70-
private String[] toArray(Map<String, String> args) {
71-
List<String> result = new ArrayList<>();
72-
args.forEach((k, v) -> result.add(k + "=" + v));
73-
return result.toArray(new String[result.size()]);
66+
Properties sysprops = new Properties(System.getProperties());
67+
try {
68+
Path file = Paths.get("env", dir);
69+
System.setProperty("env.dir", file.toString());
70+
args.forEach((k, v) -> System.setProperty(k, v));
71+
consumer.accept(Env.defaultEnvironment(getClass().getClassLoader()));
72+
} finally {
73+
System.setProperties(sysprops);
74+
}
7475
}
7576

7677
private Map<String, String> mapOf(String... values) {

jooby/src/test/java/io/jooby/JoobyRunner.java

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,20 @@ public class JoobyRunner {
2222

2323
public JoobyRunner(Consumer<Jooby> provider) {
2424
this.provider = () -> {
25-
try {
26-
Jooby.setEnv(Env.defaultEnvironment("test"));
27-
Jooby app = new Jooby();
28-
provider.accept(app);
29-
return app;
30-
} finally {
31-
Jooby.setEnv(null);
32-
}
25+
Jooby app = new Jooby();
26+
app.environment(Env.defaultEnvironment(getClass().getClassLoader(), "test"));
27+
provider.accept(app);
28+
return app;
3329
};
3430
}
3531

3632
public JoobyRunner(Supplier<Jooby> provider) {
3733
this.provider = () -> {
38-
try {
39-
Jooby.setEnv(Env.defaultEnvironment("test"));
40-
return provider.get();
41-
} finally {
42-
Jooby.setEnv(null);
34+
Jooby app = provider.get();
35+
if (app.environment() == null) {
36+
app.environment(Env.defaultEnvironment(app.getClass().getClassLoader(), "test"));
4337
}
38+
return app;
4439
};
4540
}
4641

jooby/src/test/java/io/jooby/MockRouter.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,21 @@ public class MockRouter {
1313

1414
public MockRouter(Supplier<Jooby> supplier) {
1515
this.supplier = () -> {
16-
Env env = Env.defaultEnvironment("test");
17-
Jooby.setEnv(env);
1816
Jooby jooby = supplier.get();
19-
Jooby.setEnv(null);
17+
if (jooby.environment() == null) {
18+
jooby.environment(Env.defaultEnvironment(jooby.getClass().getClassLoader(), "test"));
19+
}
2020
return jooby;
2121
};
2222
}
2323

2424
public MockRouter(Consumer<Jooby> consumer) {
2525
this.supplier = () -> {
26-
Env env = Env.defaultEnvironment("test");
27-
Jooby.setEnv(env);
28-
Jooby app = new Jooby();
29-
consumer.accept(app);
30-
Jooby.setEnv(null);
31-
return app;
26+
Jooby jooby = new Jooby();
27+
Env env = Env.defaultEnvironment(getClass().getClassLoader(), "test");
28+
jooby.environment(env);
29+
consumer.accept(jooby);
30+
return jooby;
3231
};
3332
}
3433

@@ -114,7 +113,8 @@ private Object route(Jooby router, String method, String path, Consumer<MockCont
114113
Result result = new Result(value, ctx.statusCode());
115114

116115
/** Content-Type: */
117-
result.header("Content-Type", ctx.responseContentType().toContentTypeHeader(ctx.getResponseCharset()));
116+
result.header("Content-Type",
117+
ctx.responseContentType().toContentTypeHeader(ctx.getResponseCharset()));
118118

119119
/** Length: */
120120
long responseLength = ctx.getResponseLength();

0 commit comments

Comments
 (0)