supplier) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void close() {
+ ac.close();
+ }
+
+ public ApplicationContext getApplicationContext() {
+ return ac;
+ }
+}
diff --git a/annot/src/main/java/com/predic8/membrane/annot/yaml/GenericYamlParser.java b/annot/src/main/java/com/predic8/membrane/annot/yaml/GenericYamlParser.java
index 48799b006e..d1c59f87d9 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/yaml/GenericYamlParser.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/yaml/GenericYamlParser.java
@@ -19,9 +19,12 @@
import com.networknt.schema.*;
import com.networknt.schema.Error;
import com.predic8.membrane.annot.*;
+import jakarta.annotation.PostConstruct;
+import jakarta.annotation.PreDestroy;
import com.predic8.membrane.annot.beanregistry.*;
import org.jetbrains.annotations.*;
import org.slf4j.*;
+import org.springframework.util.ReflectionUtils;
import java.io.*;
import java.lang.reflect.*;
@@ -32,6 +35,7 @@
import static com.predic8.membrane.annot.yaml.MethodSetter.*;
import static com.predic8.membrane.annot.yaml.NodeValidationUtils.*;
import static java.nio.charset.StandardCharsets.*;
+import static java.util.List.of;
import static java.util.UUID.*;
public class GenericYamlParser {
@@ -136,12 +140,12 @@ private static void validate(Grammar grammar, JsonNode input) throws YamlSchemaV
* Ensures the node contains exactly one key (the kind), resolves the Java class via the
* grammar and delegates to {@link #createAndPopulateNode(ParsingContext, Class, JsonNode)}.
*/
- public static Object readMembraneObject(String kind, Grammar grammar, JsonNode node, BeanRegistry registry) throws ParsingException {
+ public static Object readMembraneObject(String kind, Grammar grammar, JsonNode node, R registry) throws ParsingException {
ensureSingleKey(node);
Class> clazz = grammar.getElement(kind);
if (clazz == null)
throw new ParsingException("Did not find java class for kind '%s'.".formatted(kind), node);
- return createAndPopulateNode(new ParsingContext(kind, registry, grammar), clazz, node.get(kind));
+ return createAndPopulateNode(new ParsingContext<>(kind, registry, grammar), clazz, node.get(kind));
}
/**
@@ -151,7 +155,7 @@ public static Object readMembraneObject(String kind, Grammar grammar, JsonNode n
* values are produced by {@link MethodSetter#getMethodSetter(ParsingContext, Class, String)}. A top-level {@code "$ref"} injects a previously defined bean.
* All failures are wrapped in a {@link ParsingException} with location information.
*/
- public static T createAndPopulateNode(ParsingContext ctx, Class clazz, JsonNode node) throws ParsingException {
+ public static T createAndPopulateNode(ParsingContext> ctx, Class clazz, JsonNode node) throws ParsingException {
try {
T configObj = clazz.getConstructor().newInstance();
if (node.isArray()) {
@@ -186,9 +190,8 @@ public static T createAndPopulateNode(ParsingContext ctx, Class clazz, Js
}
if (!required.isEmpty())
throw new ParsingException("Missing required fields: " + required.stream().map(McYamlIntrospector::getSetterName).toList(), node);
- return configObj;
- }
- catch (NoClassDefFoundError e) {
+ return handlePostConstructAndPreDestroy(ctx, configObj);
+ } catch (NoClassDefFoundError e) {
if (e.getCause() != null) {
var missingClass = e.getCause().getMessage(); // TODO: Better use ExceptionUtil.getRootCause() but it isn't visible in annot.
var msg = "Could not create bean with class: %s\nMissing class: %s\n".formatted(clazz, missingClass);
@@ -196,15 +199,14 @@ public static T createAndPopulateNode(ParsingContext ctx, Class clazz, Js
throw new ParsingException(msg, node); // TODO: Cause we know the reason, shorten output.
}
throw new ParsingException(e, node);
- }
- catch (Throwable cause) {
+ } catch (Throwable cause) {
throw new ParsingException(cause, node);
}
}
private static List extractComponentBeanDefinitions(JsonNode componentsNode) {
if (componentsNode == null || componentsNode.isNull())
- return List.of();
+ return of();
if (!componentsNode.isObject())
throw new ParsingException("Expected object for 'components'.", componentsNode);
@@ -240,7 +242,7 @@ private static List extractComponentBeanDefinitions(JsonNode com
* into the parent object via the matching @MCChildElement setter.
* Rejects "$ref" if the same child is already configured inline.
*/
- private static void applyObjectLevelRef(ParsingContext ctx, Class parentClass, JsonNode parentNode, JsonNode refNode, T obj) throws ParsingException {
+ private static void applyObjectLevelRef(ParsingContext> ctx, Class parentClass, JsonNode parentNode, JsonNode refNode, T obj) throws ParsingException {
ensureTextual(refNode, "Expected a string after the '$ref' key.");
Object referenced = getReferenced(ctx, refNode);
String refKey = getElementName(referenced.getClass());
@@ -262,7 +264,7 @@ private static void applyObjectLevelRef(ParsingContext ctx, Class parentC
}
}
- private static Object getReferenced(ParsingContext ctx, JsonNode refNode) {
+ private static Object getReferenced(ParsingContext> ctx, JsonNode refNode) {
try {
return ctx.registry().resolve(refNode.asText());
} catch (RuntimeException e) {
@@ -270,12 +272,12 @@ private static Object getReferenced(ParsingContext ctx, JsonNode refNode) {
}
}
- public static List