Skip to content

Commit 6556de0

Browse files
committed
bean converter: favor empty constructor when there are multiple constructors. #2068
1 parent c3ec7ed commit 6556de0

3 files changed

Lines changed: 73 additions & 22 deletions

File tree

jooby/src/main/java/io/jooby/internal/converter/ReflectiveBeanConverter.java

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,8 @@
55
*/
66
package io.jooby.internal.converter;
77

8-
import io.jooby.Usage;
9-
import io.jooby.exception.BadRequestException;
10-
import io.jooby.BeanConverter;
11-
import io.jooby.FileUpload;
12-
import io.jooby.exception.MissingValueException;
13-
import io.jooby.Multipart;
14-
import io.jooby.exception.ProvisioningException;
15-
import io.jooby.ValueNode;
16-
import io.jooby.internal.reflect.$Types;
8+
import static io.jooby.SneakyThrows.propagate;
179

18-
import javax.annotation.Nonnull;
19-
import javax.inject.Inject;
20-
import javax.inject.Named;
2110
import java.lang.annotation.Annotation;
2211
import java.lang.reflect.Constructor;
2312
import java.lang.reflect.Executable;
@@ -32,7 +21,19 @@
3221
import java.util.Set;
3322
import java.util.function.Consumer;
3423

35-
import static io.jooby.SneakyThrows.propagate;
24+
import javax.annotation.Nonnull;
25+
import javax.inject.Inject;
26+
import javax.inject.Named;
27+
28+
import io.jooby.BeanConverter;
29+
import io.jooby.FileUpload;
30+
import io.jooby.Multipart;
31+
import io.jooby.Usage;
32+
import io.jooby.ValueNode;
33+
import io.jooby.exception.BadRequestException;
34+
import io.jooby.exception.MissingValueException;
35+
import io.jooby.exception.ProvisioningException;
36+
import io.jooby.internal.reflect.$Types;
3637

3738
public class ReflectiveBeanConverter implements BeanConverter {
3839
private static final String AMBIGUOUS_CONSTRUCTOR =
@@ -72,27 +73,33 @@ private static <T> T newInstance(Class<T> type, ValueNode node)
7273
}
7374

7475
private static Constructor selectConstructor(Constructor[] constructors) {
75-
Constructor result = null;
7676
if (constructors.length == 1) {
77-
result = constructors[0];
77+
return constructors[0];
7878
} else {
79+
Constructor injectConstructor = null;
80+
Constructor defaultConstructor = null;
7981
for (Constructor constructor : constructors) {
8082
if (Modifier.isPublic(constructor.getModifiers())) {
8183
Annotation inject = constructor.getAnnotation(Inject.class);
82-
if (inject != null) {
83-
if (result == null) {
84-
result = constructor;
84+
if (inject == null) {
85+
if (constructor.getParameterCount() == 0) {
86+
defaultConstructor = constructor;
87+
}
88+
} else {
89+
if (injectConstructor == null) {
90+
injectConstructor = constructor;
8591
} else {
8692
throw new IllegalStateException(AMBIGUOUS_CONSTRUCTOR);
8793
}
8894
}
8995
}
9096
}
97+
Constructor result = injectConstructor == null ? defaultConstructor : injectConstructor;
98+
if (result == null) {
99+
throw new IllegalStateException(AMBIGUOUS_CONSTRUCTOR);
100+
}
101+
return result;
91102
}
92-
if (result == null) {
93-
throw new IllegalStateException(AMBIGUOUS_CONSTRUCTOR);
94-
}
95-
return result;
96103
}
97104

98105
public static Object[] inject(ValueNode scope, Executable method, Consumer<ValueNode> state) {
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.jooby.i2068;
2+
3+
public class Bean2068 {
4+
5+
private String name;
6+
7+
public Bean2068(String name) {
8+
this.name = name;
9+
}
10+
11+
public Bean2068() {}
12+
13+
public String getName() {
14+
return name;
15+
}
16+
17+
public void setName(String name) {
18+
this.name = name;
19+
}
20+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.jooby.i2068;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
5+
import io.jooby.junit.ServerTest;
6+
import io.jooby.junit.ServerTestRunner;
7+
8+
public class Issue2068 {
9+
10+
@ServerTest
11+
public void shouldFailIfContextAsServiceWasNotCalled(ServerTestRunner runner) {
12+
runner.define(app -> {
13+
app.get("/i2068", ctx -> {
14+
Bean2068 bean = ctx.query(Bean2068.class);
15+
return bean.getName();
16+
});
17+
}).ready(http -> {
18+
http.get("/i2068?name=foo", rsp -> {
19+
assertEquals("foo", rsp.body().string());
20+
});
21+
});
22+
}
23+
24+
}

0 commit comments

Comments
 (0)