Skip to content

Commit 31a2ec6

Browse files
committed
#36 - Support @Inject of Javalin Context and Helidon ServerRequest/ServerResponse
1 parent d4ce779 commit 31a2ec6

File tree

16 files changed

+240
-48
lines changed

16 files changed

+240
-48
lines changed

generator-core/src/main/java/io/dinject/webroutegen/BaseControllerWriter.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ public BaseControllerWriter(ControllerReader reader, ProcessingContext ctx) thro
3030
initWriter();
3131
}
3232

33+
protected boolean isRequestScoped() {
34+
return reader.isRequestScoped();
35+
}
36+
3337
protected String initPackageName(String originName) {
3438
int dp = originName.lastIndexOf('.');
3539
return dp > -1 ? originName.substring(0, dp) : null;

generator-core/src/main/java/io/dinject/webroutegen/ControllerReader.java

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,15 @@ class ControllerReader {
4646
*/
4747
private final String produces;
4848

49-
private boolean docHidden;
50-
5149
private final boolean includeValidator;
5250

51+
/**
52+
* Flag set when the controller is dependant on a request scope type.
53+
*/
54+
private boolean requestScope;
55+
56+
private boolean docHidden;
57+
5358
ControllerReader(TypeElement beanType, ProcessingContext ctx) {
5459
this.beanType = beanType;
5560
this.ctx = ctx;
@@ -70,14 +75,11 @@ class ControllerReader {
7075
if (includeValidator) {
7176
importTypes.add(Constants.VALIDATOR);
7277
}
73-
7478
this.produces = initProduces();
7579
}
7680

7781
private List<Element> initInterfaces() {
78-
7982
List<Element> interfaces = new ArrayList<>();
80-
8183
for (TypeMirror anInterface : beanType.getInterfaces()) {
8284
final Element ifaceElement = ctx.asElement(anInterface);
8385
if (ifaceElement.getAnnotation(Path.class) != null) {
@@ -88,7 +90,6 @@ private List<Element> initInterfaces() {
8890
}
8991

9092
private List<ExecutableElement> initInterfaceMethods() {
91-
9293
List<ExecutableElement> ifaceMethods = new ArrayList<>();
9394
for (Element anInterface : interfaces) {
9495
ifaceMethods.addAll(ElementFilter.methodsIn(anInterface.getEnclosedElements()));
@@ -111,7 +112,6 @@ private <A extends Annotation> A findAnnotation(Class<A> type) {
111112
}
112113

113114
<A extends Annotation> A findMethodAnnotation(Class<A> type, ExecutableElement element) {
114-
115115
for (ExecutableElement interfaceMethod : interfaceMethods) {
116116
if (matchMethod(interfaceMethod, element)) {
117117
final A annotation = interfaceMethod.getAnnotation(type);
@@ -120,7 +120,6 @@ <A extends Annotation> A findMethodAnnotation(Class<A> type, ExecutableElement e
120120
}
121121
}
122122
}
123-
124123
return null;
125124
}
126125

@@ -157,34 +156,49 @@ boolean isIncludeValidator() {
157156
return includeValidator;
158157
}
159158

159+
/**
160+
* Return true if the controller has request scoped dependencies.
161+
* In that case a BeanFactory will have been generated.
162+
*/
163+
boolean isRequestScoped() {
164+
return requestScope;
165+
}
166+
160167
void read() {
161168
if (!roles.isEmpty()) {
162169
ctx.platform().controllerRoles(roles, this);
163170
}
164-
165171
for (Element element : beanType.getEnclosedElements()) {
166172
if (element.getKind() == ElementKind.METHOD) {
167173
readMethod((ExecutableElement) element);
174+
} else if (element.getKind() == ElementKind.FIELD) {
175+
readField(element);
168176
}
169177
}
170-
171178
readSuper(beanType);
172179
}
173180

181+
private void readField(Element element) {
182+
if (!requestScope) {
183+
final String rawType = element.asType().toString();
184+
requestScope = RequestScopeTypes.isRequestType(rawType);
185+
}
186+
}
187+
174188
/**
175189
* Read methods from superclasses taking into account generics.
176190
*/
177191
private void readSuper(TypeElement beanType) {
178-
179192
TypeMirror superclass = beanType.getSuperclass();
180193
if (superclass.getKind() != TypeKind.NONE) {
181194
DeclaredType declaredType = (DeclaredType) superclass;
182-
183195
final Element superElement = ctx.asElement(superclass);
184196
if (!"java.lang.Object".equals(superElement.toString())) {
185197
for (Element element : superElement.getEnclosedElements()) {
186198
if (element.getKind() == ElementKind.METHOD) {
187199
readMethod((ExecutableElement) element, declaredType);
200+
} else if (element.getKind() == ElementKind.FIELD) {
201+
readField(element);
188202
}
189203
}
190204
if (superElement instanceof TypeElement) {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.dinject.webroutegen;
2+
3+
import java.util.HashSet;
4+
import java.util.Set;
5+
6+
class RequestScopeTypes {
7+
8+
private static final String JAVALIN_CONTEXT = "io.javalin.http.Context";
9+
private static final String HELIDON_REQ = "io.helidon.webserver.ServerRequest";
10+
private static final String HELIDON_RES = "io.helidon.webserver.ServerResponse";
11+
private static final Set<String> TYPES = new HashSet<>();
12+
13+
static {
14+
TYPES.add(JAVALIN_CONTEXT);
15+
TYPES.add(HELIDON_REQ);
16+
TYPES.add(HELIDON_RES);
17+
}
18+
19+
/**
20+
* Return true if the type is a request scoped type.
21+
*/
22+
static boolean isRequestType(String rawType) {
23+
return TYPES.contains(rawType);
24+
}
25+
}

generator-helidon/src/main/java/io/dinject/webroutegen/ControllerMethodWriter.java

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ void writeRule() {
3333
}
3434
}
3535

36-
void writeHandler() {
36+
void writeHandler(boolean requestScoped) {
3737
writer.append(" private void _%s(ServerRequest req, ServerResponse res", method.simpleName());
3838
final String bodyType = method.getBodyType();
3939
if (bodyType != null) {
@@ -66,8 +66,11 @@ void writeHandler() {
6666
param.writeValidate(writer);
6767
}
6868
}
69-
70-
writer.append("controller.");
69+
if (requestScoped) {
70+
writer.append("factory.create(req, res).");
71+
} else {
72+
writer.append("controller.");
73+
}
7174
writer.append(method.simpleName()).append("(");
7275
for (int i = 0; i < params.size(); i++) {
7376
if (i > 0) {
@@ -81,22 +84,6 @@ void writeHandler() {
8184
}
8285
writer.append(";").eol();
8386
writer.append(" }").eol().eol();
84-
85-
// List<String> roles = method.roles();
86-
// if (!roles.isEmpty()) {
87-
// writer.append(", roles(");
88-
// for (int i = 0; i < roles.size(); i++) {
89-
// if (i > 0) {
90-
// writer.append(", ");
91-
// }
92-
// writer.append(Util.shortName(roles.get(i)));
93-
// }
94-
// writer.append(")");
95-
// }
96-
// writer.append(");").eol().eol();
97-
98-
// writer.append(" res.send(\"Hello\");").eol();
99-
// writer.append(" }").eol();
10087
}
10188

10289
private void writeContextReturn() {

generator-helidon/src/main/java/io/dinject/webroutegen/ControllerWriter.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ private void writeAddRoutes() {
4040
final List<ControllerMethodWriter> methods = getWriterMethods();
4141
writeRoutes(methods);
4242
for (ControllerMethodWriter methodWriter : methods) {
43-
writeHandlerMethod(methodWriter);
43+
methodWriter.writeHandler(isRequestScoped());
4444
}
4545
}
4646

@@ -56,29 +56,31 @@ private void writeRoutes(List<ControllerMethodWriter> methods) {
5656
writer.append(" }").eol().eol();
5757
}
5858

59-
private void writeHandlerMethod(ControllerMethodWriter methodWriter) {
60-
methodWriter.writeHandler();
61-
}
62-
6359
private void writeClassStart() {
6460
if (ctx.isGeneratedAvailable()) {
6561
writer.append(AT_GENERATED).eol();
6662
}
6763
writer.append("@Singleton").eol();
6864
writer.append("public class ").append(shortName).append("$route implements Service {").eol().eol();
6965

70-
writer.append(" private final %s controller;", shortName).eol();
66+
String controllerName = "controller";
67+
String controllerType = shortName;
68+
if (isRequestScoped()) {
69+
controllerName = "factory";
70+
controllerType += "$factory";
71+
}
72+
writer.append(" private final %s %s;", controllerType, controllerName).eol();
7173
if (reader.isIncludeValidator()) {
7274
writer.append(" private final Validator validator;").eol();
7375
}
7476
writer.eol();
7577

76-
writer.append(" public %s$route(%s controller", shortName, shortName);
78+
writer.append(" public %s$route(%s %s", shortName, controllerType, controllerName);
7779
if (reader.isIncludeValidator()) {
7880
writer.append(", Validator validator");
7981
}
8082
writer.append(") {").eol();
81-
writer.append(" this.controller = controller;").eol();
83+
writer.append(" this.%s = %s;", controllerName, controllerName).eol();
8284
if (reader.isIncludeValidator()) {
8385
writer.append(" this.validator = validator;").eol();
8486
}

generator-javalin/src/main/java/io/dinject/webroutegen/ControllerMethodWriter.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class ControllerMethodWriter {
2121
this.ctx = ctx;
2222
}
2323

24-
void write() {
24+
void write(boolean requestScoped) {
2525

2626
final PathSegments segments = method.getPathSegments();
2727
final String fullPath = segments.fullPath();
@@ -48,7 +48,11 @@ void write() {
4848
writeContextReturn();
4949
}
5050

51-
writer.append("controller.");
51+
if (requestScoped) {
52+
writer.append("factory.create(ctx).");
53+
} else {
54+
writer.append("controller.");
55+
}
5256
writer.append(method.simpleName()).append("(");
5357
for (int i = 0; i < params.size(); i++) {
5458
if (i > 0) {

generator-javalin/src/main/java/io/dinject/webroutegen/ControllerWriter.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ private void writeAddRoutes() {
3535
}
3636

3737
private void writeForMethod(MethodReader method) {
38-
new ControllerMethodWriter(method, writer, ctx).write();
38+
new ControllerMethodWriter(method, writer, ctx).write(isRequestScoped());
3939
if (!reader.isDocHidden()) {
4040
method.buildApiDocumentation(ctx);
4141
}
@@ -48,18 +48,25 @@ private void writeClassStart() {
4848
writer.append("@Singleton").eol();
4949
writer.append("public class ").append(shortName).append("$route implements WebRoutes {").eol().eol();
5050

51-
writer.append(" private final %s controller;", shortName).eol();
51+
String controllerName = "controller";
52+
String controllerType = shortName;
53+
if (isRequestScoped()) {
54+
controllerName = "factory";
55+
controllerType += "$factory";
56+
}
57+
writer.append(" private final %s %s;", controllerType, controllerName).eol();
58+
5259
if (reader.isIncludeValidator()) {
5360
writer.append(" private final Validator validator;").eol();
5461
}
5562
writer.eol();
5663

57-
writer.append(" public %s$route(%s controller", shortName, shortName);
64+
writer.append(" public %s$route(%s %s", shortName, controllerType, controllerName);
5865
if (reader.isIncludeValidator()) {
5966
writer.append(", Validator validator");
6067
}
6168
writer.append(") {").eol();
62-
writer.append(" this.controller = controller;").eol();
69+
writer.append(" this.%s = %s;", controllerName, controllerName).eol();
6370
if (reader.isIncludeValidator()) {
6471
writer.append(" this.validator = validator;").eol();
6572
}

tests/test-helidon/pom.xml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<properties>
1818
<mainClass>org.example.Main</mainClass>
1919
<helidon-version>2.0.1</helidon-version>
20-
<dinject-version>2.2</dinject-version>
20+
<dinject-version>2.3</dinject-version>
2121
<dinject-controller-version>1.22-SNAPSHOT</dinject-controller-version>
2222
</properties>
2323

@@ -107,6 +107,12 @@
107107
<version>4.3.1</version>
108108
<scope>test</scope>
109109
</dependency>
110+
<dependency>
111+
<groupId>org.avaje.beta.http</groupId>
112+
<artifactId>http-client</artifactId>
113+
<version>0.1-SNAPSHOT</version>
114+
<scope>test</scope>
115+
</dependency>
110116

111117
</dependencies>
112118

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.example;
2+
3+
import io.dinject.controller.Controller;
4+
import io.dinject.controller.Get;
5+
import io.dinject.controller.Path;
6+
import io.dinject.controller.Produces;
7+
import io.helidon.webserver.ServerRequest;
8+
import io.helidon.webserver.ServerResponse;
9+
10+
import javax.inject.Inject;
11+
12+
@Controller
13+
@Path("/req-scoped")
14+
public class ReqScopedController {
15+
16+
@Inject
17+
ServerRequest request;
18+
19+
@Inject
20+
ServerResponse response;
21+
22+
@Produces("text/plain")
23+
@Get
24+
String getSimple() {
25+
return request.uri().toString() + "-" + response.status();
26+
}
27+
}

tests/test-helidon/src/test/java/org/example/BaseWebTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package org.example;
22

3+
import com.fasterxml.jackson.databind.ObjectMapper;
4+
import io.avaje.http.client.HttpClientContext;
5+
import io.avaje.http.client.JacksonBodyAdapter;
6+
import io.avaje.http.client.RequestLogger;
37
import io.helidon.webserver.WebServer;
48
import org.junit.jupiter.api.AfterAll;
59
import org.junit.jupiter.api.BeforeAll;
@@ -20,4 +24,13 @@ public static void init() {
2024
public static void shutdown() {
2125
webServer.shutdown();
2226
}
27+
28+
public static HttpClientContext client() {
29+
return HttpClientContext.newBuilder()
30+
.withBaseUrl(baseUrl)
31+
.withRequestListener(new RequestLogger())
32+
.withBodyAdapter(new JacksonBodyAdapter(new ObjectMapper()))
33+
//.with(httpClient)
34+
.build();
35+
}
2336
}

0 commit comments

Comments
 (0)