Skip to content

Commit 9626702

Browse files
authored
Merge pull request #99 from SentryMan/javalinJsonB
(Javalin) Avaje JsonB support
2 parents e4febc3 + 85d6f75 commit 9626702

File tree

63 files changed

+3000
-186
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+3000
-186
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ build/
99
*.project
1010
*.processors
1111
*/bin/
12+
*.editorconfig
13+
*.Module

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,6 @@ Javalin.create()
5757
.start();
5858
```
5959

60-
6160
## Usage with Helidon SE
6261

6362
The annotation processor will generate controller classes implementing the Helidon Service interface, which we can use

http-generator-client/src/main/java/io/avaje/http/generator/client/ClientPlatformAdapter.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package io.avaje.http.generator.client;
22

3+
import java.util.List;
4+
35
import io.avaje.http.generator.core.Append;
46
import io.avaje.http.generator.core.ControllerReader;
57
import io.avaje.http.generator.core.ParamType;
68
import io.avaje.http.generator.core.PlatformAdapter;
7-
8-
import java.util.List;
9+
import io.avaje.http.generator.core.UType;
910

1011
class ClientPlatformAdapter implements PlatformAdapter {
1112

@@ -20,7 +21,7 @@ public String platformVariable(String rawType) {
2021
}
2122

2223
@Override
23-
public String bodyAsClass(String shortType) {
24+
public String bodyAsClass(UType uType) {
2425
return null;
2526
}
2627

http-generator-core/src/main/java/io/avaje/http/generator/core/ElementReader.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ void writeCtxGet(Append writer, PathSegments segments) {
206206
return;
207207
}
208208
String shortType = shortType();
209-
writer.append("%s %s %s = ", ctx.platform().indent(), shortType, varName);
209+
writer.append("%s var %s = ", ctx.platform().indent(), varName);
210210
if (setValue(writer, segments, shortType)) {
211211
writer.append(";").eol();
212212
}
@@ -259,7 +259,7 @@ private boolean setValue(Append writer, PathSegments segments, String shortType)
259259

260260
if (typeHandler == null) {
261261
// this is a body (POST, PATCH)
262-
writer.append(ctx.platform().bodyAsClass(shortType));
262+
writer.append(ctx.platform().bodyAsClass(type));
263263

264264
} else {
265265
if (hasParamDefault()) {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package io.avaje.http.generator.core;
2+
3+
import java.util.LinkedHashMap;
4+
import java.util.Map;
5+
import java.util.function.Consumer;
6+
7+
public class JsonBUtil {
8+
private JsonBUtil() {}
9+
10+
public static Map<String, UType> getJsonTypes(ControllerReader reader) {
11+
12+
final Map<String, UType> jsonTypes = new LinkedHashMap<>();
13+
14+
final Consumer<UType> addToMap = uType -> jsonTypes.put(uType.full(), uType);
15+
16+
reader.getMethods().stream()
17+
.filter(MethodReader::isWebMethod)
18+
.filter(m -> !"byte[]".equals(m.getReturnType().toString()))
19+
.filter(m -> m.getProduces() == null || m.getProduces().toLowerCase().contains("json"))
20+
.forEach(
21+
methodReader -> {
22+
addJsonBodyType(methodReader, addToMap);
23+
if (!methodReader.isVoid()) {
24+
addToMap.accept(UType.parse(methodReader.getReturnType()));
25+
}
26+
});
27+
28+
return Map.copyOf(jsonTypes);
29+
}
30+
31+
private static void addJsonBodyType(MethodReader methodReader, Consumer<UType> addToMap) {
32+
if (methodReader.getBodyType() != null) {
33+
methodReader.getParams().stream()
34+
.filter(MethodParam::isBody)
35+
.map(MethodParam::getUType)
36+
.forEach(addToMap);
37+
}
38+
}
39+
40+
public static void writeJsonbType(UType type, Append writer) {
41+
42+
writer.append(" this.%sJsonType = jsonB.type(", type.shortName());
43+
if (!type.isGeneric()) {
44+
writer.append("%s.class)", PrimitiveUtil.wrap(type.full()));
45+
} else {
46+
switch (type.mainType()) {
47+
case "java.util.List":
48+
writer.append("%s.class).list()", type.param0());
49+
break;
50+
case "java.util.Set":
51+
writer.append("%s.class).set()", type.param0());
52+
break;
53+
case "java.util.Map":
54+
writer.append("%s.class).map()", type.param1());
55+
break;
56+
default:
57+
throw new UnsupportedOperationException(
58+
"Only java.util Map, Set and List are supported JsonB Controller Collection Types");
59+
}
60+
}
61+
writer.append(";").eol();
62+
}
63+
}

http-generator-core/src/main/java/io/avaje/http/generator/core/PlatformAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public interface PlatformAdapter {
2121
/**
2222
* Return platform specific code to return the body content.
2323
*/
24-
String bodyAsClass(String shortType);
24+
String bodyAsClass(UType type);
2525

2626
/**
2727
* Return true if body is passed as a method parameter.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package io.avaje.http.generator.core;
2+
3+
import java.util.Map;
4+
5+
public final class PrimitiveUtil {
6+
7+
private PrimitiveUtil() {}
8+
9+
static final Map<String, String> wrapperMap =
10+
Map.of(
11+
"char", "Character",
12+
"byte", "Byte",
13+
"int", "Integer",
14+
"long", "Long",
15+
"short", "Short",
16+
"double", "Double",
17+
"float", "Float",
18+
"boolean", "Boolean");
19+
20+
public static String wrap(String shortName) {
21+
final var wrapped = wrapperMap.get(shortName);
22+
return wrapped != null ? wrapped : shortName;
23+
}
24+
}

http-generator-helidon/src/main/java/io/avaje/http/generator/helidon/HelidonPlatformAdapter.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
package io.avaje.http.generator.helidon;
22

3+
import java.util.List;
4+
35
import io.avaje.http.generator.core.Append;
46
import io.avaje.http.generator.core.ControllerReader;
57
import io.avaje.http.generator.core.ParamType;
68
import io.avaje.http.generator.core.PlatformAdapter;
7-
8-
import java.util.List;
9+
import io.avaje.http.generator.core.UType;
910

1011
class HelidonPlatformAdapter implements PlatformAdapter {
1112

@@ -38,7 +39,7 @@ public boolean isBodyMethodParam() {
3839
}
3940

4041
@Override
41-
public String bodyAsClass(String shortType) {
42+
public String bodyAsClass(UType uType) {
4243
return "body";
4344
}
4445

http-generator-javalin/src/main/java/io/avaje/http/generator/javalin/ControllerMethodWriter.java

Lines changed: 42 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,53 +6,56 @@
66
import io.avaje.http.generator.core.MethodReader;
77
import io.avaje.http.generator.core.PathSegments;
88
import io.avaje.http.generator.core.ProcessingContext;
9+
import io.avaje.http.generator.core.UType;
910
import io.avaje.http.generator.core.Util;
1011
import io.avaje.http.generator.core.WebMethod;
1112

12-
import java.util.List;
13-
14-
/**
15-
* Write code to register Web route for a given controller method.
16-
*/
13+
/** Write code to register Web route for a given controller method. */
1714
class ControllerMethodWriter {
1815

1916
private final MethodReader method;
2017
private final Append writer;
2118
private final WebMethod webMethod;
2219
private final ProcessingContext ctx;
20+
private final boolean useJsonB;
2321

24-
ControllerMethodWriter(MethodReader method, Append writer, ProcessingContext ctx) {
22+
ControllerMethodWriter(
23+
MethodReader method, Append writer, ProcessingContext ctx, boolean useJsonB) {
2524
this.method = method;
2625
this.writer = writer;
2726
this.webMethod = method.getWebMethod();
2827
this.ctx = ctx;
28+
this.useJsonB = useJsonB;
2929
}
3030

3131
void write(boolean requestScoped) {
3232

33-
final PathSegments segments = method.getPathSegments();
34-
final String fullPath = segments.fullPath();
33+
final var segments = method.getPathSegments();
34+
final var fullPath = segments.fullPath();
3535

36-
writer.append(" ApiBuilder.%s(\"%s\", ctx -> {", webMethod.name().toLowerCase(), fullPath).eol();
36+
writer
37+
.append(" ApiBuilder.%s(\"%s\", ctx -> {", webMethod.name().toLowerCase(), fullPath)
38+
.eol();
3739
writer.append(" ctx.status(%s);", method.getStatusCode()).eol();
3840

39-
List<PathSegments.Segment> matrixSegments = segments.matrixSegments();
40-
for (PathSegments.Segment matrixSegment : matrixSegments) {
41+
final var matrixSegments = segments.matrixSegments();
42+
for (final PathSegments.Segment matrixSegment : matrixSegments) {
4143
matrixSegment.writeCreateSegment(writer, ctx.platform());
4244
}
4345

44-
final List<MethodParam> params = method.getParams();
45-
for (MethodParam param : params) {
46+
final var params = method.getParams();
47+
for (final MethodParam param : params) {
4648
param.writeCtxGet(writer, segments);
4749
}
4850
writer.append(" ");
4951
if (method.includeValidate()) {
50-
for (MethodParam param : params) {
52+
for (final MethodParam param : params) {
5153
param.writeValidate(writer);
5254
}
5355
}
56+
5457
if (!method.isVoid()) {
55-
writeContextReturn();
58+
writer.append("var result = ");
5659
}
5760

5861
if (requestScoped) {
@@ -61,23 +64,25 @@ void write(boolean requestScoped) {
6164
writer.append("controller.");
6265
}
6366
writer.append(method.simpleName()).append("(");
64-
for (int i = 0; i < params.size(); i++) {
67+
for (var i = 0; i < params.size(); i++) {
6568
if (i > 0) {
6669
writer.append(", ");
6770
}
6871
params.get(i).buildParamName(writer);
6972
}
70-
writer.append(")");
73+
74+
writer.append(");").eol();
7175
if (!method.isVoid()) {
72-
writer.append(")");
76+
writeContextReturn();
77+
writer.eol();
7378
}
74-
writer.append(";").eol();
79+
7580
writer.append(" }");
7681

77-
List<String> roles = method.roles();
82+
final var roles = method.roles();
7883
if (!roles.isEmpty()) {
7984
writer.append(", ");
80-
for (int i = 0; i < roles.size(); i++) {
85+
for (var i = 0; i < roles.size(); i++) {
8186
if (i > 0) {
8287
writer.append(", ");
8388
}
@@ -88,15 +93,23 @@ void write(boolean requestScoped) {
8893
}
8994

9095
private void writeContextReturn() {
91-
final String produces = method.getProduces();
92-
if (produces == null || produces.equalsIgnoreCase(MediaType.APPLICATION_JSON)) {
93-
writer.append("ctx.json(");
94-
} else if (produces.equalsIgnoreCase(MediaType.TEXT_HTML)) {
95-
writer.append("ctx.html(");
96-
} else if (produces.equalsIgnoreCase(MediaType.TEXT_PLAIN)) {
97-
writer.append("ctx.contentType(\"text/plain\").result(");
96+
final var produces = method.getProduces();
97+
if (produces == null || MediaType.APPLICATION_JSON.equalsIgnoreCase(produces)) {
98+
if (useJsonB) {
99+
final var uType = UType.parse(method.getReturnType());
100+
writer.append(
101+
" %sJsonType.toJson(result, ctx.contentType(\"application/json\").outputStream());",
102+
uType.shortName());
103+
104+
} else {
105+
writer.append(" ctx.json(result);");
106+
}
107+
} else if (MediaType.TEXT_HTML.equalsIgnoreCase(produces)) {
108+
writer.append(" ctx.html(result);");
109+
} else if (MediaType.TEXT_PLAIN.equalsIgnoreCase(produces)) {
110+
writer.append(" ctx.contentType(\"text/plain\").result(result);");
98111
} else {
99-
writer.append("ctx.contentType(\"%s\").result(", produces);
112+
writer.append(" ctx.contentType(\"%s\").result(result);", produces);
100113
}
101114
}
102115
}

0 commit comments

Comments
 (0)