Skip to content

Commit 774bd71

Browse files
yholkampjknack
authored andcommitted
Adding support for modules with @provides annotated methods (#1130)
* Adding support for modules with methods annotated with @provides See https://github.com/google/guice/wiki/ProvidesMethods for the typical Guice usage of this feature, which may in some cases improve the readability of simpler modules. * Patching the JoobyTest mock verifications
1 parent 4aebb2e commit 774bd71

File tree

3 files changed

+76
-4
lines changed

3 files changed

+76
-4
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@
220220
import com.google.inject.Provider;
221221
import com.google.inject.Stage;
222222
import com.google.inject.TypeLiteral;
223+
import com.google.inject.internal.ProviderMethodsModule;
223224
import com.google.inject.multibindings.Multibinder;
224225
import com.google.inject.name.Named;
225226
import com.google.inject.name.Names;
@@ -3419,6 +3420,7 @@ private Config defaultConfig(final Config conf, final String cpath) {
34193420
private static void install(final Jooby.Module module, final Env env, final Config config,
34203421
final Binder binder) throws Throwable {
34213422
module.configure(env, config, binder);
3423+
binder.install(ProviderMethodsModule.forObject(module));
34223424
}
34233425

34243426
/**

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.google.inject.binder.ConstantBindingBuilder;
1616
import com.google.inject.binder.LinkedBindingBuilder;
1717
import com.google.inject.binder.ScopedBindingBuilder;
18+
import com.google.inject.internal.ProviderMethodsModule;
1819
import com.google.inject.multibindings.Multibinder;
1920
import com.google.inject.multibindings.OptionalBinder;
2021
import com.google.inject.name.Named;
@@ -23,10 +24,7 @@
2324
import com.typesafe.config.Config;
2425
import com.typesafe.config.ConfigFactory;
2526
import com.typesafe.config.ConfigValueFactory;
26-
import static org.easymock.EasyMock.eq;
27-
import static org.easymock.EasyMock.expect;
28-
import static org.easymock.EasyMock.expectLastCall;
29-
import static org.easymock.EasyMock.isA;
27+
import org.easymock.EasyMock;
3028
import org.jooby.Session.Definition;
3129
import org.jooby.Session.Store;
3230
import org.jooby.internal.AppPrinter;
@@ -60,6 +58,8 @@
6058
import org.jooby.test.MockUnit;
6159
import org.jooby.test.MockUnit.Block;
6260
import org.jooby.funzy.Throwing;
61+
62+
import static org.easymock.EasyMock.*;
6363
import static org.junit.Assert.assertEquals;
6464
import static org.junit.Assert.assertNotNull;
6565
import static org.junit.Assert.assertTrue;
@@ -519,6 +519,8 @@ public Object m1() {
519519
expect(serverBinding.to(isA(Class.class))).andReturn(serverScope).times(0, 1);
520520

521521
Binder binder = unit.get(Binder.class);
522+
binder.install(anyObject(ProviderMethodsModule.class));
523+
EasyMock.expectLastCall().atLeastOnce();
522524
expect(binder.bind(Server.class)).andReturn(serverBinding).times(0, 1);
523525

524526
// ConfigOrigin configOrigin = unit.mock(ConfigOrigin.class);
@@ -574,6 +576,7 @@ public void applicationSecret() throws Exception {
574576
expect(serverBinding.to(isA(Class.class))).andReturn(serverScope).times(0, 1);
575577

576578
Binder binder = unit.get(Binder.class);
579+
binder.install(anyObject(ProviderMethodsModule.class));
577580
expect(binder.bind(Server.class)).andReturn(serverBinding).times(0, 1);
578581

579582
// ConfigOrigin configOrigin = unit.mock(ConfigOrigin.class);
@@ -1059,6 +1062,7 @@ public void stopOnServerFailure() throws Exception {
10591062
expect(serverBinding.to(isA(Class.class))).andReturn(serverScope).times(0, 1);
10601063

10611064
Binder binder = unit.get(Binder.class);
1065+
binder.install(anyObject(ProviderMethodsModule.class));
10621066
expect(binder.bind(Server.class)).andReturn(serverBinding).times(0, 1);
10631067

10641068
// ConfigOrigin configOrigin = unit.mock(ConfigOrigin.class);
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package org.jooby;
2+
3+
import com.google.inject.Binder;
4+
import com.google.inject.Provides;
5+
import com.typesafe.config.Config;
6+
import com.typesafe.config.ConfigFactory;
7+
import org.jooby.mvc.GET;
8+
import org.jooby.mvc.Path;
9+
import org.jooby.test.ServerFeature;
10+
import org.junit.Test;
11+
12+
import javax.inject.Inject;
13+
import javax.inject.Named;
14+
import java.math.BigDecimal;
15+
16+
import static java.util.Objects.requireNonNull;
17+
18+
public class ModuleProvidesFeature extends ServerFeature {
19+
20+
public static class M2 implements Module {
21+
@Override
22+
public void configure(Env env, Config conf, Binder binder) throws Throwable {
23+
}
24+
25+
@Provides
26+
public BigDecimal magicNumber(@Named("m1.prop") final String property) {
27+
return new BigDecimal(42);
28+
}
29+
}
30+
31+
@Path("/p")
32+
public static class ProvidesInject {
33+
34+
private BigDecimal magicNumber;
35+
36+
@Inject
37+
public ProvidesInject(BigDecimal magicNumber) {
38+
this.magicNumber = requireNonNull(magicNumber, "The magicNumber is required.");
39+
}
40+
41+
@GET
42+
@Path("/property")
43+
public Object property() {
44+
return magicNumber;
45+
}
46+
}
47+
48+
{
49+
50+
// don't use application.conf
51+
use(ConfigFactory.empty());
52+
53+
use(new ModulePropertiesFeature.M1());
54+
55+
use(new M2());
56+
57+
use(ProvidesInject.class);
58+
}
59+
60+
@Test
61+
public void providesProperty() throws Exception {
62+
request()
63+
.get("/p/property")
64+
.expect("42");
65+
}
66+
}

0 commit comments

Comments
 (0)