Skip to content

YAML Refactor and support for global#2513

Merged
predic8 merged 10 commits into
masterfrom
router-refactor-to-beanfactory
Dec 25, 2025
Merged

YAML Refactor and support for global#2513
predic8 merged 10 commits into
masterfrom
router-refactor-to-beanfactory

Conversation

@predic8
Copy link
Copy Markdown
Member

@predic8 predic8 commented Dec 24, 2025

Summary by CodeRabbit

  • New Features

    • Added an openPorts flag to control whether proxies open ports automatically.
    • Unified and clearer startup logging for XML and YAML initialization flows.
  • Refactor

    • Reorganized bean-related packages and refined bean registry/initialization behavior.
    • Adjusted proxy startup/initialization handling and lifecycle logging.
  • Chores

    • Removed a global stopAll() public method.
    • Added human-readable string representations for bean container/definition objects.

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 24, 2025

📝 Walkthrough

Walkthrough

Added string representations to bean registry classes, minor import/package reorganizations, introduced Router.openPorts with a setter and adjusted proxy registration behavior, added CLI startup logging and port-opening orchestration, and moved BeanCacheObserver to the beanregistry package. Small test/import tweak in YamlParser.

Changes

Cohort / File(s) Summary
Bean registry toString additions
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanContainer.java, annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java
Added toString() overrides to provide readable representations. Removed an unused Jackson import in BeanContainer.
Bean registry packaging / imports
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanCacheObserver.java, annot/src/test/java/com/predic8/membrane/annot/util/YamlParser.java, annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java
Changed BeanCacheObserver package to ...beanregistry. Removed some explicit imports (including a now-unused BeanCacheObserver import in BeanRegistryImplementation). Removed one unused yaml import in YamlParser. No functional control-flow changes evident.
Router: openPorts and proxy registration
core/src/main/java/com/predic8/membrane/core/Router.java
Introduced openPorts flag (default true) and public setter setOpenPorts(boolean). Proxy addition path now conditions port-opening behavior on this flag (register as MANUAL when false). Removed stopAll() and some startup/logging plumbing; imports adjusted.
CLI startup and port orchestration
core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java
Added logStartupMessage() helper and startup logging at initialization checkpoints. For YAML flow, disables open ports during setup and explicitly opens them after startup, then logs startup message. Added terminal/color and schema-related imports.

Sequence Diagram(s)

(omitted — changes are small, localized, and do not introduce a new multi-component control flow that requires a sequence diagram)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • rrayst

Poem

🐰 I hopped through code with nimble feet,
Beans now tell their names complete,
A flag decides which ports may wake,
CLI cheers when services take,
I nibble bugs and leave a treat 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title is incomplete and vague, using a truncated phrase 'support for global' without specifying what is being supported or made global. Complete the title to clearly specify the main objective, e.g., 'YAML Refactor and support for global interceptors' or 'YAML Refactor and support for global beans'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ 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 router-refactor-to-beanfactory

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (7)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java (1)

80-85: Consider restructuring the activation conditions to clarify intent.

A bean with kind "global" that also satisfies !bd.isComponent() && observer.isActivatable(bd) will trigger both add() calls, creating unnecessary UidAction objects. While the Set deduplicates them, the logic is unclear.

🔎 Proposed refactor to combine or clarify conditions

Option 1: Use else if (if global beans should only be added when not already activatable):

             if (!bd.isComponent() && observer.isActivatable(bd)) {
                 uidsToActivate.add(new UidAction(bd.getUid(), action));
-            }
-            if ("global".equals(bd.getKind())) {
+            } else if ("global".equals(bd.getKind())) {
                 uidsToActivate.add(new UidAction(bd.getUid(), action));
             }

Option 2: Combine conditions (if both should always be checked):

