Skip to content

Add topLevel validation for @MCElement annotations#2491

Merged
predic8 merged 1 commit into
masterfrom
toplevel-component-rule
Dec 22, 2025
Merged

Add topLevel validation for @MCElement annotations#2491
predic8 merged 1 commit into
masterfrom
toplevel-component-rule

Conversation

@christiangoerdes

@christiangoerdes christiangoerdes commented Dec 22, 2025

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added a null implementation for the hot deployer to support no-op operations.
  • Bug Fixes

    • Added validation to prevent invalid configurations where an element is marked as both component and top-level simultaneously.
  • Chores

    • Updated component annotations and filters.
    • Added Apache License headers to multiple files.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Dec 22, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

This PR enforces validation to prevent MCElement annotations from being marked as both topLevel=true and component=true simultaneously. It updates existing component annotations to include component=false, adds Apache License 2.0 headers across multiple files, introduces a new NullHotDeployer class, and adjusts global element filtering in Kubernetes grammar processing.

Changes

Cohort / File(s) Summary
MCElement Annotation Validation and Updates
annot/src/main/java/com/predic8/membrane/annot/SpringConfigurationXSDGeneratingAnnotationProcessor.java, annot/src/main/java/com/predic8/membrane/annot/generator/ComponentClassGenerator.java, core/src/main/java/com/predic8/membrane/core/openapi/serviceproxy/APIProxy.java
Adds validation to throw ProcessingException when MCElement has both component=true and topLevel=true. Updates @MCElement annotations on Components and APIProxy classes to explicitly include component=false parameter.
Kubernetes Grammar Global Element Filtering
annot/src/main/java/com/predic8/membrane/annot/generator/kubernetes/Grammar.java
Expands global-element filter criteria to include elements with topLevel() in addition to component() attributes.
HotDeployer Implementation
core/src/main/java/com/predic8/membrane/core/router/hotdeploy/NullHotDeployer.java
Introduces new public class NullHotDeployer implementing HotDeployer interface with three no-op methods: start(), stop(), and setEnabled(boolean).
License Headers (Non-functional)
core/src/main/java/com/predic8/membrane/core/ExitException.java, core/src/main/java/com/predic8/membrane/core/interceptor/lang/SetBodyInterceptor.java, core/src/main/java/com/predic8/membrane/core/lang/spel/DollarTemplateParserContext.java, core/src/main/java/com/predic8/membrane/core/router/hotdeploy/DefaultHotDeployer.java, core/src/main/java/com/predic8/membrane/core/router/hotdeploy/HotDeployer.java, core/src/test/java/com/predic8/membrane/core/interceptor/lang/SetBodyInterceptorTest.java, distribution/src/test/java/com/predic8/membrane/load/LoadTester.java
Adds Apache License 2.0 header comments to file headers. No functional or behavioral changes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • SpringConfigurationXSDGeneratingAnnotationProcessor.java: Verify validation logic correctly intercepts elements with both component=true and topLevel=true, and that the ProcessingException is thrown at the appropriate stage in processing.
  • Kubernetes Grammar filtering change: Confirm the expanded filter criteria (topLevel OR component) does not inadvertently include or exclude unintended elements in global element mappings.
  • NullHotDeployer: Verify the null-object pattern implementation aligns with HotDeployer interface contract and intended usage.

Possibly related PRs

Suggested reviewers

  • rrayst

Poem

🐰 Hops through code with license so fine,
Component validation draws the line—
No topLevel and component combined,
NullDeployer waits, completely resigned,
Licensing blessed, the code shines bright!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the primary change: adding validation for topLevel in @mcelement annotations, which is demonstrated by the new ProcessingException check in SpringConfigurationXSDGeneratingAnnotationProcessor.java.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch toplevel-component-rule

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
distribution/src/test/java/com/predic8/membrane/load/LoadTester.java (1)

114-114: Redundant close() call.

The submitters ExecutorService is already declared in the try-with-resources statement (line 86-87), which will automatically close it when the block exits. This explicit call is unnecessary.

🔎 Suggested fix
-            submitters.close();
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a42af59 and 82c83e5.

📒 Files selected for processing (12)
  • annot/src/main/java/com/predic8/membrane/annot/SpringConfigurationXSDGeneratingAnnotationProcessor.java
  • annot/src/main/java/com/predic8/membrane/annot/generator/ComponentClassGenerator.java
  • annot/src/main/java/com/predic8/membrane/annot/generator/kubernetes/Grammar.java
  • core/src/main/java/com/predic8/membrane/core/ExitException.java
  • core/src/main/java/com/predic8/membrane/core/interceptor/lang/SetBodyInterceptor.java
  • core/src/main/java/com/predic8/membrane/core/lang/spel/DollarTemplateParserContext.java
  • core/src/main/java/com/predic8/membrane/core/openapi/serviceproxy/APIProxy.java
  • core/src/main/java/com/predic8/membrane/core/router/hotdeploy/DefaultHotDeployer.java
  • core/src/main/java/com/predic8/membrane/core/router/hotdeploy/HotDeployer.java
  • core/src/main/java/com/predic8/membrane/core/router/hotdeploy/NullHotDeployer.java
  • core/src/test/java/com/predic8/membrane/core/interceptor/lang/SetBodyInterceptorTest.java
  • distribution/src/test/java/com/predic8/membrane/load/LoadTester.java
