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

Commit ca07f9e

Browse files
committed
jdbc: decouple rxjdbc module fix jooby-project#874
1 parent 0c512bb commit ca07f9e

File tree

3 files changed

+53
-108
lines changed

3 files changed

+53
-108
lines changed

doc/doc/rxjava-jdbc/rxjava-jdbc.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<a href="https://github.com/davidmoten/rxjava-jdbc">rxjava-jdbc</a> efficient execution, concise code, and functional composition of database calls using JDBC and RxJava Observable.
44

55

6-
> This module depends on [jdbc module](/doc/jdbc) and [rx module](/doc/rxjava), please read the documentation of [jdbc module](/doc/jdbc) and [rx module](/doc/rxjava) before using ```rx-jdbc```.
6+
> This module depends on [jdbc](/doc/jdbc) module.
77
88
## dependency
99

@@ -28,6 +28,7 @@ import org.jooby.rx.Rx;
2828
{
2929
// required
3030
use(new Rx());
31+
use(new Jdbc());
3132

3233
use(new RxJdbc());
3334

@@ -49,12 +50,13 @@ The [Rx.rx()]({{defdocs}}/rx/Rx.html#rx--) mapper converts ```Observable``` to [
4950
import org.jooby.rx.RxJdbc;
5051
import org.jooby.rx.Rx;
5152
{
53+
use(new Jdbc("db.main"));
5254
use(new RxJdbc("db.main"));
5355

56+
use(new Jdbc("db.audit"));
5457
use(new RxJdbc("db.audit"));
5558

5659
get("/", req ->
57-
5860
Databse db = require("db.main", Database.class);
5961
Databse audit = require("db.audit", Database.class);
6062
// ...

modules/jooby-rxjava-jdbc/src/main/java/org/jooby/rx/RxJdbc.java

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,18 @@
205205

206206
import javax.sql.DataSource;
207207

208+
import com.google.inject.Key;
209+
import com.google.inject.name.Names;
208210
import org.jooby.Env;
211+
import org.jooby.Jooby;
209212
import org.jooby.jdbc.Jdbc;
210213

211214
import com.github.davidmoten.rx.jdbc.Database;
212215
import com.google.inject.Binder;
213216
import com.typesafe.config.Config;
214217

218+
import java.util.NoSuchElementException;
219+
215220
/**
216221
* <h1>rxjdbc</h1>
217222
* <p>
@@ -246,6 +251,7 @@
246251
* {
247252
* // required by RxJdbc
248253
* use(new Rx());
254+
* use(new Jdbc());
249255
*
250256
* use(new RxJdbc());
251257
*
@@ -269,7 +275,10 @@
269275
* // required by RxJdbc
270276
* use(new Rx());
271277
*
278+
* use(new Jdbc("db.main"));
272279
* use(new RxJdbc("db.main"));
280+
*
281+
* use(new Jdbc("db.audit"));
273282
* use(new RxJdbc("db.audit"));
274283
*
275284
* get("/", req ->
@@ -292,32 +301,36 @@
292301
* @author edgar
293302
* @since 1.0.0.CR3
294303
*/
295-
public class RxJdbc extends Jdbc {
304+
public class RxJdbc implements Jooby.Module {
305+
306+
private final String name;
296307

297308
/**
298309
* Creates a new {@link RxJdbc} module.
299310
*
300311
* @param name Database name.
301312
*/
302313
public RxJdbc(final String name) {
303-
super(name);
314+
this.name = name;
304315
}
305316

306317
/**
307318
* Creates a new {@link RxJdbc} module.
308319
*/
309320
public RxJdbc() {
321+
this("db");
310322
}
311323

312324
@Override
313325
public void configure(final Env env, final Config config, final Binder binder) {
314-
super.configure(env, config, binder, (name, ds) -> {
315-
Database db = Database.fromDataSource(ds);
326+
Key<DataSource> dskey = Key.get(DataSource.class, Names.named(name));
327+
DataSource ds = env.get(dskey)
328+
.orElseThrow(() -> new NoSuchElementException("DataSource missing: " + dskey));
329+
Database db = Database.fromDataSource(ds);
316330

317-
env.serviceKey().generate(Database.class, name, k -> binder.bind(k).toInstance(db));
331+
env.serviceKey().generate(Database.class, name, k -> binder.bind(k).toInstance(db));
318332

319-
// close on shutdown
320-
env.onStop(db::close);
321-
});
333+
// close on shutdown
334+
env.onStop(db::close);
322335
}
323336
}

modules/jooby-rxjava-jdbc/src/test/java/org/jooby/rx/RxJdbcTest.java

Lines changed: 28 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@
88
import com.google.inject.name.Names;
99
import com.typesafe.config.Config;
1010
import com.typesafe.config.ConfigValueFactory;
11+
1112
import static com.typesafe.config.ConfigValueFactory.fromAnyRef;
13+
1214
import com.zaxxer.hikari.HikariConfig;
1315
import com.zaxxer.hikari.HikariDataSource;
16+
1417
import static org.easymock.EasyMock.expect;
1518
import static org.easymock.EasyMock.isA;
19+
1620
import org.jooby.Env;
1721
import org.jooby.test.MockUnit;
1822
import org.jooby.test.MockUnit.Block;
@@ -23,6 +27,9 @@
2327
import org.powermock.modules.junit4.PowerMockRunner;
2428

2529
import javax.sql.DataSource;
30+
import javax.xml.crypto.Data;
31+
import java.util.NoSuchElementException;
32+
import java.util.Optional;
2633
import java.util.Properties;
2734

2835
@RunWith(PowerMockRunner.class)
@@ -32,35 +39,34 @@ public class RxJdbcTest {
3239
private MockUnit.Block onStop = unit -> {
3340
Env env = unit.get(Env.class);
3441
expect(env.onStop(unit.capture(Throwing.Runnable.class))).andReturn(env);
35-
expect(env.onStop(isA(Throwing.Runnable.class))).andReturn(env);
3642
};
3743

3844
@SuppressWarnings("unchecked")
3945
private Block bind = unit -> {
46+
Env env = unit.get(Env.class);
47+
expect(env.serviceKey()).andReturn(new Env.ServiceKey());
48+
49+
DataSource ds = unit.registerMock(DataSource.class);
50+
expect(env.get(Key.get(DataSource.class, Names.named("db")))).andReturn(Optional.of(ds));
51+
4052
unit.mockStatic(Database.class);
4153

4254
Database db = unit.mock(Database.class);
4355
unit.registerMock(Database.class, db);
44-
expect(Database.fromDataSource(unit.get(HikariDataSource.class))).andReturn(db);
56+
expect(Database.fromDataSource(unit.get(DataSource.class))).andReturn(db);
4557

4658
LinkedBindingBuilder<Database> lbb = unit.mock(LinkedBindingBuilder.class);
4759
lbb.toInstance(db);
4860
lbb.toInstance(db);
4961

5062
Binder binder = unit.get(Binder.class);
5163
expect(binder.bind(Key.get(Database.class))).andReturn(lbb);
52-
expect(binder.bind(Key.get(Database.class, Names.named("jdbctest")))).andReturn(lbb);
64+
expect(binder.bind(Key.get(Database.class, Names.named("db")))).andReturn(lbb);
5365
};
5466

5567
@Test
5668
public void configure() throws Exception {
57-
String url = "jdbc:h2:target/jdbctest";
5869
new MockUnit(Env.class, Config.class, Binder.class)
59-
.expect(props("org.h2.jdbcx.JdbcDataSource", url, "h2.jdbctest",
60-
"sa", "", false))
61-
.expect(hikariConfig())
62-
.expect(hikariDataSource())
63-
.expect(serviceKey("jdbctest"))
6470
.expect(bind)
6571
.expect(onStop)
6672
.run(unit -> {
@@ -69,15 +75,22 @@ public void configure() throws Exception {
6975
});
7076
}
7177

78+
@Test(expected = NoSuchElementException.class)
79+
public void noDataSource() throws Exception {
80+
new MockUnit(Env.class, Config.class, Binder.class)
81+
.expect(unit -> {
82+
Env env = unit.get(Env.class);
83+
expect(env.get(Key.get(DataSource.class, Names.named("db")))).andReturn(Optional.empty());
84+
})
85+
.run(unit -> {
86+
new RxJdbc()
87+
.configure(unit.get(Env.class), config(), unit.get(Binder.class));
88+
});
89+
}
90+
7291
@Test
7392
public void withDb() throws Exception {
74-
String url = "jdbc:h2:target/jdbctest";
7593
new MockUnit(Env.class, Config.class, Binder.class)
76-
.expect(props("org.h2.jdbcx.JdbcDataSource", url, "h2.jdbctest",
77-
"sa", "", false))
78-
.expect(hikariConfig())
79-
.expect(hikariDataSource())
80-
.expect(serviceKey("jdbctest"))
8194
.expect(bind)
8295
.expect(onStop)
8396
.run(unit -> {
@@ -88,13 +101,7 @@ public void withDb() throws Exception {
88101

89102
@Test
90103
public void onStop() throws Exception {
91-
String url = "jdbc:h2:target/jdbctest";
92104
new MockUnit(Env.class, Config.class, Binder.class)
93-
.expect(props("org.h2.jdbcx.JdbcDataSource", url, "h2.jdbctest",
94-
"sa", "", false))
95-
.expect(hikariConfig())
96-
.expect(hikariDataSource())
97-
.expect(serviceKey("jdbctest"))
98105
.expect(bind)
99106
.expect(onStop)
100107
.expect(unit -> {
@@ -110,84 +117,7 @@ public void onStop() throws Exception {
110117

111118
private Config config() {
112119
return new RxJdbc().config()
113-
.withValue("db", ConfigValueFactory.fromAnyRef("fs"))
114-
.withValue("application.ns", ConfigValueFactory.fromAnyRef("my.model"))
115-
.withValue("application.tmpdir", ConfigValueFactory.fromAnyRef("target"))
116-
.withValue("application.name", ConfigValueFactory.fromAnyRef("jdbctest"))
117-
.withValue("application.charset", ConfigValueFactory.fromAnyRef("UTF-8"))
118-
.withValue("runtime.processors-x2", fromAnyRef("4"))
119120
.resolve();
120121
}
121122

122-
@SuppressWarnings("unchecked")
123-
private Block serviceKey(final String db) {
124-
return unit -> {
125-
Env env = unit.get(Env.class);
126-
expect(env.serviceKey()).andReturn(new Env.ServiceKey()).times(2);
127-
128-
AnnotatedBindingBuilder<DataSource> binding = unit.mock(AnnotatedBindingBuilder.class);
129-
binding.toInstance(unit.get(HikariDataSource.class));
130-
binding.toInstance(unit.get(HikariDataSource.class));
131-
132-
Binder binder = unit.get(Binder.class);
133-
expect(binder.bind(Key.get(DataSource.class))).andReturn(binding);
134-
expect(binder.bind(Key.get(DataSource.class, Names.named(db)))).andReturn(binding);
135-
};
136-
}
137-
138-
private Block hikariConfig() {
139-
return unit -> {
140-
Properties properties = unit.get(Properties.class);
141-
HikariConfig hikari = unit.constructor(HikariConfig.class)
142-
.build(properties);
143-
unit.registerMock(HikariConfig.class, hikari);
144-
};
145-
}
146-
147-
private Block hikariDataSource() {
148-
return unit -> {
149-
HikariConfig properties = unit.get(HikariConfig.class);
150-
HikariDataSource hikari = unit.constructor(HikariDataSource.class)
151-
.build(properties);
152-
153-
unit.registerMock(HikariDataSource.class, hikari);
154-
};
155-
}
156-
157-
private Block props(final String dataSourceClassName, final String url, final String name,
158-
final String username, final String password, final boolean hasDataSourceClassName) {
159-
return unit -> {
160-
Properties properties = unit.constructor(Properties.class)
161-
.build();
162-
163-
expect(properties
164-
.setProperty("dataSource.dataSourceClassName", dataSourceClassName))
165-
.andReturn(null);
166-
if (username != null) {
167-
expect(properties
168-
.setProperty("dataSource.user", username))
169-
.andReturn(null);
170-
expect(properties
171-
.setProperty("dataSource.password", password))
172-
.andReturn(null);
173-
}
174-
expect(properties
175-
.setProperty("dataSource.url", url))
176-
.andReturn(null);
177-
178-
if (hasDataSourceClassName) {
179-
expect(properties.getProperty("dataSourceClassName")).andReturn(dataSourceClassName);
180-
} else {
181-
expect(properties.getProperty("dataSourceClassName")).andReturn(null);
182-
expect(properties.getProperty("dataSource.dataSourceClassName"))
183-
.andReturn(dataSourceClassName);
184-
expect(properties.setProperty("dataSourceClassName", dataSourceClassName)).andReturn(null);
185-
}
186-
expect(properties.remove("dataSource.dataSourceClassName")).andReturn(dataSourceClassName);
187-
expect(properties.setProperty("poolName", name)).andReturn(null);
188-
expect(properties.setProperty("maximumPoolSize", "4")).andReturn(null);
189-
190-
unit.registerMock(Properties.class, properties);
191-
};
192-
}
193123
}

0 commit comments

Comments
 (0)