Skip to content

Commit c7bb907

Browse files
committed
RelfectiveBeanConverter issue - not decoding HashValue with contructor injection fix #1531
1 parent 7a40f25 commit c7bb907

File tree

5 files changed

+153
-12
lines changed

5 files changed

+153
-12
lines changed

docs/asciidoc/usage/usage.adoc

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Kotlin build also requires it via https://kotlinlang.org/docs/reference/kapt.htm
2828
<plugins>
2929
<plugin>
3030
<artifactId>maven-compiler-plugin</artifactId>
31-
<version>${maven-compiler-plugin.version}</version>
31+
<version>{mavenCompilerPluginVersion}</version>
3232
<configuration>
3333
<annotationProcessorPaths>
3434
<path>
@@ -51,7 +51,7 @@ Kotlin build also requires it via https://kotlinlang.org/docs/reference/kapt.htm
5151
<plugin>
5252
<artifactId>kotlin-maven-plugin</artifactId>
5353
<groupId>org.jetbrains.kotlin</groupId>
54-
<version>${kotlin.version}</version>
54+
<version>{kotlinVersion}</version>
5555
<configuration>
5656
<args>
5757
<arg>-java-parameters</arg>
@@ -101,7 +101,7 @@ Kotlin build also requires it via https://kotlinlang.org/docs/reference/kapt.htm
101101
<annotationProcessorPath>
102102
<groupId>io.jooby</groupId>
103103
<artifactId>jooby-apt</artifactId>
104-
<version>${jooby.version}</version>
104+
<version>{joobyVersion}</version>
105105
</annotationProcessorPath>
106106
</annotationProcessorPaths>
107107
</configuration>
@@ -130,20 +130,20 @@ Java build needs an annotationProcessor statement using `jooby-apt`.
130130
Kotlin builds needs a https://kotlinlang.org/docs/reference/kapt.html#using-in-gradle[kapt] dependency and statement using `jooby-apt`.
131131

132132
.Java
133-
[source, groovy, role="primary"]
133+
[source, groovy, role="primary", subs="verbatim,attributes"]
134134
----
135135
dependencies {
136136
annotationProcessor "io.jooby:jooby-apt:{joobyVersion}"
137137
}
138138
----
139139

140140
.Kotlin
141-
[source, groovy, role="secondary"]
141+
[source, groovy, role="secondary", subs="verbatim,attributes"]
142142
----
143143
buildscript {
144144
...
145145
dependencies {
146-
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
146+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:{kotlinVersion}"
147147
}
148148
}
149149
@@ -184,3 +184,78 @@ Alternatively, you can delegate IntelliJ build/run actions to Maven or Gradle co
184184
*Eclipse 4.9+*
185185

186186
You need https://www.eclipse.org/m2e/[M2Eclipse] for Maven or https://projects.eclipse.org/projects/tools.buildship[Gradle Buildship]
187+
188+
== Bean Converter
189+
190+
=== Parameter Name Missing
191+
192+
*Exception*:
193+
194+
----
195+
Unable to provision parameter at position: '...', require by: ... Parameter's name is missing
196+
----
197+
198+
Thrown when the bean converter has no access to a parameter name at runtime. Compilation must be
199+
done using `parameters` compiler option.
200+
201+
*Maven Solution*
202+
203+
.Java
204+
[source, xml, role = "primary", subs="verbatim,attributes"]
205+
----
206+
<build>
207+
<plugins>
208+
<plugin>
209+
<artifactId>maven-compiler-plugin</artifactId>
210+
<version>{mavenCompilerPluginVersion}</version>
211+
<configuration>
212+
...
213+
<compilerArgs>
214+
<arg>-parameters</arg>
215+
</compilerArgs>
216+
</configuration>
217+
</plugin>
218+
</plugins>
219+
</build>
220+
----
221+
222+
.Kotlin
223+
[source, xml, role = "secondary", subs="verbatim,attributes"]
224+
----
225+
<build>
226+
<plugins>
227+
<plugin>
228+
<artifactId>kotlin-maven-plugin</artifactId>
229+
<groupId>org.jetbrains.kotlin</groupId>
230+
<version>{kotlinVersion}</version>
231+
<configuration>
232+
...
233+
<args>
234+
<arg>-java-parameters</arg>
235+
</args>
236+
<jvmTarget>1.8</jvmTarget>
237+
...
238+
</configuration>
239+
</plugin>
240+
</plugins>
241+
</build>
242+
----
243+
244+
*Gradle Solution*
245+
246+
.Java
247+
[source, groovy, role = "primary", subs="verbatim,attributes"]
248+
----
249+
tasks.withType(JavaCompile) {
250+
options.compilerArgs << '-parameters'
251+
options.debug = true
252+
}
253+
----
254+
255+
.Kotlin
256+
[source, groovy, role = "secondary", subs="verbatim,attributes"]
257+
----
258+
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
259+
kotlinOptions.javaParameters = true
260+
}
261+
----

