Skip to content

Commit d70d0d9

Browse files
committed
Hikari doc + some minor changes
1 parent 80c458e commit d70d0d9

File tree

17 files changed

+807
-25
lines changed

17 files changed

+807
-25
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ TODO
2828
tmp
2929
checkstyle
3030
javadoc
31+
examples.mv.db

docs/asciidoc/extension.adoc

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
== Extensions and Services
2+
3+
Jooby comes with a simple extension mechanism. The javadoc:Extension[] API allows to configure
4+
, extend an application by adding shared/single services, infrastructure/technical concerns like
5+
dependency injection, database connection pools, cron-job, etc.
6+
7+
Services are shared/singleton objects, usually with a clear lifecycle for starting and stopping them.
8+
9+
=== Writing Custom Extension
10+
11+
We are going to develop a custom extension that configure a `DataSource` service.
12+
13+
.Java
14+
[source, java, role = "primary"]
15+
----
16+
import io.jooby.Extension;
17+
18+
public class MyExtension implements Extension {
19+
20+
public void install(Jooby application) {
21+
DataSource dataSource = createDataSource(); <1>
22+
23+
ServiceRegistry registry = application.getServices(); <2>
24+
registry.put(DataSource.class, dataSource); <3>
25+
26+
application.onStop(dataSource::close) <4>
27+
}
28+
}
29+
----
30+
31+
.Kotlin
32+
[source, kotlin, role = "secondary"]
33+
----
34+
import io.jooby.Extension
35+
36+
class MyExtension: Extension {
37+
override fun install(application: Jooby) {
38+
val dataSource = createDataSource() <1>
39+
40+
val registry = application.services <2>
41+
registry.put(DataSource::class, dataSource) <3>
42+
application.onStop(dataSource::close) <4>
43+
}
44+
}
45+
----
46+
47+
<1> Create the service
48+
<2> Access to service registry
49+
<3> Add it to the service registry
50+
<4> Close/release service on application stop
51+
52+
Let's install the extension and use the service!!
53+
54+
55+
.Java
56+
[source, java, role = "primary"]
57+
----
58+
public class App extends Jooby {
59+
60+
{
61+
install(new MyExtension()); <1>
62+
63+
get("/", ctx -> {
64+
MyDataSource ds = require(MyDataSource.class); <2>
65+
// ...
66+
});
67+
}
68+
}
69+
----
70+
71+
.Kotlin
72+
[source, kotlin, role = "secondary"]
73+
----
74+
import io.jooby.Extension
75+
76+
class App: Kooby({
77+
78+
install(MyExtension()) <1>
79+
80+
get("/") {ctx ->
81+
val ds = require(MyDataSource::class) <2>
82+
}
83+
})
84+
----
85+
86+
<1> Install the extension
87+
<2> Use the service
88+
89+
Services are accessible via javadoc:Registry[require, java.lang.Class].
90+
91+
In addition to services, an extension module may provides infrastructure routes, body decoder/encoder,
92+
template engines, etc.
93+
94+
The extension mechanism is a simple way of reusing code and decoupling technical features from
95+
business logic.
96+
97+
More advanced techniques are describe in the <<Dependency Injection>> section.

docs/asciidoc/index.adoc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,4 +228,8 @@ include::testing.adoc[]
228228

229229
include::dev-tools.adoc[]
230230

231+
include::extension.adoc[]
232+
231233
include::dependency-injection.adoc[]
234+
235+
include::modules.adoc[]

docs/asciidoc/modules.adoc

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
== Modules
2+
3+
Modules are a key concept for building reusable and configurable pieces of software.
4+
5+
Modules (unlike in other frameworks) are thin and do a lot of work to bootstrap and configure an
6+
external library, but they DO NOT provide a new level of abstraction nor [do] they provide a custom
7+
API to access functionality in that library. Instead they expose the library components as they are.
8+
9+
Modules are shipped as separated jar/dependency and usually implement the javadoc:Extension[] API.
10+
11+
In general they provide a `builder` class to create the and configure the external library from
12+
configuration properties.
13+
14+
The module name is usually the same as the library, except when library comes with a class with the
15+
same name. To avoid name collisions we choose one of following convention:
16+
17+
- An abbreviation of the name/library. For example: `Hibernate` -> `Hbm`, `Handlebars -> Hbs`, `Freemarker` -> `Ftl`.
18+
- Add a `by` suffix. For example: `Hibernate` -> `Hibernateby`, `Guice` -> `Guiceby`, `Handelbars` -> `Handlebarsby`
19+
20+
=== Data
21+
22+
- link:modules/hikari[Hikari Connection Pool]: A high-performance JDBC connection pool.
23+
24+
.

