Skip to content

Commit 65c63fb

Browse files
authored
Merge pull request #3844 from kliushnichenko/feat/jakarta-default-value
jakarta default value support
2 parents befcb7f + 0bad11c commit 65c63fb

File tree

8 files changed

+197
-24
lines changed

8 files changed

+197
-24
lines changed

modules/jooby-apt/src/main/java/io/jooby/internal/apt/MvcParameter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,13 +98,13 @@ yield hasAnnotation(NULLABLE)
9898
if (strategy.isEmpty()) {
9999
// must be body
100100
yield ParameterGenerator.BodyParam.toSourceCode(
101-
kt, route, null, type, parameterName, isNullable(kt));
101+
kt, route, null, type, parameter, parameterName, isNullable(kt));
102102
} else {
103103
var paramGenerator = strategy.get().getKey();
104104
paramGenerator.verifyType(parameterType, parameterName, route);
105105

106106
yield paramGenerator.toSourceCode(
107-
kt, route, strategy.get().getValue(), type, parameterName, isNullable(kt));
107+
kt, route, strategy.get().getValue(), type, parameter, parameterName, isNullable(kt));
108108
}
109109
}
110110
};

modules/jooby-apt/src/main/java/io/jooby/internal/apt/ParameterGenerator.java

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@
55
*/
66
package io.jooby.internal.apt;
77

8-
import static io.jooby.internal.apt.AnnotationSupport.findAnnotationValue;
9-
import static io.jooby.internal.apt.Types.BUILT_IN;
10-
import static java.util.stream.Collectors.joining;
11-
8+
import javax.lang.model.element.*;
129
import java.util.*;
1310
import java.util.function.Predicate;
1411
import java.util.stream.Stream;
1512

16-
import javax.lang.model.element.*;
13+
import static io.jooby.internal.apt.AnnotationSupport.findAnnotationValue;
14+
import static io.jooby.internal.apt.Types.BUILT_IN;
15+
import static java.util.stream.Collectors.joining;
1716

