Skip to content

Commit 47f722f

Browse files
committed
server: allow to setup web server programatically
- fix #2807 - Support Virutal Threads (Discussion) fix #2779 - fix some doc issues - fix test naming
1 parent 2619511 commit 47f722f

File tree

18 files changed

+202
-59
lines changed

18 files changed

+202
-59
lines changed

docs/asciidoc/modules/ebean.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Persistence module using Ebean: https://ebean.io
1111

1212
2) Add database driver (mySQL here):
1313

14-
[dependency, artifactId="mysql-connector-java"]
14+
[dependency, artifactId="mysql-connector-j"]
1515
.
1616

1717
3) Set database properties

docs/asciidoc/modules/flyway.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ https://flywaydb.org[Flyway] database migrations module.
1111

1212
2) Add database driver (mySQL here):
1313

14-
[dependency, artifactId="mysql-connector-java"]
14+
[dependency, artifactId="mysql-connector-j"]
1515
.
1616

1717
3) Set database properties

docs/asciidoc/modules/hibernate.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ https://hibernate.org/orm/[Hibernate ORM] module.
1111

1212
2) Add database driver (mySQL here):
1313

14-
[dependency, artifactId="mysql-connector-java"]
14+
[dependency, artifactId="mysql-connector-j"]
1515
.
1616

1717
3) Set database properties

docs/asciidoc/modules/hikari.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ https://github.com/brettwooldridge/HikariCP[HikariCP] is a high-performance JDBC
1111

1212
2) Add database driver (MySQL here):
1313

14-
[dependency, artifactId="mysql-connector-java"]
14+
[dependency, artifactId="mysql-connector-j"]
1515
.
1616

1717
3) Set database properties

docs/asciidoc/modules/jdbi.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ https://github.com/jdbi/jdbi[Jdbi] module.
1111

1212
2) Add database driver (mySQL here):
1313

14-
[dependency, artifactId="mysql-connector-java"]
14+
[dependency, artifactId="mysql-connector-j"]
1515
.
1616

1717
3) Set database properties

docs/asciidoc/servers.adoc

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,76 @@ To use Undertow, add the dependency:
2828
Only one server dependency must be available on classpath.
2929
====
3030

31+
=== Manual setup
32+
33+
Servers are automatically loaded using `ServiceLoader` API. If you need to add it manually:
34+
35+
.Server
36+
[source,java,role="primary"]
37+
----
38+
39+
import io.jooby.netty.NettyServer;
40+
41+
{
42+
install(new NettyServer());
43+
}
44+
----
45+
46+
.Kotlin
47+
[source,kotlin,role="secondary"]
48+
----
49+
import io.jooby.netty.NettyServer
50+
51+
{
52+
install(NettyServer())
53+
}
54+
----
55+
56+
Server might or might not provide way to configure it (depends on Server). For example `JettyServer`
57+
let you customize the `ThreadPool`, here is an example to setup Jetty with Loom(Virtual Threads):
58+
59+
.Jetty Loom
60+
[source,java,role="primary"]
61+
----
62+
63+
import io.jooby.jetty.JettyServer;
64+
65+
import java.util.concurrent.Executors;
66+
67+
import org.eclipse.jetty.util.thread.QueuedThreadPool;
68+
69+
70+
{
71+
// Use virtual Thread in Java 19 with --enable-preview
72+
QueuedThreadPool worker = new QueuedThreadPool();
73+
worker.setReservedThreads(0);
74+
worker.setVirtualThreadsExecutor(Executors.newVirtualThreadPerTaskExecutor());
75+
76+
install(new JettyServer(worker));
77+
}
78+
----
79+
80+
.Kotlin
81+
[source,kotlin,role="secondary"]
82+
----
83+
84+
import io.jooby.jetty.JettyServer
85+
86+
import java.util.concurrent.Executors
87+
88+
import org.eclipse.jetty.util.thread.QueuedThreadPool
89+
90+
91+
{
92+
// Use virtual Thread in Java 19 with --enable-preview
93+
val worker = QueuedThreadPool()
94+
worker.reservedThreads = 0
95+
worker.virtualThreadsExecutor = Executors.newVirtualThreadPerTaskExecutor()
96+
97+
install(JettyServer(worker))
98+
}
99+
----
100+
31101
=== Options
32102