docs/asciidoc/modules/hikari.adoc

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
== Hikari
2+
3+
https://github.com/brettwooldridge/HikariCP[HikariCP] is a high-performance JDBC connection pool.
4+
5+
=== Usage
6+
7+
1) Add the dependency:
8+
9+
[dependency, artifactId="jooby-hikary"]
10+
.
11+
12+
2) Add database driver (mySQL here):
13+
14+
[dependency, artifactId="mysql-connector-java"]
15+
.
16+
17+
3) Set database properties
18+
19+
.application.conf
20+
[source, properties]
21+
----
22+
db.url = "jdbc:mysql://localhost/mydb"
23+
db.user = myuser
24+
db.password = mypass
25+
----
26+
27+
28+
4) Install and use the connection pool
29+
30+
.Java
31+
[source, java, role="primary"]
32+
----
33+
import io.jooby.hikari.Hikary;
34+
35+
{
36+
install(new Hikari());
37+
38+
get("/", ctx -> {
39+
DataSource ds = require(DataSource.class);
40+
// work with data source
41+
});
42+
}
43+
----
44+
45+
.Kotlin
46+
[source, kt, role="secondary"]
47+
----
48+
import io.jooby.hikari.Hikary
49+
50+
{
51+
install(Hikari())
52+
53+
get("/") { ctx ->
54+
val ds = require(DataSource::class)
55+
// work with data source
56+
}
57+
}
58+
----
59+
60+
=== Database configuration
61+
62+
By default the javadoc:hikari.Hikari[] module expects to find database properties as application
63+
configuration properties under the `db` key prefix. The next example shows how to overrides the
64+
database prefix:
65+
66+
.Custom database prefix
67+
[source, java, role="primary"]
68+
----
69+
import io.jooby.hikari.Hikary;
70+
71+
{
72+
install(new Hikari("mydb"));
73+
}
74+
----
75+
76+
.Kotlin
77+
[source, kt, role="secondary"]
78+
----
79+
import io.jooby.hikari.Hikary
80+
81+
{
82+
install(Hikari("mydb"))
83+
}
84+
----
85+
86+
Configuration properties are optionally if the database driver support them from jdbc url:
87+
88+
.No properties
89+
[source, java, role="primary"]
90+
----
91+
import io.jooby.hikari.Hikary;
92+
93+
{
94+
install(new Hikari("jdbc:mysql://localhost/mydb"));
95+
}
96+
----
97+
98+
.Kotlin
99+
[source, kt, role="secondary"]
100+
----
101+
import io.jooby.hikari.Hikary
102+
103+
{
104+
install(Hikari("jdbc:mysql://localhost/mydb"))
105+
}
106+
----
107+
108+
=== Special databases
109+
110+
Modules comes with 3 special databases provided by https://github.com/h2database/h2database[H2 database]:
111+
112+
- `mem`: setup an in-memory database
113+
- `fs` : a file system database at `System.getProperty("user.dir")`
114+
- `tmp`: a tmp file system database at `System.getProperty("user.dir") + "/tmp"` directory
115+
116+
=== Multiple databases
117+
118+
Multiple database is supported using jdbc url or database configuration keys.
119+
120+
.application.conf
121+
[source, properties]
122+
----
123+
maindb.url = "jdbc:mysql://localhost/main"
124+
maindb.user = myuser
125+
maindb.password = mypass
126+
127+
auditdb.url = "jdbc:mysql://localhost/audit"
128+
auditdb.user = myuser
129+
auditdb.password = mypass
130+
----
131+
132+
.Multiple data sources
133+
[source, java, role="primary"]
134+
----
135+
import io.jooby.hikari.Hikary;
136+
137+
{
138+
install(new Hikari("maindb"));
139+
140+
install(new Hikari("auditdb"));
141+
142+
143+
get("/", ctx -> {
144+
DataSource maindb = require(DataSource.class, "maindb");
145+
DataSource auditdb = require(DataSource.class, "auditdb");
146+
// ...
147+
});
148+
}
149+
----
150+
151+
.Kotlin
152+
[source, kt, role="secondary"]
153+
----
154+
import io.jooby.hikari.Hikary
155+
156+
{
157+
install(Hikari("maindb"))
158+
159+
install(Hikari("auditdb"))
160+
161+
get("/") { ctx ->
162+
val maindb = require(DataSource::class, "maindb")
163+
val auditdb = require(DataSource::class, "auditdb")
164+
// ...
165+
}
166+
}
167+
----
168+
169+
=== Advanced options
170+
171+
Advanced Hikari configuration is supported from application configuration properties.
172+
173+
.Maximum Pool Size
174+
[source, properties]
175+
----
176+
db.url = "jdbc:mysql://localhost/main"
177+
db.user = myuser
178+
179+
hikari.maximumPoolSize = 10
180+
----
181+
182+
Different configuration per database is available by adding the database key:
183+
184+
.Maximum Pool Size
185+
[source, properties]
186+
----
187+
maindb.url = "jdbc:mysql://localhost/main"
188+
maindb.user = myuser
189+
maindb.password = mypass
190+
191+
hikari.maindb.maximumPoolSize = 10
192+
193+
auditdb.url = "jdbc:mysql://localhost/audit"
194+
auditdb.user = myuser
195+
auditdb.password = mypass
196+
197+
hikari.auditdb.maximumPoolSize = 15
198+
----

docs/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
<version>${jooby.version}</version>
2121
</dependency>
2222

23+
<dependency>
24+
<groupId>ch.qos.logback</groupId>
25+
<artifactId>logback-classic</artifactId>
26+
</dependency>
27+
2328
<dependency>
2429
<groupId>org.ow2.asm</groupId>
2530
<artifactId>asm-util</artifactId>

0 commit comments

Comments
 (0)