Skip to content
This repository was archived by the owner on Mar 3, 2026. It is now read-only.

Commit b12364e

Browse files
committed
env.onStart/onStop callbacks fix jooby-project#302
1 parent 24090e7 commit b12364e

File tree

8 files changed

+182
-6
lines changed

8 files changed

+182
-6
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.jooby;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
import org.jooby.test.ServerFeature;
7+
import org.junit.Test;
8+
9+
public class EnvOnStart2Feature extends ServerFeature {
10+
11+
{
12+
13+
List<String> order = new ArrayList<>();
14+
15+
onStart(() -> order.add("a"));
16+
17+
use((env, conf, binder) -> {
18+
env.onStart(() -> order.add("m1"));
19+
});
20+
21+
use((env, conf, binder) -> {
22+
env.onStart(() -> order.add("m2"));
23+
});
24+
25+
onStart(() -> order.add("b"));
26+
27+
get("/onStartOrder", () -> order);
28+
}
29+
30+
@Test
31+
public void onStartOrder() throws Exception {
32+
request().get("/onStartOrder").expect("[m1, m2, a, b]");
33+
}
34+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package org.jooby;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
import org.jooby.test.ServerFeature;
7+
import org.junit.Test;
8+
9+
public class EnvOnStartFeature extends ServerFeature {
10+
11+
{
12+
13+
List<String> order = new ArrayList<>();
14+
15+
use((env, conf, binder) -> {
16+
env.onStart(() -> order.add("m1"));
17+
});
18+
19+
use((env, conf, binder) -> {
20+
env.onStart(() -> order.add("m2"));
21+
});
22+
23+
get("/onStartOrder", () -> order);
24+
}
25+
26+
@Test
27+
public void onStartOrder() throws Exception {
28+
request().get("/onStartOrder").expect("[m1, m2]");
29+
}
30+
}

coverage-report/src/test/java/org/jooby/issues/Issue273.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
package org.jooby.issues;
22

3-
import java.util.Arrays;
4-
import java.util.Locale;
5-
63
import org.jooby.test.ServerFeature;
74
import org.junit.Test;
85

jooby-jdbc/src/test/java/org/jooby/jdbc/JdbcTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import static org.junit.Assert.assertTrue;
1212

1313
import java.io.File;
14+
import java.util.List;
1415
import java.util.Locale;
1516
import java.util.Properties;
1617
import java.util.function.BiConsumer;
@@ -991,6 +992,26 @@ public Routes routes() throws UnsupportedOperationException {
991992
throw new UnsupportedOperationException();
992993
}
993994

995+
@Override
996+
public Env onStop(final Runnable shutdownTask) {
997+
throw new UnsupportedOperationException();
998+
}
999+
1000+
@Override
1001+
public List<Runnable> stopTasks() {
1002+
throw new UnsupportedOperationException();
1003+
}
1004+
1005+
@Override
1006+
public Env onStart(final Runnable task) {
1007+
throw new UnsupportedOperationException();
1008+
}
1009+
1010+
@Override
1011+
public List<Runnable> startTasks() {
1012+
throw new UnsupportedOperationException();
1013+
}
1014+
9941015
@Override
9951016
public Config config() {
9961017
return ConfigFactory.empty();

jooby/src/main/java/org/jooby/Env.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static com.google.common.base.Preconditions.checkArgument;
2222
import static java.util.Objects.requireNonNull;
2323

24+
import java.util.List;
2425
import java.util.Locale;
2526
import java.util.Optional;
2627
import java.util.function.Predicate;
@@ -29,6 +30,7 @@
2930
import com.google.common.base.CharMatcher;
3031
import com.google.common.base.Splitter;
3132
import com.google.common.base.Strings;
33+
import com.google.common.collect.ImmutableList;
3234
import com.typesafe.config.Config;
3335

3436
import javaslang.control.Match;
@@ -98,6 +100,10 @@ default Env build(final Config config) {
98100
String name = config.hasPath("application.env") ? config.getString("application.env") : "dev";
99101
return new Env() {
100102

103+
private ImmutableList.Builder<Runnable> start = ImmutableList.builder();
104+
105+
private ImmutableList.Builder<Runnable> shutdown = ImmutableList.builder();
106+
101107
@Override
102108
public String name() {
103109
return name;
@@ -125,6 +131,28 @@ public Locale locale() {
125131
public String toString() {
126132
return name();
127133
}
134+
135+
@Override
136+
public List<Runnable> stopTasks() {
137+
return shutdown.build();
138+
}
139+
140+
@Override
141+
public Env onStop(final Runnable task) {
142+
this.shutdown.add(task);
143+
return this;
144+
}
145+
146+
@Override
147+
public Env onStart(final Runnable task) {
148+
this.start.add(task);
149+
return this;
150+
}
151+
152+
@Override
153+
public List<Runnable> startTasks() {
154+
return this.start.build();
155+
}
128156
};
129157
};
130158

@@ -332,4 +360,40 @@ default <T> MatchValue.Then<String, T> when(final Predicate<String> predicate, f
332360
return match().when(e -> predicate.test(e.toString())).then(result);
333361
}
334362

363+
/**
364+
* Add a start task, useful for initialize and/or start services at startup time.
365+
*
366+
* You should ONLY call this method while the application is been initialized, usually executing
367+
* {@link Jooby.Module#configure(Env, Config, com.google.inject.Binder)}.
368+
*
369+
* The behaviour of this method once application has been initialized is <code>undefined</code>.
370+
*
371+
* @param task Task to run.
372+
* @return This env.
373+
*/
374+
Env onStart(Runnable task);
375+
376+
/**
377+
* Add a stop task, useful for cleanup and/or stop service at stop time.
378+
*
379+
* You should ONLY call this method while the application is been initialized, usually executing
380+
* {@link Jooby.Module#configure(Env, Config, com.google.inject.Binder)}.
381+
*
382+
* The behaviour of this method once application has been initialized is <code>undefined</code>.
383+
*
384+
* @param task Task to run.
385+
* @return This env.
386+
*/
387+
Env onStop(Runnable task);
388+
389+
/**
390+
* @return List of start tasks.
391+
*/
392+
List<Runnable> startTasks();
393+
394+
/**
395+
* @return List of stop tasks.
396+
*/
397+
List<Runnable> stopTasks();
398+
335399
}

jooby/src/main/java/org/jooby/Jooby.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3575,6 +3575,9 @@ private Injector bootstrap(final Config args,
35753575
ehandlers.addBinding().toInstance(new Err.DefHandler());
35763576
});
35773577

3578+
onStart.addAll(0, finalEnv.startTasks());
3579+
onStop.addAll(finalEnv.stopTasks());
3580+
35783581
// clear bag and freeze it
35793582
this.bag.clear();
35803583
this.bag = ImmutableSet.of();

jooby/src/test/java/org/jooby/EnvTest.java

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static org.junit.Assert.assertEquals;
44
import static org.junit.Assert.fail;
55

6+
import java.util.Arrays;
67
import java.util.Optional;
78

89
import org.junit.Test;
@@ -126,7 +127,8 @@ public void resolveEmpty() {
126127

127128
@Test
128129
public void ifMode() throws Throwable {
129-
assertEquals("$dev", Env.DEFAULT.build(ConfigFactory.empty()).ifMode("dev", () -> "$dev").get());
130+
assertEquals("$dev",
131+
Env.DEFAULT.build(ConfigFactory.empty()).ifMode("dev", () -> "$dev").get());
130132
assertEquals(Optional.empty(),
131133
Env.DEFAULT.build(ConfigFactory.empty()).ifMode("prod", () -> "$dev"));
132134

@@ -135,12 +137,14 @@ public void ifMode() throws Throwable {
135137
Env.DEFAULT
136138
.build(
137139
ConfigFactory.empty().withValue("application.env",
138-
ConfigValueFactory.fromAnyRef("prod"))).ifMode("prod", () -> "$prod").get());
140+
ConfigValueFactory.fromAnyRef("prod")))
141+
.ifMode("prod", () -> "$prod").get());
139142
assertEquals(Optional.empty(),
140143
Env.DEFAULT
141144
.build(
142145
ConfigFactory.empty().withValue("application.env",
143-
ConfigValueFactory.fromAnyRef("prod"))).ifMode("dev", () -> "$prod"));
146+
ConfigValueFactory.fromAnyRef("prod")))
147+
.ifMode("dev", () -> "$prod"));
144148
}
145149

