From 83b64c9f054e2717a1e8bbd8a0597c29b3988d28 Mon Sep 17 00:00:00 2001
From: Thomas Bayer
Date: Sat, 6 Dec 2025 17:06:07 +0100
Subject: [PATCH 1/5] feat: add `MCExcludeFromSchema` annotation and migrate
`statusCode` to `status` in YAML tutorials and schemas
- Introduced `MCExcludeFromSchema` annotation to allow exclusion of fields during schema generation.
- Replaced `statusCode` with `status` across YAML tutorial and schema files for consistency.
- Updated `JsonSchemaGenerator` and `AttributeInfo` to support exclusion logic based on the new annotation.
---
.../membrane/annot/MCExcludeFromSchema.java | 39 +++++++++++++++++++
.../annot/generator/JsonSchemaGenerator.java | 7 +++-
.../membrane/annot/model/AttributeInfo.java | 26 +++++++++++++
.../interceptor/flow/ReturnInterceptor.java | 35 ++++++++++++-----
.../core/config/spring/k8s/EnvelopeTest.java | 2 +-
.../custom-error-messages/apis.yaml | 4 +-
.../examples/extending-membrane/if/apis.yaml | 2 +-
.../monitoring-tracing/prometheus/apis.yaml | 6 +--
.../openapi/validation-security/apis.yaml | 2 +-
.../openapi/validation-simple/apis.yaml | 2 +-
.../examples/openapi/validation/apis.yaml | 4 +-
.../call-authentication/apis.yaml | 2 +-
.../routing-traffic/shadowing/apis.yaml | 6 +--
.../ssl-tls/api-with-tls-pem/apis.yaml | 2 +-
.../ssl-tls/api-with-tls-pkcs12/apis.yaml | 2 +-
.../examples/templating/json/apis.yaml | 2 +-
.../examples/templating/xml/apis.yaml | 4 +-
.../tutorials/advanced/10-PathParameters.yaml | 2 +-
distribution/tutorials/advanced/60-if.yaml | 2 +-
.../advanced/70-Scripting-Groovy.yaml | 2 +-
.../getting-started/50-Short-Circuit.yaml | 2 +-
.../getting-started/60-SetHeader.yaml | 2 +-
.../getting-started/70-Template.yaml | 2 +-
distribution/tutorials/json/20-JSONPath.yaml | 2 +-
.../json/60-Json-Transformation.yaml | 2 +-
.../tutorials/xml/10-JSON-to-XML.yaml | 2 +-
.../tutorials/xml/15-XML-to-JSON.yaml | 2 +-
distribution/tutorials/xml/20-XPath.yaml | 2 +-
28 files changed, 127 insertions(+), 42 deletions(-)
create mode 100644 annot/src/main/java/com/predic8/membrane/annot/MCExcludeFromSchema.java
diff --git a/annot/src/main/java/com/predic8/membrane/annot/MCExcludeFromSchema.java b/annot/src/main/java/com/predic8/membrane/annot/MCExcludeFromSchema.java
new file mode 100644
index 0000000000..e78253e6df
--- /dev/null
+++ b/annot/src/main/java/com/predic8/membrane/annot/MCExcludeFromSchema.java
@@ -0,0 +1,39 @@
+/* Copyright 2025 predic8 GmbH, www.predic8.com
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License. */
+
+package com.predic8.membrane.annot;
+
+import java.lang.annotation.*;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+/**
+ * Annotation to exclude specific fields from being included in schemas
+ * during schema generation for different configuration formats.
+ *
+ * This annotation can be applied to fields to specify whether they should
+ * be excluded from JSON Schema (YAML) or XSD (XML configuration).
+ *
+ * - Setting `json` to true excludes the field from JSON Schema.
+ * - Setting `xsd` to true excludes the field from XSD.
+ */
+@Retention(RUNTIME)
+@Target(METHOD)
+public @interface MCExcludeFromSchema {
+ boolean json() default false; // excludes from JSON Schema (YAML)
+ boolean xsd() default false; // excludes from XSD (XML configuration)
+}
+
+
diff --git a/annot/src/main/java/com/predic8/membrane/annot/generator/JsonSchemaGenerator.java b/annot/src/main/java/com/predic8/membrane/annot/generator/JsonSchemaGenerator.java
index a233aa5984..b61f8b3725 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/generator/JsonSchemaGenerator.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/generator/JsonSchemaGenerator.java
@@ -173,6 +173,11 @@ private FileObject createFile(MainInfo main) throws IOException {
private void processMCAttributes(ElementInfo i, SchemaObject so) {
i.getAis().forEach(ai -> {
+
+ // skip attributes marked with @MCExcludeFromSchema
+ if (ai.isExcludedFromJsonSchema())
+ return;
+
// hide id only on top-level elements
if ("id".equals(ai.getXMLName()) && i.getAnnotation().topLevel()) {
return;
@@ -251,7 +256,6 @@ boolean isFlowFromWebSocket(ChildElementInfo cei) {
}
private AbstractSchema> processList(ElementInfo i, AbstractSchema> so, ChildElementInfo cei, ArrayList sos) {
-
SchemaObject items = object("items");
if (shouldGenerateParserType(cei)) {
@@ -291,7 +295,6 @@ private void addChildsAsProperties(Model m, MainInfo main, ChildElementInfo cei,
.ref("#/$defs/" + ei.getXSDTypeName(m)))
.description(getDescriptionContent(ei))
.required(cei.isRequired());
-
}
}
diff --git a/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java b/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
index f10b6aa576..82013cbee3 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
@@ -195,4 +195,30 @@ public boolean isRequired() {
public void setRequired(boolean required) {
this.required = required;
}
+
+ /**
+ * Determines whether the current field or method should be excluded from the JSON schema during schema generation.
+ * @return {@code true} if the field or method is excluded from the JSON schema; {@code false} otherwise.
+ */
+ public boolean isExcludedFromJsonSchema() {
+ MCExcludeFromSchema ann = getE().getAnnotation(MCExcludeFromSchema.class);
+ return ann != null && ann.json();
+ }
+
+
+ /**
+ * Determines whether the current field or method should be excluded from the XSD schema during schema generation.
+ *
+ * The exclusion is determined based on the presence and configuration of the {@code MCExcludeFromSchema} annotation.
+ *
+ * @return {@code true} if the field or method is excluded from the XSD schema; {@code false} otherwise.
+ *
+ * Hint: Not implemented yet in XSD Schema Generator
+ */
+ @SuppressWarnings("unused")
+ public boolean isExcludedFromXsdSchema() {
+ MCExcludeFromSchema ann = getE().getAnnotation(MCExcludeFromSchema.class);
+ return ann != null && ann.xsd();
+ }
+
}
\ No newline at end of file
diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ReturnInterceptor.java b/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ReturnInterceptor.java
index 985695dfdf..6b3729a6a2 100644
--- a/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ReturnInterceptor.java
+++ b/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ReturnInterceptor.java
@@ -51,7 +51,7 @@ public class ReturnInterceptor extends AbstractInterceptor {
private static final Logger log = LoggerFactory.getLogger(ReturnInterceptor.class.getName());
- private int statusCode = 200;
+ private int status = 200;
private String contentType = null;
@Override
@@ -76,9 +76,9 @@ private Response getOrCreateResponse(Exchange exc) throws IOException {
response = createResponseFromRequest(exc);
}
- if (statusCode != 0) {
- response.setStatusCode(statusCode);
- response.setStatusMessage(getMessageForStatusCode(statusCode));
+ if (status != 0) {
+ response.setStatusCode(status);
+ response.setStatusMessage(getMessageForStatusCode(status));
}
if (contentType!=null) {
@@ -92,7 +92,7 @@ private Response getOrCreateResponse(Exchange exc) throws IOException {
}
private Response createResponseFromRequest(Exchange exc) throws IOException {
- Response.ResponseBuilder builder = new Response.ResponseBuilder().status(statusCode);
+ Response.ResponseBuilder builder = new Response.ResponseBuilder().status(status);
String reqContentType = exc.getRequest().getHeader().getContentType();
if (reqContentType != null) {
builder.contentType(reqContentType);
@@ -112,7 +112,7 @@ public String getDisplayName() {
@Override
public String getShortDescription() {
- return (contentType != null) ? format("Sends a response with a status code of %d and a content type of %s.", statusCode, contentType) : format("Sends a response with a status code of %d.", statusCode);
+ return (contentType != null) ? format("Sends a response with a status code of %d and a content type of %s.", status, contentType) : format("Sends a response with a status code of %d.", status);
}
@Override
@@ -121,21 +121,38 @@ public EnumSet getAppliedFlow() {
}
/**
+ * @deprecated Use status instead.
* @description HTTP status code to be returned.
* @default 200
* @example 400
*/
+ @MCExcludeFromSchema(json = true)
@MCAttribute
public void setStatusCode(int statusCode) {
- this.statusCode = statusCode;
+ // Gets included in JSON schema but not XSD schema.
+ this.status = statusCode;
}
public int getStatusCode() {
- return statusCode;
+ return status;
}
/**
- * @description Content type of the response. If not set, the content type of the request (if available) or no content type will be used.
+ * @description HTTP status code to be returned.
+ * @default 200
+ * @example 400
+ */
+ @MCAttribute
+ public void setStatus(int status) {
+ this.status = status;
+ }
+
+ public int getStatus() {
+ return status;
+ }
+
+ /**
+ * @description Content-Type of the response. If not set, the content type of the request (if available) or no content type will be used.
* @default null
* @example application/json; charset=utf-8
*/
diff --git a/core/src/test/java/com/predic8/membrane/core/config/spring/k8s/EnvelopeTest.java b/core/src/test/java/com/predic8/membrane/core/config/spring/k8s/EnvelopeTest.java
index 919712b1c8..d928776500 100644
--- a/core/src/test/java/com/predic8/membrane/core/config/spring/k8s/EnvelopeTest.java
+++ b/core/src/test/java/com/predic8/membrane/core/config/spring/k8s/EnvelopeTest.java
@@ -83,7 +83,7 @@ void routerConfConfig() {
contentType: application/json
src: '{ "ok": 1 }'
- return:
- statusCode: 200
+ status: 200
---
api:
port: 2000
diff --git a/distribution/examples/extending-membrane/error-handling/custom-error-messages/apis.yaml b/distribution/examples/extending-membrane/error-handling/custom-error-messages/apis.yaml
index d3b21cbb30..3c45cc942b 100644
--- a/distribution/examples/extending-membrane/error-handling/custom-error-messages/apis.yaml
+++ b/distribution/examples/extending-membrane/error-handling/custom-error-messages/apis.yaml
@@ -104,7 +104,7 @@ api:
contentType: text/plain
src: Ordinary error!
- return:
- statusCode: 500
+ status: 500
- if:
test: param.case == 'd'
flow:
@@ -115,6 +115,6 @@ api:
XML Fehler Meldung vom Backend!
- return:
- statusCode: 500
+ status: 500
# SOAP Service Mock for Debugging
- sampleSoapService: {}
\ No newline at end of file
diff --git a/distribution/examples/extending-membrane/if/apis.yaml b/distribution/examples/extending-membrane/if/apis.yaml
index 7cacef4110..24ccf0fa2b 100644
--- a/distribution/examples/extending-membrane/if/apis.yaml
+++ b/distribution/examples/extending-membrane/if/apis.yaml
@@ -69,4 +69,4 @@ api:
- template:
src: Success
- return:
- statusCode: 302
\ No newline at end of file
+ status: 302
\ No newline at end of file
diff --git a/distribution/examples/monitoring-tracing/prometheus/apis.yaml b/distribution/examples/monitoring-tracing/prometheus/apis.yaml
index f08a45a002..04981129bc 100644
--- a/distribution/examples/monitoring-tracing/prometheus/apis.yaml
+++ b/distribution/examples/monitoring-tracing/prometheus/apis.yaml
@@ -11,7 +11,7 @@ api:
port: 2001
flow:
- return:
- statusCode: 200
+ status: 200
---
@@ -19,7 +19,7 @@ api:
port: 2002
flow:
- return:
- statusCode: 404
+ status: 404
---
@@ -27,4 +27,4 @@ api:
port: 2003
flow:
- return:
- statusCode: 500
\ No newline at end of file
+ status: 500
\ No newline at end of file
diff --git a/distribution/examples/openapi/validation-security/apis.yaml b/distribution/examples/openapi/validation-security/apis.yaml
index 66a8e20acf..87c7a2fb45 100644
--- a/distribution/examples/openapi/validation-security/apis.yaml
+++ b/distribution/examples/openapi/validation-security/apis.yaml
@@ -30,4 +30,4 @@ api:
- template:
src: Success!
- return:
- statusCode: 200
\ No newline at end of file
+ status: 200
\ No newline at end of file
diff --git a/distribution/examples/openapi/validation-simple/apis.yaml b/distribution/examples/openapi/validation-simple/apis.yaml
index e54b3c6234..b6460ad184 100644
--- a/distribution/examples/openapi/validation-simple/apis.yaml
+++ b/distribution/examples/openapi/validation-simple/apis.yaml
@@ -22,6 +22,6 @@ api:
contentType: application/json
src: '{ "success": true }'
- return:
- statusCode: 201
+ status: 201
# See examples/openapi-validator for a more detailed example
\ No newline at end of file
diff --git a/distribution/examples/openapi/validation/apis.yaml b/distribution/examples/openapi/validation/apis.yaml
index 46041c0bf7..8ca2621d14 100644
--- a/distribution/examples/openapi/validation/apis.yaml
+++ b/distribution/examples/openapi/validation/apis.yaml
@@ -30,7 +30,7 @@ api:
"email": "foo@baz.org"
}
- return:
- statusCode: 201
+ status: 201
---
@@ -53,7 +53,7 @@ api:
}
] }
- return:
- statusCode: 200
+ status: 200
---
# Monitoring endpoint for prometheus
diff --git a/distribution/examples/orchestration/call-authentication/apis.yaml b/distribution/examples/orchestration/call-authentication/apis.yaml
index 73f7ffe0e2..f16ab04cd9 100644
--- a/distribution/examples/orchestration/call-authentication/apis.yaml
+++ b/distribution/examples/orchestration/call-authentication/apis.yaml
@@ -46,4 +46,4 @@ api:
- static:
src: Please log in!
- return:
- statusCode: 401
\ No newline at end of file
+ status: 401
\ No newline at end of file
diff --git a/distribution/examples/routing-traffic/shadowing/apis.yaml b/distribution/examples/routing-traffic/shadowing/apis.yaml
index 8c2253bb7f..f6fe024ad4 100644
--- a/distribution/examples/routing-traffic/shadowing/apis.yaml
+++ b/distribution/examples/routing-traffic/shadowing/apis.yaml
@@ -26,7 +26,7 @@ api:
flow:
- log: {}
- return:
- statusCode: 200
+ status 200
---
@@ -35,7 +35,7 @@ api:
flow:
- log: {}
- return:
- statusCode: 201
+ status: 201
---
@@ -44,4 +44,4 @@ api:
flow:
- log: {}
- return:
- statusCode: 202
\ No newline at end of file
+ status: 202
\ No newline at end of file
diff --git a/distribution/examples/security/ssl-tls/api-with-tls-pem/apis.yaml b/distribution/examples/security/ssl-tls/api-with-tls-pem/apis.yaml
index d12d8358c6..4b5cb52d3d 100644
--- a/distribution/examples/security/ssl-tls/api-with-tls-pem/apis.yaml
+++ b/distribution/examples/security/ssl-tls/api-with-tls-pem/apis.yaml
@@ -30,4 +30,4 @@ api:
"success": true
}
- return:
- statusCode: 200
\ No newline at end of file
+ status: 200
\ No newline at end of file
diff --git a/distribution/examples/security/ssl-tls/api-with-tls-pkcs12/apis.yaml b/distribution/examples/security/ssl-tls/api-with-tls-pkcs12/apis.yaml
index 62bddc8350..73ef16e8e3 100644
--- a/distribution/examples/security/ssl-tls/api-with-tls-pkcs12/apis.yaml
+++ b/distribution/examples/security/ssl-tls/api-with-tls-pkcs12/apis.yaml
@@ -31,4 +31,4 @@ api:
"success": true
}
- return:
- statusCode: 200
\ No newline at end of file
+ status: 200
\ No newline at end of file
diff --git a/distribution/examples/templating/json/apis.yaml b/distribution/examples/templating/json/apis.yaml
index 55c7f33655..0f4a65c290 100644
--- a/distribution/examples/templating/json/apis.yaml
+++ b/distribution/examples/templating/json/apis.yaml
@@ -15,7 +15,7 @@ api:
}
# To forward to backend use target below instead of return
- return:
- statusCode: 200
+ status: 200
# target:
# host: YourBackendHost
# port: YourBackendPort
diff --git a/distribution/examples/templating/xml/apis.yaml b/distribution/examples/templating/xml/apis.yaml
index 3354558e0d..3d759062ca 100644
--- a/distribution/examples/templating/xml/apis.yaml
+++ b/distribution/examples/templating/xml/apis.yaml
@@ -12,7 +12,7 @@ api:
src: Buenas Noches, ${property.fn}sito!
# To forward to backend use target below instead of return
- return:
- statusCode: 200
+ status: 200
contentType: text/plain
# target:
# host: YourBackendHost
@@ -27,4 +27,4 @@ api:
- template:
location: template.xml
- return:
- statusCode: 200
\ No newline at end of file
+ status: 200
\ No newline at end of file
diff --git a/distribution/tutorials/advanced/10-PathParameters.yaml b/distribution/tutorials/advanced/10-PathParameters.yaml
index e7a9e0f4f6..fa5d08136d 100644
--- a/distribution/tutorials/advanced/10-PathParameters.yaml
+++ b/distribution/tutorials/advanced/10-PathParameters.yaml
@@ -23,4 +23,4 @@ api:
Customer: ${pathParam.id}
Account: ${pathParam.accountNumber}
- return:
- statusCode: 200
+ status: 200
diff --git a/distribution/tutorials/advanced/60-if.yaml b/distribution/tutorials/advanced/60-if.yaml
index 4aea89219b..90e1473af5 100644
--- a/distribution/tutorials/advanced/60-if.yaml
+++ b/distribution/tutorials/advanced/60-if.yaml
@@ -19,7 +19,7 @@ api:
- static:
src: Please set X-Id header
- return:
- statusCode: 400
+ status: 400
- if:
test: path.startsWith("/foo")
language: groovy
diff --git a/distribution/tutorials/advanced/70-Scripting-Groovy.yaml b/distribution/tutorials/advanced/70-Scripting-Groovy.yaml
index bb12ab4b36..2c944f2002 100644
--- a/distribution/tutorials/advanced/70-Scripting-Groovy.yaml
+++ b/distribution/tutorials/advanced/70-Scripting-Groovy.yaml
@@ -17,7 +17,7 @@ api:
src: |
println "I'm executed in the ${flow} flow"
- return:
- statusCode: 200
+ status: 200
---
api:
diff --git a/distribution/tutorials/getting-started/50-Short-Circuit.yaml b/distribution/tutorials/getting-started/50-Short-Circuit.yaml
index 8ca88bf0c0..3fefc766dc 100644
--- a/distribution/tutorials/getting-started/50-Short-Circuit.yaml
+++ b/distribution/tutorials/getting-started/50-Short-Circuit.yaml
@@ -28,4 +28,4 @@ api:
# Reverses the flow.
# If there is no response yet it will copy the body from the request.
- return:
- statusCode: 200
\ No newline at end of file
+ status: 200
\ No newline at end of file
diff --git a/distribution/tutorials/getting-started/60-SetHeader.yaml b/distribution/tutorials/getting-started/60-SetHeader.yaml
index 758ff3c828..4b4910801b 100644
--- a/distribution/tutorials/getting-started/60-SetHeader.yaml
+++ b/distribution/tutorials/getting-started/60-SetHeader.yaml
@@ -22,4 +22,4 @@ api:
name: X-Method
value: ${method} # Variable or computed value
- return:
- statusCode: 200
\ No newline at end of file
+ status: 200
\ No newline at end of file
diff --git a/distribution/tutorials/getting-started/70-Template.yaml b/distribution/tutorials/getting-started/70-Template.yaml
index 3843516a6f..4b03fd320d 100644
--- a/distribution/tutorials/getting-started/70-Template.yaml
+++ b/distribution/tutorials/getting-started/70-Template.yaml
@@ -25,4 +25,4 @@ api:
Path: ${path},
Date: ${new Date()}
- return:
- statusCode: 200
+ status: 200
diff --git a/distribution/tutorials/json/20-JSONPath.yaml b/distribution/tutorials/json/20-JSONPath.yaml
index 54865e7fa1..ba9e080c15 100644
--- a/distribution/tutorials/json/20-JSONPath.yaml
+++ b/distribution/tutorials/json/20-JSONPath.yaml
@@ -51,4 +51,4 @@ api:
# Log the query parameter
message: "First: ${params.animal}"
- return:
- statusCode: 200
\ No newline at end of file
+ status: 200
\ No newline at end of file
diff --git a/distribution/tutorials/json/60-Json-Transformation.yaml b/distribution/tutorials/json/60-Json-Transformation.yaml
index 301dc49225..aba4c40c44 100644
--- a/distribution/tutorials/json/60-Json-Transformation.yaml
+++ b/distribution/tutorials/json/60-Json-Transformation.yaml
@@ -51,4 +51,4 @@ api:
]
}
- return:
- statusCode: 200
\ No newline at end of file
+ status: 200
\ No newline at end of file
diff --git a/distribution/tutorials/xml/10-JSON-to-XML.yaml b/distribution/tutorials/xml/10-JSON-to-XML.yaml
index aebe8f280a..c0404c5ae6 100644
--- a/distribution/tutorials/xml/10-JSON-to-XML.yaml
+++ b/distribution/tutorials/xml/10-JSON-to-XML.yaml
@@ -19,4 +19,4 @@ api:
root: zoo # XML root element
- beautifier: {} # Format
- return:
- statusCode: 200
\ No newline at end of file
+ status: 200
\ No newline at end of file
diff --git a/distribution/tutorials/xml/15-XML-to-JSON.yaml b/distribution/tutorials/xml/15-XML-to-JSON.yaml
index ce95254e35..c6d7f6e2ce 100644
--- a/distribution/tutorials/xml/15-XML-to-JSON.yaml
+++ b/distribution/tutorials/xml/15-XML-to-JSON.yaml
@@ -18,4 +18,4 @@ api:
- xml2Json: {}
- beautifier: {} # Format
- return:
- statusCode: 200
\ No newline at end of file
+ status: 200
\ No newline at end of file
diff --git a/distribution/tutorials/xml/20-XPath.yaml b/distribution/tutorials/xml/20-XPath.yaml
index fe16123564..13f923154a 100644
--- a/distribution/tutorials/xml/20-XPath.yaml
+++ b/distribution/tutorials/xml/20-XPath.yaml
@@ -50,5 +50,5 @@ api:
- log:
message: Dog found!
- return:
- statusCode: 200
+ status: 200
contentType: application/xml
\ No newline at end of file
From edb472e5ebb59276c1b650bed8f0f90f61f7ca24 Mon Sep 17 00:00:00 2001
From: Thomas Bayer
Date: Sat, 6 Dec 2025 18:10:51 +0100
Subject: [PATCH 2/5] refactor: remove `MCExcludeFromSchema` annotation and
migrate exclusion logic to `MCAttribute`
---
.../predic8/membrane/annot/MCAttribute.java | 15 ++++++-
.../membrane/annot/MCExcludeFromSchema.java | 39 -------------------
.../membrane/annot/model/AttributeInfo.java | 8 ++--
.../interceptor/flow/ReturnInterceptor.java | 10 ++---
.../routing-traffic/shadowing/apis.yaml | 2 +-
5 files changed, 23 insertions(+), 51 deletions(-)
delete mode 100644 annot/src/main/java/com/predic8/membrane/annot/MCExcludeFromSchema.java
diff --git a/annot/src/main/java/com/predic8/membrane/annot/MCAttribute.java b/annot/src/main/java/com/predic8/membrane/annot/MCAttribute.java
index 5c95c5f770..53865d6244 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/MCAttribute.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/MCAttribute.java
@@ -19,11 +19,22 @@
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
- * Injects an XML attribute using a setter method.
+ * Annotation for marking a method to represent an attribute in the Membrane configuration.
+ * Primarily used for defining properties and their representation across different configuration grammars,
+ * such as JSON Schema or XML Schema (XSD).
+ *
+ * Methods annotated with this are typically setters with specific behavior or constraints
+ * controlled by the annotation's attributes.
+ *
+ * Attributes:
+ * - attributeName: Specifies the name of the attribute. If not defined, a default naming convention might apply.
+ * - excludeFromJson: Indicates whether the attribute should be excluded from JSON Schema representation (default is false).
+ * - excludeFromXsd: Indicates whether the attribute should be excluded from XML Schema (XSD) representation (default is false).
*/
@Target(METHOD)
@Retention(RUNTIME)
public @interface MCAttribute {
-
String attributeName() default "";
+ boolean excludeFromJson() default false; // excludes from JSON Schema (YAML)
+ boolean excludeFromXsd() default false; // excludes from XSD (XML configuration)
}
diff --git a/annot/src/main/java/com/predic8/membrane/annot/MCExcludeFromSchema.java b/annot/src/main/java/com/predic8/membrane/annot/MCExcludeFromSchema.java
deleted file mode 100644
index e78253e6df..0000000000
--- a/annot/src/main/java/com/predic8/membrane/annot/MCExcludeFromSchema.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright 2025 predic8 GmbH, www.predic8.com
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License. */
-
-package com.predic8.membrane.annot;
-
-import java.lang.annotation.*;
-
-import static java.lang.annotation.ElementType.*;
-import static java.lang.annotation.RetentionPolicy.*;
-
-/**
- * Annotation to exclude specific fields from being included in schemas
- * during schema generation for different configuration formats.
- *
- * This annotation can be applied to fields to specify whether they should
- * be excluded from JSON Schema (YAML) or XSD (XML configuration).
- *
- * - Setting `json` to true excludes the field from JSON Schema.
- * - Setting `xsd` to true excludes the field from XSD.
- */
-@Retention(RUNTIME)
-@Target(METHOD)
-public @interface MCExcludeFromSchema {
- boolean json() default false; // excludes from JSON Schema (YAML)
- boolean xsd() default false; // excludes from XSD (XML configuration)
-}
-
-
diff --git a/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java b/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
index 82013cbee3..74458d4ed6 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
@@ -201,8 +201,8 @@ public void setRequired(boolean required) {
* @return {@code true} if the field or method is excluded from the JSON schema; {@code false} otherwise.
*/
public boolean isExcludedFromJsonSchema() {
- MCExcludeFromSchema ann = getE().getAnnotation(MCExcludeFromSchema.class);
- return ann != null && ann.json();
+ MCAttribute ann = getE().getAnnotation(MCAttribute.class);
+ return ann != null && ann.excludeFromJson();
}
@@ -217,8 +217,8 @@ public boolean isExcludedFromJsonSchema() {
*/
@SuppressWarnings("unused")
public boolean isExcludedFromXsdSchema() {
- MCExcludeFromSchema ann = getE().getAnnotation(MCExcludeFromSchema.class);
- return ann != null && ann.xsd();
+ MCAttribute ann = getE().getAnnotation(MCAttribute.class);
+ return ann != null && ann.excludeFromXsd();
}
}
\ No newline at end of file
diff --git a/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ReturnInterceptor.java b/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ReturnInterceptor.java
index 6b3729a6a2..830dc5e77f 100644
--- a/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ReturnInterceptor.java
+++ b/core/src/main/java/com/predic8/membrane/core/interceptor/flow/ReturnInterceptor.java
@@ -39,7 +39,7 @@
* 2. If there is no response in the exchange, the body and contentType of the request is copied into a new response.
*
*
- * The options statusCode and contentType will overwrite the values from the messages.
+ * The options status and contentType will overwrite the values from the messages.
*
*
* This plugin is useful together with the template plugin. See examples/template.
@@ -122,14 +122,14 @@ public EnumSet getAppliedFlow() {
/**
* @deprecated Use status instead.
- * @description HTTP status code to be returned.
+ * @description HTTP status code to be returned. statusCode is kept only for backward compatibility use status instead.
* @default 200
* @example 400
*/
- @MCExcludeFromSchema(json = true)
- @MCAttribute
+ @Deprecated
+ @MCAttribute(excludeFromJson = true)
public void setStatusCode(int statusCode) {
- // Gets included in JSON schema but not XSD schema.
+ // Is excluded from the JSON schema. But will be included in the XSD schema.
this.status = statusCode;
}
diff --git a/distribution/examples/routing-traffic/shadowing/apis.yaml b/distribution/examples/routing-traffic/shadowing/apis.yaml
index f6fe024ad4..89a1047139 100644
--- a/distribution/examples/routing-traffic/shadowing/apis.yaml
+++ b/distribution/examples/routing-traffic/shadowing/apis.yaml
@@ -26,7 +26,7 @@ api:
flow:
- log: {}
- return:
- status 200
+ status: 200
---
From c1499d89fa4acb5c87ff5c401276bcda493c8b2e Mon Sep 17 00:00:00 2001
From: Thomas Bayer
Date: Sat, 6 Dec 2025 18:28:13 +0100
Subject: [PATCH 3/5] refactor: simplify exclusion method names and streamline
annotation handling in `AttributeInfo` and `JsonSchemaGenerator`
---
.../annot/generator/JsonSchemaGenerator.java | 2 +-
.../predic8/membrane/annot/model/AttributeInfo.java | 12 +++++-------
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/annot/src/main/java/com/predic8/membrane/annot/generator/JsonSchemaGenerator.java b/annot/src/main/java/com/predic8/membrane/annot/generator/JsonSchemaGenerator.java
index b61f8b3725..0e44ad7014 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/generator/JsonSchemaGenerator.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/generator/JsonSchemaGenerator.java
@@ -175,7 +175,7 @@ private void processMCAttributes(ElementInfo i, SchemaObject so) {
i.getAis().forEach(ai -> {
// skip attributes marked with @MCExcludeFromSchema
- if (ai.isExcludedFromJsonSchema())
+ if (ai.excludedFromJsonSchema())
return;
// hide id only on top-level elements
diff --git a/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java b/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
index 74458d4ed6..c0020c33f1 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
@@ -200,25 +200,23 @@ public void setRequired(boolean required) {
* Determines whether the current field or method should be excluded from the JSON schema during schema generation.
* @return {@code true} if the field or method is excluded from the JSON schema; {@code false} otherwise.
*/
- public boolean isExcludedFromJsonSchema() {
- MCAttribute ann = getE().getAnnotation(MCAttribute.class);
- return ann != null && ann.excludeFromJson();
+ public boolean excludedFromJsonSchema() {
+ return annotation != null && annotation.excludeFromJson();
}
/**
* Determines whether the current field or method should be excluded from the XSD schema during schema generation.
*
- * The exclusion is determined based on the presence and configuration of the {@code MCExcludeFromSchema} annotation.
+ * The exclusion is determined based on the configuration of the {@code MCAttribute} annotation.
*
* @return {@code true} if the field or method is excluded from the XSD schema; {@code false} otherwise.
*
* Hint: Not implemented yet in XSD Schema Generator
*/
@SuppressWarnings("unused")
- public boolean isExcludedFromXsdSchema() {
- MCAttribute ann = getE().getAnnotation(MCAttribute.class);
- return ann != null && ann.excludeFromXsd();
+ public boolean excludedFromXsdSchema() {
+ return annotation != null && annotation.excludeFromXsd();
}
}
\ No newline at end of file
From 195407ec6d134b26241b66b92401e181dc2ecb26 Mon Sep 17 00:00:00 2001
From: Thomas Bayer
Date: Sat, 6 Dec 2025 18:29:36 +0100
Subject: [PATCH 4/5] refactor: remove redundant Javadoc tags in
`AttributeInfo` methods
---
.../java/com/predic8/membrane/annot/model/AttributeInfo.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java b/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
index c0020c33f1..afdca80f1f 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
@@ -75,7 +75,6 @@ public String getSchemaType(Types typeUtils) {
/**
* It is not checked how many values the enum has. There are enums link validateRequests of OpenAPIValidator
* that have more than 2 values but they are also booleans at the configuration level
- * @return
*/
private boolean isEnumBoolean(Types typeUtils) {
return getEnumValues(typeUtils).contains("TRUE") && getEnumValues(typeUtils).contains("FALSE");
@@ -98,7 +97,6 @@ public boolean isBeanReference(Types typeUtils) {
/**
* Sets as side effect instance variables e.g. xsdType, isEnum, isBeanReference.
- * @param typeUtils
*/
private void analyze(Types typeUtils) {
if (xsdType != null) // already analyzed?
From 9be78b8e6f709e1d64ea02713ff2d788fd10b9d8 Mon Sep 17 00:00:00 2001
From: Tobias Polley
Date: Mon, 8 Dec 2025 13:34:34 +0100
Subject: [PATCH 5/5] expose 'excludeFromJson' and 'deprecated' to help
reference
---
.../com/predic8/membrane/annot/MCAttribute.java | 2 --
.../membrane/annot/generator/HelpReference.java | 4 ++++
.../annot/model/AbstractJavadocedInfo.java | 12 +++++++++++-
.../membrane/annot/model/AttributeInfo.java | 15 ---------------
4 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/annot/src/main/java/com/predic8/membrane/annot/MCAttribute.java b/annot/src/main/java/com/predic8/membrane/annot/MCAttribute.java
index 53865d6244..0eecbb64e4 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/MCAttribute.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/MCAttribute.java
@@ -29,12 +29,10 @@
* Attributes:
* - attributeName: Specifies the name of the attribute. If not defined, a default naming convention might apply.
* - excludeFromJson: Indicates whether the attribute should be excluded from JSON Schema representation (default is false).
- * - excludeFromXsd: Indicates whether the attribute should be excluded from XML Schema (XSD) representation (default is false).
*/
@Target(METHOD)
@Retention(RUNTIME)
public @interface MCAttribute {
String attributeName() default "";
boolean excludeFromJson() default false; // excludes from JSON Schema (YAML)
- boolean excludeFromXsd() default false; // excludes from XSD (XML configuration)
}
diff --git a/annot/src/main/java/com/predic8/membrane/annot/generator/HelpReference.java b/annot/src/main/java/com/predic8/membrane/annot/generator/HelpReference.java
index d08ebeb433..3bb6042a78 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/generator/HelpReference.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/generator/HelpReference.java
@@ -123,6 +123,7 @@ private void handle(Model m, MainInfo main, ElementInfo ei) throws XMLStreamExce
xew.writeAttribute("mixed", "true");
xew.writeAttribute("topLevel", Boolean.toString(ei.getAnnotation().topLevel()));
xew.writeAttribute("id", ei.getId());
+ xew.writeAttribute("deprecated", Boolean.toString(ei.isDeprecated()));
if (!ei.getAnnotation().topLevel()) {
String primaryParentId = getPrimaryParentId(m, main, ei);
if (primaryParentId != null)
@@ -198,6 +199,7 @@ private void handle(Model m, MainInfo main, ChildElementInfo cei) throws XMLStre
xew.writeStartElement("child");
xew.writeAttribute("min", cei.isRequired() ? "1" : "0");
xew.writeAttribute("max", cei.isList() ? "unbounded" : "1");
+ xew.writeAttribute("deprecated", Boolean.toString(cei.isDeprecated()));
handleDoc(cei);
@@ -228,6 +230,8 @@ private void handle(AttributeInfo ai) throws XMLStreamException {
xew.writeStartElement("attribute");
xew.writeAttribute("name", ai.getXMLName());
xew.writeAttribute("required", Boolean.toString(ai.isRequired()));
+ xew.writeAttribute("excludeFromJson", Boolean.toString(ai.excludedFromJsonSchema()));
+ xew.writeAttribute("deprecated", Boolean.toString(ai.isDeprecated()));
handleDoc(ai);
xew.writeEndElement();
}
diff --git a/annot/src/main/java/com/predic8/membrane/annot/model/AbstractJavadocedInfo.java b/annot/src/main/java/com/predic8/membrane/annot/model/AbstractJavadocedInfo.java
index f36cf197a6..d8c5b2865d 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/model/AbstractJavadocedInfo.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/model/AbstractJavadocedInfo.java
@@ -14,7 +14,9 @@
package com.predic8.membrane.annot.model;
import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
import com.predic8.membrane.annot.MCAttribute;
import com.predic8.membrane.annot.MCElement;
@@ -24,7 +26,8 @@
* Common behavior of Javadoc handling for {@link MCAttribute}, {@link MCElement}, etc.
*/
public abstract class AbstractJavadocedInfo {
- private Element docedE;
+ public static final String JAVA_LANG_DEPRECATED = "java.lang.Deprecated";
+ private Element docedE;
private boolean docGenerated;
private Doc doc;
@@ -50,4 +53,11 @@ public Doc getDoc(ProcessingEnvironment processingEnv) {
return doc = new Doc(processingEnv, javadoc, getDocedE());
}
+ public boolean isDeprecated() {
+ for (AnnotationMirror am : docedE.getAnnotationMirrors())
+ if (((TypeElement) am.getAnnotationType().asElement()).getQualifiedName().toString().equals(JAVA_LANG_DEPRECATED))
+ return true;
+ return false;
+ }
+
}
diff --git a/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java b/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
index afdca80f1f..361e1304d6 100644
--- a/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
+++ b/annot/src/main/java/com/predic8/membrane/annot/model/AttributeInfo.java
@@ -202,19 +202,4 @@ public boolean excludedFromJsonSchema() {
return annotation != null && annotation.excludeFromJson();
}
-
- /**
- * Determines whether the current field or method should be excluded from the XSD schema during schema generation.
- *
- * The exclusion is determined based on the configuration of the {@code MCAttribute} annotation.
- *
- * @return {@code true} if the field or method is excluded from the XSD schema; {@code false} otherwise.
- *
- * Hint: Not implemented yet in XSD Schema Generator
- */
- @SuppressWarnings("unused")
- public boolean excludedFromXsdSchema() {
- return annotation != null && annotation.excludeFromXsd();
- }
-
}
\ No newline at end of file