Skip to content

Commit 681d85c

Browse files
Open parts of AOT api for extensibility.
Make method generation context available for subclassing which allows dedicated tests to be implemented in store modules without having to bootstrap the entire AOT facility. This also demanded to change visibility of fragment metadata. Along the way fixed json rendering of method metadata by wrapping nested values in json objects. This allows to print out values of eg. list type as json array. Added test to cover json repository metadata rendering and storage. See: #3265
1 parent 739f505 commit 681d85c

File tree

5 files changed

+53
-5
lines changed

5 files changed

+53
-5
lines changed

src/main/java/org/springframework/data/repository/aot/generate/AotQueryMethodGenerationContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public class AotQueryMethodGenerationContext {
5050
private final MethodMetadata targetMethodMetadata;
5151
private final VariableNameFactory variableNameFactory;
5252

53-
AotQueryMethodGenerationContext(RepositoryInformation repositoryInformation, Method method, QueryMethod queryMethod,
53+
protected AotQueryMethodGenerationContext(RepositoryInformation repositoryInformation, Method method, QueryMethod queryMethod,
5454
AotRepositoryFragmentMetadata targetTypeMetadata) {
5555

5656
this.method = method;

src/main/java/org/springframework/data/repository/aot/generate/AotRepositoryFragmentMetadata.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
* @author Mark Paluch
3636
* @since 4.0
3737
*/
38-
class AotRepositoryFragmentMetadata {
38+
public class AotRepositoryFragmentMetadata {
3939

4040
private final ClassName className;
4141
private final Map<String, FieldSpec> fields = new HashMap<>(3);

src/main/java/org/springframework/data/repository/aot/generate/AotRepositoryMethod.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ static JSONObject queryMetadataToJson(QueryMetadata queryMetadata) throws JSONEx
5454
JSONObject query = new JSONObject();
5555

5656
for (Map.Entry<String, Object> entry : queryMetadata.serialize().entrySet()) {
57-
query.put(entry.getKey(), entry.getValue());
57+
query.put(entry.getKey(), JSONObject.wrap(entry.getValue()));
5858
}
5959

6060
return query;

src/test/java/org/springframework/data/repository/aot/generate/RepositoryContributorUnitTests.java

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@
2424
import example.UserRepositoryExtensionImpl;
2525

2626
import java.lang.reflect.Method;
27+
import java.lang.reflect.Parameter;
28+
import java.util.Arrays;
2729
import java.util.Map;
2830
import java.util.Optional;
2931
import java.util.Set;
3032

3133
import org.jspecify.annotations.Nullable;
3234
import org.junit.jupiter.api.Test;
33-
3435
import org.springframework.aot.test.generate.TestGenerationContext;
3536
import org.springframework.core.test.tools.TestCompiler;
3637
import org.springframework.data.aot.CodeContributionAssert;
@@ -95,6 +96,53 @@ public Map<String, Object> serialize() {
9596
new CodeContributionAssert(generationContext).contributesReflectionFor(expectedTypeName);
9697
}
9798

99+
@Test // GH-3265
100+
void writesCapturedQueryMetadataToResources() {
101+
102+
DummyModuleAotRepositoryContext aotContext = new DummyModuleAotRepositoryContext(UserRepository.class, null);
103+
RepositoryContributor repositoryContributor = new RepositoryContributor(aotContext) {
104+
105+
@Override
106+
protected @Nullable MethodContributor<? extends QueryMethod> contributeQueryMethod(Method method) {
107+
108+
return MethodContributor
109+
.forQueryMethod(
110+
new QueryMethod(method, getRepositoryInformation(), getProjectionFactory(), DefaultParameters::new))
111+
.withMetadata(new QueryMetadata() {
112+
113+
@Override
114+
public Map<String, Object> serialize() {
115+
116+
return Map.of("filter", "FILTER(%s > $1)".formatted(method.getName()), "project",
117+
Arrays.stream(method.getParameters()).map(Parameter::getName).toList());
118+
}
119+
}).contribute(context -> {
120+
121+
CodeBlock.Builder builder = CodeBlock.builder();
122+
if (!ClassUtils.isVoidType(method.getReturnType())) {
123+
builder.addStatement("return null");
124+
}
125+
126+
return builder.build();
127+
});
128+
}
129+
};
130+
131+
TestGenerationContext generationContext = new TestGenerationContext(UserRepository.class);
132+
repositoryContributor.contribute(generationContext);
133+
generationContext.writeGeneratedContent();
134+
135+
String expectedTypeName = "example.UserRepositoryImpl__Aot";
136+
137+
TestCompiler.forSystem().with(generationContext).compile(compiled -> {
138+
String content = compiled.getResourceFile().getContent();
139+
assertThat(content).containsIgnoringWhitespaces("\"filter\": \"FILTER(doSomething > $1)\"")
140+
.containsIgnoringWhitespaces("\"project\": [\n\"firstname\"\n]");
141+
});
142+
143+
new CodeContributionAssert(generationContext).contributesReflectionFor(expectedTypeName);
144+
}
145+
98146
@Test // GH-3279
99147
void callsMethodContributionForQueryMethod() {
100148

src/test/java/org/springframework/data/repository/aot/generate/StubRepositoryInformation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public boolean isCustomMethod(Method method) {
108108

109109
@Override
110110
public boolean isQueryMethod(Method method) {
111-
return false;
111+
return !isBaseClassMethod(method);
112112
}
113113

114114
@Override

0 commit comments

Comments
 (0)