jooby/src/main/java/io/jooby/Usage.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,30 @@
55
*/
66
package io.jooby;
77

8+
import io.jooby.exception.ProvisioningException;
9+
810
import javax.annotation.Nonnull;
11+
import java.lang.reflect.Executable;
12+
import java.lang.reflect.Parameter;
13+
import java.util.stream.Collectors;
14+
import java.util.stream.Stream;
915

1016
/**
1117
* Usage exceptions. They provide a descriptive message with a link for a detailed section.
1218
*
1319
* @since 2.1.0
1420
*/
1521
public class Usage extends RuntimeException {
22+
1623
/**
1724
* Creates a new Usage exception.
1825
*
1926
* @param message Message.
2027
* @param id Link to detailed section.
2128
*/
2229
public Usage(@Nonnull String message, @Nonnull String id) {
23-
super((message + "\nFor more details, please visit: https://jooby.io/usage#" + id));
30+
super((message + "\nFor more details, please visit: " + System
31+
.getProperty("jooby.host", "https://jooby.io") + "/usage#" + id));
2432
}
2533

2634
/**
@@ -34,6 +42,22 @@ public Usage(@Nonnull String message, @Nonnull String id) {
3442
+ "`. Make sure Jooby annotation processor is configured properly.", "router-not-found");
3543
}
3644

45+
/**
46+
* Thrown when the reflective bean converter has no access to a parameter name. Compilation
47+
* must be done using <code>parameters</code> compiler option.
48+
*
49+
* @param parameter Parameter.
50+
* @return Usage exception.
51+
*/
52+
public static @Nonnull Usage parameterNameNotPresent(@Nonnull Parameter parameter) {
53+
Executable executable = parameter.getDeclaringExecutable();
54+
int p = Stream.of(executable.getParameters()).collect(Collectors.toList()).indexOf(parameter);
55+
String message = "Unable to provision parameter at position: '" + p + "', require by: "
56+
+ ProvisioningException.toString(parameter.getDeclaringExecutable())
57+
+ ". Parameter's name is missing";
58+
return new Usage(message, "bean-converter-parameter-name-missing");
59+
}
60+
3761
private static Usage apt(String message, String id) {
3862
return new Usage(message, "annotation-processing-tool-" + id);
3963
}

jooby/src/main/java/io/jooby/exception/ProvisioningException.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,23 @@ public ProvisioningException(@Nonnull String message, @Nonnull Throwable cause)
4141
super(message, cause);
4242
}
4343

44-
private static String toString(Parameter parameter) {
44+
/**
45+
* Creates a parameter description.
46+
*
47+
* @param parameter Parameter.
48+
* @return Description.
49+
*/
50+
public static String toString(@Nonnull Parameter parameter) {
4551
return parameter.getName() + ": " + parameter.getParameterizedType();
4652
}
4753

48-
private static String toString(Executable method) {
54+
/**
55+
* Creates a method description.
56+
*
57+
* @param method Parameter.
58+
* @return Description.
59+
*/
60+
public static String toString(@Nonnull Executable method) {
4961
StringBuilder buff = new StringBuilder();
5062
if (method instanceof Constructor) {
5163
buff.append("constructor ");

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

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

8+
import io.jooby.Usage;
89
import io.jooby.exception.BadRequestException;
910
import io.jooby.BeanConverter;
1011
import io.jooby.FileUpload;
@@ -111,12 +112,14 @@ public static Object[] inject(ValueNode scope, Executable method, Consumer<Value
111112
}
112113

113114
private static String paramName(Parameter parameter) {
114-
String name = parameter.getName();
115115
Named named = parameter.getAnnotation(Named.class);
116116
if (named != null && named.value().length() > 0) {
117-
name = named.value();
117+
return named.value();
118118
}
119-
return name;
119+
if (parameter.isNamePresent()) {
120+
return parameter.getName();
121+
}
122+
throw Usage.parameterNameNotPresent(parameter);
120123
}
121124

122125
private static <T> T setters(T newInstance, ValueNode node, Set<ValueNode> skip) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package io.jooby;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.lang.reflect.Method;
6+
7+
import static org.junit.jupiter.api.Assertions.assertEquals;
8+
9+
public class UsageTest {
10+
11+
static {
12+
System.setProperty("jooby.host", "http://localhost:4000");
13+
}
14+
15+
@Test
16+
public void parameterNameMissing() throws NoSuchMethodException {
17+
Method method = getClass().getDeclaredMethod("parameterMissing", String.class);
18+
Usage usage = Usage.parameterNameNotPresent(method.getParameters()[0]);
19+
assertEquals("Unable to provision parameter at position: '0', require by: method io.jooby.UsageTest.parameterMissing(java.lang.String). Parameter's name is missing\n"
20+
+ "For more details, please visit: http://localhost:4000/usage#bean-converter-parameter-name-missing", usage.getMessage());
21+
}
22+
23+
public void parameterMissing(String some) {
24+
25+
}
26+
27+
}

0 commit comments

Comments
 (0)