33103
Server options are available via javadoc:ServerOptions[] class:

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

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@
7575
*
7676
* More documentation at <a href="https://jooby.io">jooby.io</a>
7777
*
78-
* @since 2.0.0
7978
* @author edgar
79+
* @since 2.0.0
8080
*/
8181
public class Jooby implements Router, Registry {
8282

@@ -122,6 +122,8 @@ public class Jooby implements Router, Registry {
122122

123123
private String version;
124124

125+
private Server server;
126+
125127
/** Creates a new Jooby instance. */
126128
public Jooby() {
127129
if (owner == null) {
@@ -539,6 +541,17 @@ public Jooby encoder(@NonNull MediaType contentType, @NonNull MessageEncoder enc
539541
return this;
540542
}
541543

544+
/**
545+
* Set server to use.
546+
*
547+
* @param server Web Server.
548+
* @return This application.
549+
*/
550+
@NonNull public Jooby install(@NonNull Server server) {
551+
this.server = server;
552+
return this;
553+
}
554+
542555
@NonNull @Override
543556
public Jooby dispatch(@NonNull Runnable body) {
544557
router.dispatch(body);
@@ -838,46 +851,58 @@ public Jooby setStartupSummary(List<StartupSummary> startupSummary) {
838851
* @return Server.
839852
*/
840853
public @NonNull Server start() {
841-
List<Server> servers =
842-
stream(
843-
spliteratorUnknownSize(
844-
ServiceLoader.load(Server.class).iterator(), Spliterator.ORDERED),
845-
false)
846-
.collect(Collectors.toList());
847-
if (servers.size() == 0) {
848-
throw new IllegalStateException("Server not found.");
854+
if (server == null) {
855+
this.server = loadServer();
849856
}
850-
if (servers.size() > 1) {
851-
List<String> names =
852-
servers.stream()
853-
.map(it -> it.getClass().getSimpleName().toLowerCase())
854-
.collect(Collectors.toList());
855-
getLog().warn("Multiple servers found {}. Using: {}", names, names.get(0));
856-
}
857-
Server server = servers.get(0);
857+
858858
try {
859859
if (serverOptions == null) {
860860
serverOptions = ServerOptions.from(getEnvironment().getConfig()).orElse(null);
861861
}
862862
if (serverOptions != null) {
863-
serverOptions.setServer(server.getClass().getSimpleName().toLowerCase());
863+
serverOptions.setServer(server.getName());
864864
server.setOptions(serverOptions);
865865
}
866866

867867
return server.start(this);
868-
} catch (Throwable x) {
868+
} catch (Throwable startupError) {
869869
Logger log = getLog();
870-
log.error("Application startup resulted in exception", x);
870+
log.error("Application startup resulted in exception", startupError);
871871
try {
872872
server.stop();
873-
} catch (Throwable stopx) {
874-
log.info("Server stop resulted in exception", stopx);
873+
} catch (Throwable stopError) {
874+
log.info("Server stop resulted in exception", stopError);
875875
}
876876
// rethrow
877-
throw x instanceof StartupException
878-
? (StartupException) x
879-
: new StartupException("Application startup resulted in exception", x);
877+
throw startupError instanceof StartupException
878+
? (StartupException) startupError
879+
: new StartupException("Application startup resulted in exception", startupError);
880+
}
881+
}
882+
883+
/**
884+
* Load server from classpath using {@link ServiceLoader}.
885+
*
886+
* @return A server.
887+
*/
888+
private Server loadServer() {
889+
List<Server> servers =
890+
stream(
891+
spliteratorUnknownSize(
892+
ServiceLoader.load(Server.class).iterator(), Spliterator.ORDERED),
893+
false)
894+
.collect(Collectors.toList());
895+
if (servers.size() == 0) {
896+
throw new StartupException("Server not found.");
897+
}
898+
if (servers.size() > 1) {
899+
List<String> names =
900+
servers.stream()
901+
.map(it -> it.getClass().getSimpleName().toLowerCase())
902+
.collect(Collectors.toList());
903+
getLog().warn("Multiple servers found {}. Using: {}", names, names.get(0));
880904
}
905+
return servers.get(0);
881906
}
882907

883908
/**

jooby/src/main/java/io/jooby/Server.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ protected void addShutdownHook() {
123123
*/
124124
@NonNull Server setOptions(@NonNull ServerOptions options);
125125

126+
@NonNull String getName();
127+
126128
/**
127129
* Get server options.
128130
*

jooby/src/main/java/io/jooby/ServerOptions.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@
2828
import io.jooby.internal.SslContextProvider;
2929

3030
/**
31-
* Available server options.
31+
* Available server options. To load server options from configuration files, just do:
32+
*
33+
* <pre>{@code
34+
* Optional<ServerOptions> serverOptions = ServerOptions.from(getEnvironment().getConfig());
35+
*
36+
* }</pre>
3237
*
3338
* @author edgar
3439
* @since 2.0.0
@@ -320,31 +325,31 @@ public int getIoThreads(int defaultIoThreads) {
320325
}
321326

322327
/**
323-
* Number of worker threads (a.k.a application) to use. This are the threads which are allowed to
328+
* Number of worker threads (a.k.a application) to use. These are the threads which are allowed to
324329
* block.
325330
*
326-
* @return Number of worker threads (a.k.a application) to use. This are the threads which are
331+
* @return Number of worker threads (a.k.a application) to use. These are the threads which are
327332
* allowed to block.
328333
*/
329334
public int getWorkerThreads() {
330335
return getWorkerThreads(WORKER_THREADS);
331336
}
332337

333338
/**
334-
* Number of worker threads (a.k.a application) to use. This are the threads which are allowed to
339+
* Number of worker threads (a.k.a application) to use. These are the threads which are allowed to
335340
* block.
336341
*
337342
* @param defaultWorkerThreads Default worker threads is none was set.
338-
* @return Number of worker threads (a.k.a application) to use. This are the threads which are
343+
* @return Number of worker threads (a.k.a application) to use. These are the threads which are
339344
* allowed to block.
340345
*/
341346
public int getWorkerThreads(int defaultWorkerThreads) {
342347
return workerThreads == null ? defaultWorkerThreads : workerThreads;
343348
}
344349

345350
/**
346-
* Set number of worker threads (a.k.a application) to use. This are the threads which are allowed
347-
* to block.
351+
* Set number of worker threads (a.k.a application) to use. These are the threads which are
352+
* allowed to block.
348353
*
349354
* @param workerThreads Number of worker threads to use.
350355
* @return This options.

modules/jooby-cli/src/main/resources/cli/App.java.hbs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
package {{package}};
22

33
import io.jooby.Jooby;
4+
import io.jooby.netty.NettyServer;
45
{{#if openapi}}
56
import io.jooby.OpenAPIModule;
67
{{/if}}
78

89
public class App extends Jooby {
910

1011
{
11-
{{#if openapi}}
12+
install(new NettyServer());
13+
{{#if openapi}}
1214
install(new OpenAPIModule());
13-
{{/if}}
14-
15-
{{#if mvc}}
15+
{{/if}}
16+
{{#if mvc}}
1617
mvc(new Controller());
17-
{{else}}
18+
{{else}}
1819
get("/", ctx -> "Welcome to Jooby!");
19-
{{/if}}
20+
{{/if}}
2021
}
2122

2223
public static void main(final String[] args) {

0 commit comments

Comments
 (0)