-            if (!bd.isComponent() && observer.isActivatable(bd)) {
-                uidsToActivate.add(new UidAction(bd.getUid(), action));
-            }
-            if ("global".equals(bd.getKind())) {
+            if ((!bd.isComponent() && observer.isActivatable(bd)) || "global".equals(bd.getKind())) {
                 uidsToActivate.add(new UidAction(bd.getUid(), action));
             }
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java (1)

16-17: Prefer explicit imports over wildcards.

Wildcard imports can reduce code clarity and potentially cause naming conflicts if new classes are added to these packages in the future.

🔎 Suggested explicit imports
-import com.fasterxml.jackson.databind.*;
-import com.predic8.membrane.annot.yaml.*;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.predic8.membrane.annot.yaml.WatchAction;
core/src/main/java/com/predic8/membrane/core/transport/Transport.java (1)

151-153: Consider documenting the relationship between setRouter and init.

Both setRouter(Router) (new) and init(Router) at line 57 set the router field, creating two pathways to establish the router reference. While this appears intentional for bidirectional linking (Router calls this in its setTransport method), the dual assignment pattern could confuse maintainers.

Consider adding a JavaDoc comment explaining that setRouter is called early by Router.setTransport to establish the link before init is invoked, or consolidate the logic if the early assignment isn't required.

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

30-30: Consider using specific imports instead of wildcards.

Wildcard imports (import com.predic8.schema.*; and import static com.predic8.membrane.core.Constants.*;) reduce code clarity by hiding which specific classes or constants are actually used. Explicit imports make dependencies more obvious and help prevent naming conflicts.

Also applies to: 43-43

core/src/main/java/com/predic8/membrane/core/Router.java (3)

18-18: Consider using specific imports instead of wildcard.

The wildcard import import com.predic8.membrane.annot.beanregistry.*; makes it less clear which specific classes from the beanregistry package are actually used in this file.


87-87: Add documentation for the openPorts field.

The openPorts field controls whether ports are automatically opened when proxies are registered, which is significant behavior. Adding JavaDoc or an @description annotation (consistent with other Router fields) would help maintainers understand its purpose and default value.


609-611: Add documentation for the setOpenPorts setter.

The setter controls whether proxies automatically open ports when registered. Adding an @description annotation (consistent with other Router setters) would clarify:

  • When and why to disable automatic port opening
  • The relationship to manual openPorts() calls
  • Usage patterns (e.g., YAML initialization scenario)
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4160c3b and 520164b.

📒 Files selected for processing (6)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanContainer.java
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java
  • core/src/main/java/com/predic8/membrane/core/Router.java
  • core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java
  • core/src/main/java/com/predic8/membrane/core/transport/Transport.java
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-11T14:18:23.761Z
Learnt from: rrayst
Repo: membrane/api-gateway PR: 1977
File: core/src/main/java/com/predic8/membrane/core/interceptor/opentelemetry/OpenTelemetryInterceptor.java:107-109
Timestamp: 2025-07-11T14:18:23.761Z
Learning: In Java exception handling, use ExceptionUtil.concatMessageAndCauseMessages(e) instead of e.getMessage() or e.getCause().getMessage() to get a complete view of the exception chain. This utility method safely concatenates all exception messages in the chain with " caused by: " separator, providing comprehensive error information for debugging without risk of NullPointerException.

Applied to files:

  • core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java
📚 Learning: 2025-07-28T16:28:17.849Z
Learnt from: rrayst
Repo: membrane/api-gateway PR: 1977
File: core/src/main/java/com/predic8/membrane/core/interceptor/opentelemetry/OpenTelemetryInterceptor.java:107-109
Timestamp: 2025-07-28T16:28:17.849Z
Learning: In Java exception handling for OpenTelemetry body logging, use log.debug() level with ExceptionUtil.concatMessageAndCauseMessages(e) to log body reading failures. This prevents cluttering info logs with potentially common stream reading issues while still providing comprehensive error information when debug logging is enabled.

Applied to files:

  • core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java
🔇 Additional comments (8)
annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanDefinition.java (1)

101-110: LGTM!

The toString() method provides a comprehensive representation of the bean definition, including all relevant fields for debugging and logging purposes.

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

41-44: LGTM!

The toString() method provides a concise and informative representation of the bean container using modern Java syntax.

core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java (3)

159-161: LGTM! Clean startup logging integration.

The extraction of router initialization followed by centralized startup logging improves code clarity and ensures consistent messaging for XML-based configurations.


180-197: LGTM! Well-structured YAML initialization sequence.

The explicit port control (setOpenPorts(false), followed by manual openPorts() call) provides fine-grained control over the initialization sequence and aligns well with the new Router capabilities. The unified startup logging ensures consistent messaging across XML and YAML configurations.


382-384: LGTM! Centralized startup logging enhances consistency.

The helper method consolidates startup messaging and adds visual polish with ANSI colors, improving the user experience during CLI startup.

core/src/main/java/com/predic8/membrane/core/Router.java (3)

298-301: Verify that bidirectional coupling is necessary.

The transport.setRouter(this) call establishes a bidirectional reference between Router and Transport, creating tight coupling. While this may be intentional for the new port control features, bidirectional references can:

  • Make the object lifecycle more complex
  • Complicate testing (circular dependencies)
  • Increase coupling between components

Consider whether the Transport truly needs a direct Router reference, or if required functionality could be passed via init() or through a more limited interface.


341-350: LGTM! Clean conditional port opening logic.

The openPorts flag provides flexible control over proxy registration behavior, enabling scenarios like YAML initialization where port opening needs to be deferred. The conditional logic is clear and aligns well with the RouterCLI initialization flows.


533-535: LGTM! Appropriate guard for GlobalInterceptor.

The early return prevents GlobalInterceptor beans from being incorrectly processed as Proxy instances, avoiding potential type errors and double-initialization issues.

Comment thread core/src/main/java/com/predic8/membrane/core/Router.java Outdated
@membrane-ci-server
Copy link
Copy Markdown

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
core/src/main/java/com/predic8/membrane/core/Router.java (1)

550-563: Resolve or remove TODO comment block before merging.

This TODO block explicitly states "Code Should be deleted before merge." As noted in the previous review, this commented-out proxy initialization code needs to be resolved before merging. The block should either be:

  1. Removed if proxy initialization is properly handled elsewhere
  2. Uncommented and refactored if the logic is actually needed
  3. Converted to a tracked issue with a reference if further discussion is required
🧹 Nitpick comments (2)
core/src/main/java/com/predic8/membrane/core/Router.java (2)

18-18: Consider using explicit imports instead of wildcard.

Wildcard imports can reduce code clarity by obscuring which specific classes are being used from the beanregistry package. They can also introduce naming conflicts if the package adds new classes in the future.

🔎 Verify which classes are actually imported
#!/bin/bash
# Description: Find all usages of beanregistry classes in Router.java to determine if wildcard is justified

# Search for class references from the beanregistry package
rg -n "BeanRegistry|BeanDefinition|BeanCacheObserver" core/src/main/java/com/predic8/membrane/core/Router.java

538-541: LGTM! Guard prevents incorrect processing of GlobalInterceptor beans.

The early return for GlobalInterceptor correctly prevents these beans from being processed as Proxy instances, which would fail at line 543. This aligns with the expanded bean activation logic for "global" kind beans mentioned in the PR context.

Consider adding a brief comment explaining why GlobalInterceptor requires special handling:

🔎 Suggested comment
+    // GlobalInterceptor beans are handled separately and should not be processed as Proxy instances
     if (bean instanceof GlobalInterceptor) {
         return;
     }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 520164b and cf52d74.

📒 Files selected for processing (2)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java
  • core/src/main/java/com/predic8/membrane/core/Router.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java
⏰ 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 (3)
core/src/main/java/com/predic8/membrane/core/Router.java (3)

87-94: LGTM! Clear documentation and sensible default.

The new openPorts field is well-documented and defaults to true, maintaining backward compatibility while enabling deferred port opening when needed.


347-356: LGTM! Port opening logic correctly implements the new flag.

The conditional logic properly respects the openPorts flag: when true, ports are opened immediately via addProxyAndOpenPortIfNew; when false, proxies are registered with MANUAL source without opening ports. This enables the deferred port opening behavior described in the PR objectives.


617-624: LGTM! Setter is well-documented and correctly implemented.

The public setter for openPorts is straightforward and enables external control over port opening behavior as intended by the PR objectives.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
core/src/main/java/com/predic8/membrane/core/Router.java (1)

539-552: Resolve or remove TODO comment block before merging.

This TODO block explicitly states "Code Should be deleted before merge" and was flagged in previous reviews. The commented-out initialization code needs to be either:

  1. Removed if the duplicate initialization issue is confirmed resolved
  2. Documented with a reference to a tracking issue if further discussion is needed
  3. Uncommented and refactored if the initialization is actually required

The current state indicates incomplete work that should be addressed before merging.

🧹 Nitpick comments (2)
core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java (1)

30-30: Consider specific imports over wildcards.

The switch to wildcard imports (com.predic8.schema.* and static com.predic8.membrane.core.Constants.*) reduces clarity about which specific types or constants are actually used. Wildcard imports can hide dependencies and make the code harder to understand at a glance.

🔎 Consider reverting to specific imports

For line 30, if only a few schema types are used, list them explicitly:

-import com.predic8.schema.*;
+import com.predic8.schema.Schema;
+import com.predic8.schema.SchemaType;
+// add other specific types as needed

For line 43, restore the specific import if only MEMBRANE_HOME, PRODUCT_NAME, and VERSION are used:

-import static com.predic8.membrane.core.Constants.*;
+import static com.predic8.membrane.core.Constants.MEMBRANE_HOME;
+import static com.predic8.membrane.core.Constants.PRODUCT_NAME;
+import static com.predic8.membrane.core.Constants.VERSION;

Also applies to: 43-43

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

606-613: Consider documenting lifecycle constraints.

The setOpenPorts() method is well-documented and correctly implements the public API. However, consider adding a note in the javadoc that this method should typically be called during router initialization (before start()) to avoid race conditions with concurrent proxy additions.

🔎 Suggested javadoc enhancement
 /**
  * Configures whether the router should open tcp ports when adding proxies. Use this field to create a router
  * and open the ports later
+ * <p>
+ * This method should typically be called during router initialization, before {@link #start()}, to avoid
+ * race conditions with concurrent proxy additions.
  * @param openPorts a boolean indicating whether ports should be opened (true) or closed (false)
  */
 public void setOpenPorts(boolean openPorts) {
     this.openPorts = openPorts;
 }
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf52d74 and 21ae9a1.

📒 Files selected for processing (5)
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanCacheObserver.java
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java
  • annot/src/test/java/com/predic8/membrane/annot/util/YamlParser.java
  • core/src/main/java/com/predic8/membrane/core/Router.java
  • core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java
💤 Files with no reviewable changes (2)
  • annot/src/test/java/com/predic8/membrane/annot/util/YamlParser.java
  • annot/src/main/java/com/predic8/membrane/annot/beanregistry/BeanRegistryImplementation.java
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-11T14:18:23.761Z
Learnt from: rrayst
Repo: membrane/api-gateway PR: 1977
File: core/src/main/java/com/predic8/membrane/core/interceptor/opentelemetry/OpenTelemetryInterceptor.java:107-109
Timestamp: 2025-07-11T14:18:23.761Z
Learning: In Java exception handling, use ExceptionUtil.concatMessageAndCauseMessages(e) instead of e.getMessage() or e.getCause().getMessage() to get a complete view of the exception chain. This utility method safely concatenates all exception messages in the chain with " caused by: " separator, providing comprehensive error information for debugging without risk of NullPointerException.

Applied to files:

  • core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java
📚 Learning: 2025-07-28T16:28:17.849Z
Learnt from: rrayst
Repo: membrane/api-gateway PR: 1977
File: core/src/main/java/com/predic8/membrane/core/interceptor/opentelemetry/OpenTelemetryInterceptor.java:107-109
Timestamp: 2025-07-28T16:28:17.849Z
Learning: In Java exception handling for OpenTelemetry body logging, use log.debug() level with ExceptionUtil.concatMessageAndCauseMessages(e) to log body reading failures. This prevents cluttering info logs with potentially common stream reading issues while still providing comprehensive error information when debug logging is enabled.

Applied to files:

  • core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java
🧬 Code graph analysis (1)
core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java (1)
core/src/main/java/com/predic8/membrane/core/Constants.java (1)
  • Constants (24-103)
⏰ 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 (7)
core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java (2)

159-161: LGTM! Startup message centralized.

The XML initialization flow now uses the centralized logStartupMessage() helper, maintaining consistency with the YAML initialization path.


381-383: LGTM! Centralized startup message.

The new logStartupMessage() helper consolidates startup logging for both XML and YAML initialization paths, emitting a color-coded banner. The implementation is clean and improves maintainability.

core/src/main/java/com/predic8/membrane/core/Router.java (5)

18-18: Wildcard import is justified.

The wildcard import for com.predic8.membrane.annot.beanregistry.* is appropriate here, as the class uses multiple types from this package (BeanRegistry, BeanRegistryAware, BeanCacheObserver, BeanDefinition, etc.).


85-92: LGTM! Well-documented field addition.

The new openPorts field provides explicit control over port-opening behavior with a sensible default (true) that maintains backward compatibility. The comprehensive javadoc clearly explains its purpose.


170-170: LGTM! Modernized string formatting.

Updated to use .formatted() instead of string concatenation, which is more idiomatic for modern Java.


528-530: LGTM! Defensive guard for GlobalInterceptor.

The early return for GlobalInterceptor beans is correct, as GlobalInterceptor is not a Proxy and should not be processed in the proxy lifecycle handling logic. This prevents the IllegalArgumentException that would be thrown at line 533.


344-347: Both code paths consistently use RuleDefinitionSource.MANUAL—no inconsistency exists.

When openPorts is true, addProxyAndOpenPortIfNew(sp) (line 345) invokes the parameterless method, which defaults to RuleDefinitionSource.MANUAL (RuleManager.java line 66). When openPorts is false, line 347 explicitly passes RuleDefinitionSource.MANUAL to addProxy(). The source is semantically consistent across both branches.

Likely an incorrect or invalid review comment.

Comment thread core/src/main/java/com/predic8/membrane/core/cli/RouterCLI.java
@rrayst
Copy link
Copy Markdown
Member

rrayst commented Dec 25, 2025

/ok-to-test

1 similar comment
@rrayst
Copy link
Copy Markdown
Member

rrayst commented Dec 25, 2025

/ok-to-test

@predic8 predic8 merged commit 75f0a80 into master Dec 25, 2025
5 checks passed
@predic8 predic8 deleted the router-refactor-to-beanfactory branch December 25, 2025 14:44
@coderabbitai coderabbitai Bot mentioned this pull request Jan 13, 2026
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.

3 participants