Skip to content

Commit 38ddee8

Browse files
committed
#118 - Add compile error when @singleton has a @request scope dependency
1 parent fcc7be9 commit 38ddee8

File tree

8 files changed

+85
-15
lines changed

8 files changed

+85
-15
lines changed

inject-generator/src/main/java/io/avaje/inject/generator/BeanReader.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
class BeanReader {
1111

12+
private final ProcessingContext context;
1213
private final TypeElement beanType;
1314
private final String shortName;
1415
private final String type;
@@ -32,6 +33,7 @@ class BeanReader {
3233

3334
BeanReader(TypeElement beanType, ProcessingContext context, boolean factory) {
3435
this.beanType = beanType;
36+
this.context = context;
3537
this.type = beanType.getQualifiedName().toString();
3638
this.shortName = shortName(beanType);
3739
this.primary = (beanType.getAnnotation(Primary.class) != null);
@@ -40,7 +42,7 @@ class BeanReader {
4042

4143
typeReader.process();
4244
this.requestScopedBean = typeReader.isRequestScopeBean();
43-
this.requestParams = new BeanRequestParams(type, requestScopedBean);
45+
this.requestParams = new BeanRequestParams(context, type, requestScopedBean);
4446
this.name = typeReader.getName();
4547
this.injectMethods = typeReader.getInjectMethods();
4648
this.injectFields = typeReader.getInjectFields();
@@ -146,6 +148,9 @@ boolean isExtraInjectionRequired() {
146148
}
147149

148150
void buildAddFor(Append writer) {
151+
if (requestParams.isRequestParam()) {
152+
context.logError(beanType, "@Singleton %s is not allowed to have a @Request scope dependency %s", shortName, requestParams.getRequestParamType());
153+
}
149154
writer.append(" if (builder.isAddBeanFor(");
150155
if (name != null && !name.isEmpty()) {
151156
writer.append("\"%s\", ", name);

inject-generator/src/main/java/io/avaje/inject/generator/BeanRequestParams.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,36 @@
11
package io.avaje.inject.generator;
22

3+
import io.avaje.inject.Request;
4+
5+
import javax.lang.model.element.TypeElement;
36
import java.util.Set;
47

58
/**
69
* Holds detection and details of request scoped dependencies.
710
*/
811
class BeanRequestParams {
912

13+
private final ProcessingContext context;
1014
private final String parentType;
1115
private final boolean requestScopedBean;
1216

1317
private RequestScope.Handler reqScopeHandler;
18+
private String requestParamType;
1419

15-
BeanRequestParams(String parentType, boolean requestScopedBean) {
20+
BeanRequestParams(ProcessingContext context, String parentType, boolean requestScopedBean) {
21+
this.context = context;
1622
this.parentType = parentType;
1723
this.requestScopedBean = requestScopedBean;
1824
}
1925

26+
boolean isRequestParam() {
27+
return requestParamType != null;
28+
}
29+
30+
String getRequestParamType() {
31+
return requestParamType;
32+
}
33+
2034
/**
2135
* Return true if this type is a request scoped type (e.g. Javalin Context).
2236
*/
@@ -31,6 +45,14 @@ boolean check(String paramType) {
3145
}
3246
return true;
3347
}
48+
if (paramType != null && requestParamType == null) {
49+
final TypeElement element = context.element(paramType);
50+
if (element != null) {
51+
if (element.getAnnotation(Request.class) != null) {
52+
requestParamType = paramType;
53+
}
54+
}
55+
}
3456
return false;
3557
}
3658

inject-generator/src/main/java/io/avaje/inject/generator/MetaData.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class MetaData {
2020

2121
private String method;
2222
private boolean wired;
23+
private boolean requestScope;
2324

2425
/**
2526
* The interfaces and class annotations the bean has (to register into lists).
@@ -32,6 +33,7 @@ class MetaData {
3233
private List<String> dependsOn;
3334

3435
MetaData(DependencyMeta meta) {
36+
this.requestScope = meta.requestScope();
3537
this.type = meta.type();
3638
this.name = trimName(meta.name());
3739
this.shortType = Util.shortName(type);
@@ -101,6 +103,7 @@ private List<String> asList(String[] content) {
101103
}
102104

103105
void update(BeanReader beanReader) {
106+
this.requestScope = beanReader.isRequestScopedBean();
104107
this.provides = beanReader.getInterfaces();
105108
this.dependsOn = beanReader.getDependsOn();
106109
}
@@ -109,6 +112,10 @@ String getType() {
109112
return type;
110113
}
111114

115+
boolean isRequestScope() {
116+
return requestScope;
117+
}
118+
112119
List<String> getProvides() {
113120
return provides;
114121
}
@@ -149,6 +156,9 @@ String buildMethod(MetaDataOrdering ordering) {
149156

150157
StringBuilder sb = new StringBuilder(200);
151158
sb.append(" @DependencyMeta(type=\"").append(type).append("\"");
159+
if (requestScope) {
160+
sb.append(", requestScope=true");
161+
}
152162
if (name != null) {
153163
sb.append(", name=\"").append(name).append("\"");
154164
}

inject-generator/src/main/java/io/avaje/inject/generator/MetaDataOrdering.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class MetaDataOrdering {
1616
private final ProcessingContext context;
1717

1818
private final List<MetaData> orderedList = new ArrayList<>();
19-
19+
private final List<MetaData> requestScope = new ArrayList<>();
2020
private final List<MetaData> queue = new ArrayList<>();
2121

2222
private final Map<String, ProviderList> providers = new HashMap<>();
@@ -32,7 +32,11 @@ class MetaDataOrdering {
3232
this.context = context;
3333

3434
for (MetaData metaData : values) {
35-
if (metaData.noDepends()) {
35+
if (metaData.isRequestScope()) {
36+
// request scoped expected to have externally provided dependencies
37+
requestScope.add(metaData);
38+
metaData.setWired();
39+
} else if (metaData.noDepends()) {
3640
orderedList.add(metaData);
3741
metaData.setWired();
3842
} else {
@@ -46,12 +50,10 @@ class MetaDataOrdering {
4650
providers.computeIfAbsent(provide, s -> new ProviderList()).add(metaData);
4751
}
4852
}
49-
5053
// order no dependency list by ... name asc (order does not matter but for consistency)
5154
}
5255

5356
int processQueue() {
54-
5557
int count;
5658
do {
5759
count = processQueueRound();
@@ -159,11 +161,8 @@ String getTopPackage() {
159161
}
160162

161163
private int processQueueRound() {
162-
163164
// loop queue looking for entry that has all provides marked as included
164-
165165
int count = 0;
166-
167166
Iterator<MetaData> iterator = queue.iterator();
168167
while (iterator.hasNext()) {
169168
MetaData queuedMeta = iterator.next();
@@ -174,7 +173,6 @@ private int processQueueRound() {
174173
count++;
175174
}
176175
}
177-
178176
return count;
179177
}
180178

@@ -200,11 +198,18 @@ List<MetaData> getOrdered() {
200198
return orderedList;
201199
}
202200

201+
List<MetaData> getRequestScope() {
202+
return requestScope;
203+
}
204+
203205
Set<String> getImportTypes() {
204206
Set<String> importTypes = new TreeSet<>();
205207
for (MetaData metaData : orderedList) {
206208
metaData.addImportTypes(importTypes);
207209
}
210+
for (MetaData metaData : requestScope) {
211+
metaData.addImportTypes(importTypes);
212+
}
208213
return importTypes;
209214
}
210215

inject-generator/src/main/java/io/avaje/inject/generator/Processor.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,8 @@ private void readChangedBeans(Set<? extends Element> beans, boolean factory) {
153153
*/
154154
private void mergeMetaData() {
155155
for (BeanReader beanReader : beanReaders) {
156-
if (beanReader.isRequestScopedController()) {
157-
context.logDebug("skipping request scoped processed bean " + beanReader);
158-
} else {
159-
String metaKey = beanReader.getMetaKey();
160-
MetaData metaData = this.metaData.get(metaKey);
156+
if (!beanReader.isRequestScopedController()) {
157+
MetaData metaData = this.metaData.get(beanReader.getMetaKey());
161158
if (metaData == null) {
162159
addMeta(beanReader);
163160
} else {

inject-generator/src/main/java/io/avaje/inject/generator/SimpleFactoryWriter.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import javax.tools.JavaFileObject;
55
import java.io.IOException;
66
import java.io.Writer;
7+
import java.util.List;
78
import java.util.Set;
89
import java.util.TreeSet;
910

@@ -93,6 +94,9 @@ private void writeBuildMethods() {
9394
for (MetaData metaData : ordering.getOrdered()) {
9495
writer.append(metaData.buildMethod(ordering)).eol();
9596
}
97+
for (MetaData metaData : ordering.getRequestScope()) {
98+
writer.append(metaData.buildMethod(ordering)).eol();
99+
}
96100
}
97101

98102
private void writeCreateMethod() {
@@ -105,6 +109,14 @@ private void writeCreateMethod() {
105109
for (MetaData metaData : ordering.getOrdered()) {
106110
writer.append(" build_%s();", metaData.getBuildName()).eol();
107111
}
112+
final List<MetaData> requestScope = ordering.getRequestScope();
113+
if (!requestScope.isEmpty()) {
114+
writer.eol();
115+
writer.append(" // request scope providers").eol();
116+
for (MetaData metaData : requestScope) {
117+
writer.append(" build_%s();", metaData.getBuildName()).eol();
118+
}
119+
}
108120
writer.append(" }").eol();
109121
writer.eol();
110122
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package org.example.requestscope;
2+
3+
import jakarta.inject.Singleton;
4+
5+
@Singleton
6+
public class NotReqBean {
7+
8+
//final MyReqThingWithContext myReq;
9+
10+
public NotReqBean() {//MyReqThingWithContext myReq) {
11+
//this.myReq = myReq;
12+
}
13+
14+
}

inject/src/main/java/io/avaje/inject/spi/DependencyMeta.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
*/
66
public @interface DependencyMeta {
77

8+
/**
9+
* Request scope
10+
*/
11+
boolean requestScope() default false;
12+
813
/**
914
* The bean type.
1015
*/

0 commit comments

Comments
 (0)