146150
@Test
@@ -166,4 +170,24 @@ public void name() throws Exception {
166170
ConfigValueFactory.fromAnyRef("prod"))).toString());
167171

168172
}
173+
174+
@Test
175+
public void onStart() throws Exception {
176+
Env env = Env.DEFAULT.build(ConfigFactory.empty());
177+
Runnable task = () -> {
178+
};
179+
env.onStart(task);
180+
181+
assertEquals(Arrays.asList(task), env.startTasks());
182+
}
183+
184+
@Test
185+
public void onStop() throws Exception {
186+
Env env = Env.DEFAULT.build(ConfigFactory.empty());
187+
Runnable task = () -> {
188+
};
189+
env.onStop(task);
190+
191+
assertEquals(Arrays.asList(task), env.stopTasks());
192+
}
169193
}

jooby/src/test/java/org/jooby/JoobyTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.time.ZoneId;
1616
import java.time.format.DateTimeFormatter;
1717
import java.util.Arrays;
18+
import java.util.Collections;
1819
import java.util.LinkedList;
1920
import java.util.List;
2021
import java.util.Locale;
@@ -745,6 +746,8 @@ public void customEnv() throws Exception {
745746
.expect(unit -> {
746747
Env env = unit.mock(Env.class);
747748
expect(env.name()).andReturn("dev").times(2);
749+
expect(env.startTasks()).andReturn(Collections.emptyList());
750+
expect(env.stopTasks()).andReturn(Collections.emptyList());
748751

749752
Env.Builder builder = unit.get(Env.Builder.class);
750753
expect(builder.build(isA(Config.class), isA(Jooby.class), isA(Locale.class)))

0 commit comments

Comments
 (0)