1817
public enum ParameterGenerator {
1918
ContextParam("getAttribute", "io.jooby.annotation.ContextParam", "jakarta.ws.rs.core.Context") {
@@ -23,6 +22,7 @@ public String toSourceCode(
2322
MvcRoute route,
2423
AnnotationMirror annotation,
2524
TypeDefinition type,
25+
VariableElement parameter,
2626
String name,
2727
boolean nullable) {
2828
if (type.is(Map.class)) {
@@ -70,6 +70,7 @@ public String toSourceCode(
7070
MvcRoute route,
7171
AnnotationMirror annotation,
7272
TypeDefinition type,
73+
VariableElement parameter,
7374
String name,
7475
boolean nullable) {
7576
var rawType = type.getRawType().toString();
@@ -107,6 +108,7 @@ public String toSourceCode(
107108
MvcRoute route,
108109
AnnotationMirror annotation,
109110
TypeDefinition type,
111+
VariableElement parameter,
110112
String name,
111113
boolean nullable) {
112114
List<Element> converters = new ArrayList<>();
@@ -200,10 +202,11 @@ public String toSourceCode(
200202
MvcRoute route,
201203
AnnotationMirror annotation,
202204
TypeDefinition type,
205+
VariableElement parameter,
203206
String name,
204207
boolean nullable) {
205208
var paramSource = source(annotation);
206-
var builtin = builtinType(kt, annotation, type, name, nullable);
209+
var builtin = builtinType(kt, annotation, type, parameter, name, nullable);
207210
if (builtin == null) {
208211
// List, Set,
209212
var toValue =
@@ -323,10 +326,15 @@ public String toSourceCode(
323326
}
324327

325328
protected String builtinType(
326-
boolean kt, AnnotationMirror annotation, TypeDefinition type, String name, boolean nullable) {
329+
boolean kt,
330+
AnnotationMirror annotation,
331+
TypeDefinition type,
332+
VariableElement parameter,
333+
String name,
334+
boolean nullable) {
327335
if (BUILT_IN.stream().anyMatch(type::is)) {
328336
var paramSource = source(annotation);
329-
var defaultValue = defaultValue(annotation);
337+
var defaultValue = defaultValue(parameter, annotation);
330338
// look at named parameter
331339
if (type.isPrimitive()) {
332340
// like: .intValue
@@ -425,10 +433,19 @@ protected String source(AnnotationMirror annotation) {
425433
return "";
426434
}
427435

428-
protected String defaultValue(AnnotationMirror annotation) {
429-
if (annotation.getAnnotationType().toString().startsWith("io.jooby.annotation")) {
436+
protected String defaultValue(VariableElement parameter, AnnotationMirror annotation) {
437+
var annotationType = annotation.getAnnotationType().toString();
438+
439+
if (annotationType.startsWith("io.jooby.annotation")) {
430440
var sources = findAnnotationValue(annotation, AnnotationSupport.VALUE);
431441
return sources.isEmpty() ? "" : CodeBlock.of(", ", CodeBlock.string(sources.getFirst()));
442+
} else if (annotationType.startsWith("jakarta.ws.rs")) {
443+
var defaultValueAnnotation = AnnotationSupport.findAnnotationByName(
444+
parameter, "jakarta.ws.rs.DefaultValue");
445+
if (defaultValueAnnotation != null) {
446+
var defaultValue = findAnnotationValue(defaultValueAnnotation, AnnotationSupport.VALUE);
447+
return defaultValue.isEmpty() ? "" : CodeBlock.of(", ", CodeBlock.string(defaultValue.getFirst()));
448+
}
432449
}
433450
return "";
434451
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package tests.i3761;
7+
8+
import io.jooby.annotation.GET;
9+
import io.jooby.annotation.Path;
10+
import jakarta.ws.rs.DefaultValue;
11+
import jakarta.ws.rs.QueryParam;
12+
13+
@Path("/3761")
14+
public class C3761Jakarta {
15+
16+
@GET("/number")
17+
public int number(@QueryParam("num") @DefaultValue("5") int num) {
18+
return num;
19+
}
20+
21+
@GET("/unset")
22+
public String unset(@QueryParam("unset") String unset) {
23+
return unset;
24+
}
25+
26+
@GET("/emptySet")
27+
public String emptySet(@QueryParam("emptySet") @DefaultValue("") String emptySet) {
28+
return emptySet;
29+
}
30+
31+
@GET("/stringVal")
32+
public String string(@QueryParam("stringVal") @DefaultValue("Hello") String stringVal) {
33+
return stringVal;
34+
}
35+
}

modules/jooby-apt/src/test/java/tests/i3761/Issue3761.java

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,30 @@
55
*/
66
package tests.i3761;
77

8-
import static org.junit.jupiter.api.Assertions.*;
9-
8+
import io.jooby.apt.ProcessorRunner;
109
import org.junit.jupiter.api.Test;
1110

12-
import io.jooby.apt.ProcessorRunner;
11+
import static org.junit.jupiter.api.Assertions.assertTrue;
1312

1413
public class Issue3761 {
1514
@Test
1615
public void shouldGenerateDefaultValues() throws Exception {
1716
new ProcessorRunner(new C3761())
18-
.withSourceCode(
19-
(source) -> {
20-
assertTrue(source.contains("return c.number(ctx.query(\"num\", \"5\").intValue());"));
21-
assertTrue(source.contains("return c.unset(ctx.query(\"unset\").valueOrNull());"));
22-
assertTrue(
23-
source.contains("return c.emptySet(ctx.query(\"emptySet\", \"\").value());"));
24-
assertTrue(
25-
source.contains("return c.string(ctx.query(\"stringVal\", \"Hello\").value());"));
26-
});
17+
.withSourceCode(Issue3761::assertSourceCodeRespectDefaultValues);
18+
}
19+
20+
@Test
21+
public void shouldGenerateJakartaDefaultValues() throws Exception {
22+
new ProcessorRunner(new C3761Jakarta())
23+
.withSourceCode(Issue3761::assertSourceCodeRespectDefaultValues);
24+
}
25+
26+
private static void assertSourceCodeRespectDefaultValues(String source) {
27+
assertTrue(source.contains("return c.number(ctx.query(\"num\", \"5\").intValue());"));
28+
assertTrue(source.contains("return c.unset(ctx.query(\"unset\").valueOrNull());"));
29+
assertTrue(
30+
source.contains("return c.emptySet(ctx.query(\"emptySet\", \"\").value());"));
31+
assertTrue(
32+
source.contains("return c.string(ctx.query(\"stringVal\", \"Hello\").value());"));
2733
}
2834
}

modules/jooby-openapi/src/main/java/io/jooby/internal/openapi/AnnotationParser.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,20 @@ public Optional<String> getDefaultValue(List<AnnotationNode> annotations) {
122122
}
123123
}
124124
}
125+
return getJakartaDefaultValue(annotations);
126+
}
127+
128+
public Optional<String> getJakartaDefaultValue(List<AnnotationNode> annotations) {
129+
List<Class> names =
130+
Stream.of(annotations()).filter(it -> it.getName().startsWith("jakarta.ws.rs")).toList();
131+
for (var a : annotations) {
132+
if (a.values != null) {
133+
var matches = names.stream().anyMatch(it -> "Ljakarta/ws/rs/DefaultValue;".equals(a.desc));
134+
if (matches) {
135+
return AnnotationUtils.findAnnotationValue(a, "value").map(Objects::toString);
136+
}
137+
}
138+
}
125139
return Optional.empty();
126140
}
127141

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package issues.i3835;
7+
8+
import io.jooby.Jooby;
9+
10+
import static io.jooby.openapi.MvcExtensionGenerator.toMvcExtension;
11+
12+
public class App3835Jakarta extends Jooby {
13+
{
14+
mvc(toMvcExtension(C3835Jakarta.class));
15+
}
16+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Jooby https://jooby.io
3+
* Apache License Version 2.0 https://jooby.io/LICENSE.txt
4+
* Copyright 2014 Edgar Espina
5+
*/
6+
package issues.i3835;
7+
8+
import jakarta.ws.rs.DefaultValue;
9+
import jakarta.ws.rs.GET;
10+
import jakarta.ws.rs.Path;
11+
import jakarta.ws.rs.QueryParam;
12+
13+
import java.util.List;
14+
import java.util.Map;
15+
16+
@Path("/3835")
17+
public class C3835Jakarta {
18+
19+
/**
20+
* Search/scan index.
21+
*
22+
* @param q Search string. Defaults to <code>*</code>
23+
* @return Search result.
24+
*/
25+
@GET
26+
public Map<String, Object> search(
27+
@QueryParam("q") @DefaultValue("*") String q,
28+
@QueryParam("pageSize") @DefaultValue("20") int pageSize,
29+
@QueryParam("page") @DefaultValue("1") int page,
30+
@QueryParam("options") @DefaultValue("--a") List<String> options) {
31+
return null;
32+
}
33+
}

modules/jooby-openapi/src/test/java/issues/i3835/Issue3835.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,56 @@ public void shouldGenerateCorrectName(OpenAPIResult result) {
6363
type: object\
6464
""");
6565
}
66+
67+
@OpenAPITest(value = App3835Jakarta.class)
68+
public void shouldGenerateJakartaDefaultValues(OpenAPIResult result) {
69+
assertThat(result.toYaml())
70+
.isEqualToIgnoringNewLines(
71+
"""
72+
openapi: 3.0.1
73+
info:
74+
title: 3835Jakarta API
75+
description: 3835Jakarta API description
76+
version: "1.0"
77+
paths:
78+
/3835:
79+
get:
80+
summary: Search/scan index.
81+
operationId: search
82+
parameters:
83+
- name: q
84+
in: query
85+
description: Search string. Defaults to *
86+
schema:
87+
type: string
88+
default: '*'
89+
- name: pageSize
90+
in: query
91+
schema:
92+
type: integer
93+
format: int32
94+
default: 20
95+
- name: page
96+
in: query
97+
schema:
98+
type: integer
99+
format: int32
100+
default: 1
101+
- name: options
102+
in: query
103+
schema:
104+
type: array
105+
items:
106+
type: string
107+
responses:
108+
"200":
109+
description: Search result.
110+
content:
111+
application/json:
112+
schema:
113+
type: object
114+
additionalProperties:
115+
type: object\
116+
""");
117+
}
66118
}

0 commit comments

Comments
 (0)