🧰 Additional context used
🧬 Code graph analysis (1)
core/src/main/java/com/predic8/membrane/core/openapi/serviceproxy/APIProxy.java (2)
core/src/main/java/com/predic8/membrane/core/interceptor/flow/choice/Case.java (1)
  • MCElement (29-95)
core/src/main/java/com/predic8/membrane/core/openapi/serviceproxy/OpenAPISpec.java (1)
  • MCElement (26-165)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (java)
🔇 Additional comments (14)
core/src/main/java/com/predic8/membrane/core/interceptor/lang/SetBodyInterceptor.java (1)

1-14: License header addition looks good.

Standard Apache License 2.0 header with correct copyright attribution.

core/src/main/java/com/predic8/membrane/core/lang/spel/DollarTemplateParserContext.java (1)

1-14: License header addition looks good.

Consistent Apache License 2.0 header format applied.

core/src/main/java/com/predic8/membrane/core/ExitException.java (1)

1-14: License header addition looks good.

Consistent Apache License 2.0 header format applied.

core/src/main/java/com/predic8/membrane/core/router/hotdeploy/DefaultHotDeployer.java (1)

1-14: License header addition looks good.

Consistent Apache License 2.0 header format applied.

distribution/src/test/java/com/predic8/membrane/load/LoadTester.java (3)

1-14: License header addition looks good.

Consistent Apache License 2.0 header format applied.


39-51: Class structure is well-organized.

Constants are appropriately documented with Javadoc comments explaining their purpose.


118-144: Async completion handling is correctly implemented.

Both success and error paths properly release the semaphore and count down the latch, ensuring no resource leaks or deadlocks.

core/src/test/java/com/predic8/membrane/core/interceptor/lang/SetBodyInterceptorTest.java (1)

1-14: License header addition looks good.

Consistent Apache License 2.0 header format applied.

core/src/main/java/com/predic8/membrane/core/router/hotdeploy/HotDeployer.java (1)

1-14: LGTM! License header added.

The Apache License 2.0 header has been properly added to the file with no functional changes.

core/src/main/java/com/predic8/membrane/core/router/hotdeploy/NullHotDeployer.java (1)

17-32: LGTM! Proper null object implementation.

The NullHotDeployer correctly implements the null object pattern with no-op methods, providing a safe default implementation for the HotDeployer interface.

annot/src/main/java/com/predic8/membrane/annot/generator/kubernetes/Grammar.java (1)

149-149: LGTM! Expands global element filter to include topLevel elements.

The filter now includes elements marked with topLevel() in addition to component(), which aligns with the validation rule being introduced. This ensures topLevel elements are properly included in global element mappings.

annot/src/main/java/com/predic8/membrane/annot/SpringConfigurationXSDGeneratingAnnotationProcessor.java (1)

218-220: LGTM! Validation correctly enforces topLevel/component mutual exclusivity.

The validation properly prevents elements from being marked as both topLevel=true and component=true. The placement is correct (before recording as a component), and the error message is clear.

annot/src/main/java/com/predic8/membrane/annot/generator/ComponentClassGenerator.java (1)

39-39: LGTM! Annotation updated to comply with topLevel/component validation.

The addition of component=false is necessary since the Components class is marked as topLevel=true. This change ensures compliance with the new validation rule.

core/src/main/java/com/predic8/membrane/core/openapi/serviceproxy/APIProxy.java (1)

47-47: All topLevel annotations in production code are correctly configured.

The addition of component=false to APIProxy is correct. A comprehensive search of the codebase reveals that APIProxy is the only production class with @MCElement(topLevel=true), and it now correctly includes component=false. The annotation processor enforces this requirement, as topLevel=true and component=true cannot coexist (the default component value is true, making explicit component=false mandatory for top-level elements).

@membrane-ci-server

Copy link
Copy Markdown

This pull request needs "/ok-to-test" from an authorized committer.

@christiangoerdes

Copy link
Copy Markdown
Collaborator Author

/ok-to-test

@predic8 predic8 merged commit 49bdf13 into master Dec 22, 2025
4 of 5 checks passed
@predic8 predic8 deleted the toplevel-component-rule branch December 22, 2025 09:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants