Skip to content

Conversation

@javier-godoy
Copy link
Member

@javier-godoy javier-godoy commented Dec 1, 2025

Summary by CodeRabbit

  • New Features

    • Version-aware instrumentation of client-callable methods with dynamic JSON type mapping and explicit legacy/current support.
    • Migration helper added for newer Vaadin JSON node types.
  • Bug Fixes

    • JSON null now serializes as null.
    • Numeric JSON values serialize as integers when integral; default JSON serialization returns node string instead of throwing.
  • Tests

    • Expanded test suite covering instrumented callables across versions, primitives, wrappers, strings, and JSON value types.

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

@coderabbitai
Copy link

coderabbitai bot commented Dec 1, 2025

Walkthrough

Convert class instrumentation to an instance-based, version-aware utility with dynamic Jackson descriptor lookup; add ClassInstrumentationJacksonHelper; adjust Elemental* toJson behaviors and UnsupportedJsonValueImpl; switch migration helpers to use per-version instrumentation; and add extensive Vaadin 24/25 client-callable test harnesses and fixtures.

Changes

Cohort / File(s) Summary
Instrumentation core
src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java, src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationJacksonHelper.java
Make ClassInstrumentationUtil stateful (constructor with version) and convert many utilities to instance methods; make InstrumentedClassLoader a non-static inner class; add MethodHandle-based delegation to ClassInstrumentationJacksonHelper.getConvertedTypeDescriptor to resolve JSON→Jackson descriptors.
JSON node implementations
src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNullNode.java, src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNumberNode.java, src/main/java/com/flowingcode/vaadin/jsonmigration/UnsupportedJsonValueImpl.java
Add/override toJson() implementations: ElementalNullNode.toJson() returns null; ElementalNumberNode.toJson() returns integral values as long strings else falls back; UnsupportedJsonValueImpl.toJson() returns ((JsonNode)this).toString() instead of throwing.
Migration helpers
src/main/java/com/flowingcode/vaadin/jsonmigration/JsonMigrationHelper25.java, src/main/java/com/flowingcode/vaadin/jsonmigration/LegacyJsonMigrationHelper.java
Instantiate and use ClassInstrumentationUtil per-version (25 and 24); update callers to delegate instrumentation to the instance; LegacyJsonMigrationHelper.instrumentClass return type changed to Class<? extends T>.
Test harness & utilities
src/test/java/com/flowingcode/vaadin/jsonmigration/BaseClientCallable.java, .../ClientCallablesTest*.java, .../LegacyClientCallablesTest*.java
Add abstract reflective test harnesses and concrete subclasses for Vaadin 24/25 that provide JSON factory hooks and instrumentation entrypoints for test suites.
ClientCallable test fixtures (Vaadin 25)
src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_*.java, src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__*.java (many files)
Add ~36 test classes covering parameter and return permutations (primitives, String, Integer, and Jackson JsonNode types) used by the new tests.
LegacyClientCallable test fixtures (Vaadin 24)
src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_*.java, src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__*.java (many files)
Add ~36 legacy test classes mirroring the Vaadin 25 fixtures but annotated with @LegacyClientCallable and using elemental.json factories where applicable.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas needing extra attention:
    • Instance refactor in ClassInstrumentationUtil and InstrumentedClassLoader behavior.
    • MethodHandle/reflection call to ClassInstrumentationJacksonHelper.getConvertedTypeDescriptor: classloading and correctness.
    • Signature change in LegacyJsonMigrationHelper.instrumentClass and its callers.
    • Behavioral changes in toJson() implementations and UnsupportedJsonValueImpl.
    • Large added test suite: verify reflective discovery, expected-exception tests, and JSON fixture correctness.

Possibly related PRs

Suggested reviewers

  • mlopezFC
  • paodb

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.68% 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 main changes: comprehensive unit tests are added alongside internal fixes to class instrumentation logic.
✨ 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 20251130

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

@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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/main/java/com/flowingcode/vaadin/jsonmigration/LegacyJsonMigrationHelper.java (1)

46-48: Incorrect type name in error message.

The error message references JsonObject but the method handles general JsonValue types.

-          object.getClass().getName() + " cannot be converted to elemental.json.JsonObject");
+          object.getClass().getName() + " cannot be converted to elemental.json.JsonValue");
🧹 Nitpick comments (10)
src/main/java/com/flowingcode/vaadin/jsonmigration/UnsupportedJsonValueImpl.java (1)

48-51: Implementation relies on all implementers extending JsonNode.

The cast (JsonNode) this assumes every class implementing UnsupportedJsonValueImpl also extends a Jackson JsonNode type. This is currently valid (e.g., ElementalNullNode extends NullNode, ElementalNumberNode extends NumericNode), but consider adding a comment documenting this constraint for future maintainers.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_Z__V.java (1)

13-14: Remove trailing blank lines.

Apply this diff:

-
-
src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest25.java (1)

21-22: Consider migrating from deprecated ExpectedException.

ExpectedException has been deprecated since JUnit 4.13 in favor of assertThrows. If the project uses JUnit 4.13+ or JUnit 5, consider refactoring to the modern API for clearer test intent.

Example refactor using assertThrows (JUnit 4.13+):

-  @Rule
-  public ExpectedException thrown = ExpectedException.none();
-
   @Override
   protected <T extends Component> Class<? extends T> instrumentClass(Class<T> clazz) {
+    boolean expectException = false;
     for (Class<?> arg : getClientCallableTestMethod(clazz).getParameterTypes()) {
       if (JsonValue.class.isAssignableFrom(arg)) {
-        thrown.expect(IllegalArgumentException.class);
-        thrown.expectMessage(containsString(ERRMSG));
+        expectException = true;
         break;
       }
     }
+    if (expectException) {
+      IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
+        () -> new JsonMigrationHelper25().instrumentClass(clazz));
+      assertTrue(exception.getMessage().contains(ERRMSG));
+      return clazz;
+    }
     return new JsonMigrationHelper25().instrumentClass(clazz);
   }
src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest24.java (2)

16-17: Consider migrating from deprecated ExpectedException.

ExpectedException has been deprecated since JUnit 4.13. Consider refactoring to assertThrows for clearer test intent, similar to the suggestion for ClientCallablesTest25.


28-30: Clarify the assertion intent.

The assertion assertEquals(clazz, instrumentedClazz) suggests that LegacyJsonMigrationHelper returns the original class unchanged for Vaadin 24. If this is the expected behavior, consider adding a comment explaining why instrumentation is skipped.

Example:

+    // For Vaadin 24, LegacyJsonMigrationHelper returns the original class without instrumentation
     Class<? extends T> instrumentedClazz = new LegacyJsonMigrationHelper().instrumentClass(clazz);
     assertEquals(clazz, instrumentedClazz);
src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest.java (2)

24-31: Consider making test method discovery more robust.

The current implementation relies on the method being named exactly "test". This is fragile and could lead to false negatives if the naming convention changes.

Consider either:

  1. Adding validation that exactly one @ClientCallable method exists
  2. Making the method name a parameter or using a more flexible search
 protected static Method getClientCallableTestMethod(Class<? extends Component> clazz) {
+  Method found = null;
   for (Method method : clazz.getDeclaredMethods()) {
     if ("test".equals(method.getName()) && method.isAnnotationPresent(ClientCallable.class)) {
-      return method;
+      if (found != null) {
+        throw new IllegalStateException("Multiple test methods found in " + clazz);
+      }
+      found = method;
     }
   }
-  return null;
+  return found;
 }

43-44: Use assertNotNull for clearer assertion.

Using assertTrue(MESSAGE, testMethod != null) is less clear than assertNotNull(MESSAGE, testMethod).

-    assertTrue(MESSAGE, testMethod != null);
+    assertNotNull(MESSAGE, testMethod);
src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest.java (2)

24-31: Inconsistent visibility with ClientCallablesTest.

In ClientCallablesTest, getClientCallableTestMethod is protected static (allowing subclass access), but here it's private static. Consider making it protected static for consistency, especially if subclasses might need to reference it.

-  private static Method getClientCallableTestMethod(BaseClientCallable c) {
+  protected static Method getClientCallableTestMethod(BaseClientCallable c) {

43-43: Use assertNotNull for clearer assertion.

Using assertTrue(MESSAGE, testMethod != null) is less clear than assertNotNull(MESSAGE, testMethod).

-    assertTrue(MESSAGE, testMethod != null);
+    assertNotNull(MESSAGE, testMethod);
src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java (1)

375-386: Handle ClassNotFoundException explicitly for clarity.

The reflection-based lazy loading of ClassInstrumentationJacksonHelper uses @SneakyThrows, which suppresses checked exceptions. If the helper class is missing, the error will be less clear.

Consider explicit exception handling with a descriptive message:

-    @SneakyThrows
     private String getConvertedTypeDescriptor(Class<?> type) {
       if (getConvertedTypeDescriptor == null) {
+        try {
         Class<?> helper = Class.forName("com.flowingcode.vaadin.jsonmigration.ClassInstrumentationJacksonHelper");
         MethodHandles.Lookup lookup = MethodHandles.lookup();
         MethodType methodType = MethodType.methodType(String.class, Class.class);
         getConvertedTypeDescriptor = lookup.findStatic(helper, "getConvertedTypeDescriptor", methodType);
+        } catch (ClassNotFoundException e) {
+          throw new IllegalStateException(
+            "ClassInstrumentationJacksonHelper not found. Ensure Jackson databind is on the classpath.", e);
+        } catch (Exception e) {
+          throw new IllegalStateException("Failed to initialize type descriptor conversion", e);
+        }
       }
+      try {
       return (String) getConvertedTypeDescriptor.invokeExact(type);
+      } catch (Throwable e) {
+        throw new IllegalStateException("Failed to convert type descriptor for " + type, e);
+      }
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aa010ea and 980e766.

📒 Files selected for processing (60)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationJacksonHelper.java (1 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java (8 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNullNode.java (1 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNumberNode.java (1 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/JsonMigrationHelper25.java (1 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/LegacyJsonMigrationHelper.java (1 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/UnsupportedJsonValueImpl.java (2 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/BaseClientCallable.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_D__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_I__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonArray__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonBoolean__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonNull__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonNumber__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonObject__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonString__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonValue__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_String__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_Z__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__D.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__I.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__Integer.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonArray.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonBoolean.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonNull.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonNumber.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonObject.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonString.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonValue.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__Z.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest24.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest25.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_D__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_I__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonArray__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonBoolean__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonNull__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonNumber__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonObject__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonString__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonValue__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_String__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_Z__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__D.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__I.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__Integer.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonArray.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonBoolean.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNull.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNumber.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonObject.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonString.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonValue.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__Z.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest24.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest25.java (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: javier-godoy
Repo: FlowingCode/JsonMigrationHelper PR: 11
File: src/main/java/com/flowingcode/vaadin/jsonmigration/JsonSerializer.java:281-301
Timestamp: 2025-11-25T16:35:42.544Z
Learning: In the JsonMigrationHelper project, code copied from the Vaadin codebase should be kept consistent with the original source unless there's a specific reason to deviate.
📚 Learning: 2025-11-25T16:35:42.544Z
Learnt from: javier-godoy
Repo: FlowingCode/JsonMigrationHelper PR: 11
File: src/main/java/com/flowingcode/vaadin/jsonmigration/JsonSerializer.java:281-301
Timestamp: 2025-11-25T16:35:42.544Z
Learning: In the JsonMigrationHelper project, code copied from the Vaadin codebase should be kept consistent with the original source unless there's a specific reason to deviate.

Applied to files:

  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonString__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonArray.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonString__V.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNumberNode.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/UnsupportedJsonValueImpl.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonNull__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonString.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonObject.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonValue__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonNull.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNull.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonNumber__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonObject__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__Z.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/JsonMigrationHelper25.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonNumber__V.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationJacksonHelper.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest24.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNumber.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonValue.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonString.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonValue.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/LegacyJsonMigrationHelper.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonBoolean__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonValue__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonNull__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonBoolean__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_Z__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest25.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest25.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest24.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest.java
🔇 Additional comments (54)
src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNullNode.java (1)

31-34: Verify that returning Java null is intentional.

Returning Java null from toJson() differs from the typical JSON serialization expectation where a JSON null value would serialize to the string "null". If the intent is to produce valid JSON output, this should return "null" instead. However, if this is intentional behavior for a specific use case (e.g., signaling "no value" to callers), please confirm.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonArray__V.java (1)

8-14: LGTM!

The test class follows the established naming convention and correctly implements a @ClientCallable method with a JsonArray parameter for instrumentation testing.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonNumber__V.java (1)

8-14: LGTM!

The test class is consistent with the established pattern for @ClientCallable parameter type testing.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonBoolean.java (1)

9-16: LGTM!

The test class correctly implements a @ClientCallable method returning JsonBoolean and follows the established naming convention (double underscore indicating return type).

src/main/java/com/flowingcode/vaadin/jsonmigration/JsonMigrationHelper25.java (1)

45-49: LGTM! Instance-based instrumentation correctly implemented.

The refactoring from static utility to instance-based, version-aware instrumentation (version 25) is correctly implemented. The ClassInstrumentationUtil instance is properly initialized and used.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__D.java (1)

5-5: No action needed. The @LegacyClientCallable annotation is correctly accessible.

The annotation is defined in src/main/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable.java and the test file is in the same package (com.flowingcode.vaadin.jsonmigration). In Java, types within the same package are directly accessible without explicit import statements. The code compiles and functions correctly.

Likely an incorrect or invalid review comment.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__Z.java (1)

6-12: LGTM! Test stub follows expected pattern.

The test stub correctly extends BaseClientCallable and implements a client-callable method that traces execution and returns a boolean value.

Note: The AI summary incorrectly states test(boolean arg), but the actual implementation is parameterless test() returning boolean.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__V.java (1)

6-11: LGTM! Test stub follows expected pattern.

The void-returning client-callable test stub is correctly implemented.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_D__V.java (1)

6-11: LGTM! Test stub follows expected pattern.

The test stub correctly accepts a double parameter and traces execution.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__Integer.java (1)

3-9: LGTM! Legacy test stub follows expected pattern.

The legacy client-callable test stub correctly returns an Integer value after tracing.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonString__V.java (1)

5-10: LGTM! Legacy test stub follows expected pattern.

The legacy test stub correctly accepts a JsonString parameter and traces execution.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonNumber.java (1)

9-15: LGTM! Test stub follows expected pattern.

The test stub correctly returns a JsonNumber value after tracing.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonNull__V.java (1)

8-13: LGTM! Test stub follows expected pattern.

The test stub correctly accepts a JsonNull parameter and traces execution.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__I.java (1)

6-12: LGTM! Test stub follows expected pattern.

The test stub correctly returns a primitive int value after tracing.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonValue__V.java (1)

8-14: LGTM!

The test helper class correctly implements the expected pattern for ClientCallable parameter testing.

src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNumberNode.java (1)

31-39: LGTM!

The conditional formatting logic correctly handles integral double values by formatting them without decimal points, while delegating non-integral and edge cases (NaN, Infinity, overflow) to the parent implementation.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__I.java (1)

3-10: LGTM!

The test helper correctly implements the legacy client-callable pattern with primitive int return type.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonValue.java (1)

9-16: LGTM!

The test helper correctly returns a JsonValue (JsonObject is a valid JsonValue implementation) and follows the expected pattern.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_D__V.java (1)

3-9: LGTM!

The test helper correctly implements the legacy client-callable pattern with a double parameter.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonArray.java (1)

9-16: LGTM!

The test helper correctly returns a JsonArray and follows the expected pattern for testing JsonArray return types.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__Integer.java (1)

6-13: LGTM!

The test helper correctly returns an Integer (autoboxed from primitive 0) and follows the expected pattern for testing wrapper type returns.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonObject.java (1)

9-16: LGTM!

The test helper correctly returns a JsonObject and follows the expected pattern for testing JsonObject return types.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonNull.java (1)

1-16: JsonNull client-callable test looks correct

Imports, annotation usage, trace call, and Json.createNull() return type are all consistent with the rest of the suite.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__D.java (1)

1-13: Primitive double client-callable scaffold is fine

The annotation, return type, and tracing pattern are straightforward and consistent with the other helper classes.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__Z.java (1)

1-10: Legacy boolean client-callable helper is consistent

The use of @LegacyClientCallable, boolean return, and tracing pattern aligns with the overall legacy test suite conventions.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonArray__V.java (1)

1-11: Legacy JsonArray-argument callable is well-formed

Signature, annotation, and body (trace-only) are appropriate for the instrumentation tests and match the established naming scheme.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_String__V.java (1)

1-12: String-parameter client-callable helper looks good

Modern @ClientCallable usage with a single String argument and trace-only body fits the existing test pattern.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonNull__V.java (1)

1-11: Legacy JsonNull-argument callable matches suite conventions

The parameter type, void return, and @LegacyClientCallable usage align cleanly with the other JSON legacy helper classes.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonObject__V.java (1)

1-11: Legacy JsonObject-argument callable is correctly structured

This is a straightforward trace-only legacy endpoint with the expected JsonObject parameter and naming.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonObject.java (1)

1-13: Legacy JsonObject-returning callable implementation is appropriate

The method traces and returns a freshly created JsonObject via Json.createObject(), matching the intended legacy test behavior.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNumber.java (1)

1-13: LGTM! Simple test fixture is correct.

The test class correctly follows the pattern for JSON return-type fixtures: extends BaseClientCallable, calls trace(), and returns an appropriate JsonNumber instance.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNull.java (1)

1-13: LGTM! Simple test fixture is correct.

The test class correctly follows the pattern: extends BaseClientCallable, calls trace(), and returns JsonNull via Json.createNull().

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonValue__V.java (1)

1-11: LGTM! Simple test fixture is correct.

The test class correctly follows the parameter-variant pattern (indicated by __V suffix): extends BaseClientCallable, accepts a JsonValue parameter, and calls trace().

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonValue.java (1)

1-13: LGTM! Simple test fixture is correct.

The test class correctly returns a JsonObject (via Json.createObject()) as JsonValue, which is valid since JsonObject implements the JsonValue interface.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonArray.java (1)

1-13: LGTM! Simple test fixture is correct.

The test class correctly follows the pattern: extends BaseClientCallable, calls trace(), and returns an empty JsonArray via Json.createArray().

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_Z__V.java (1)

1-12: LGTM! Test fixture is correct.

The test class correctly uses @ClientCallable (not @LegacyClientCallable) and follows the parameter-variant pattern for boolean arguments.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_Z__V.java (1)

1-9: LGTM! Simple test fixture is correct.

The test class correctly follows the parameter-variant pattern for boolean arguments with the @LegacyClientCallable annotation.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_I__V.java (1)

1-9: LGTM! Simple test fixture is correct.

The test class correctly follows the parameter-variant pattern for int arguments with the @LegacyClientCallable annotation.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonObject__V.java (1)

1-14: LGTM!

The test class follows the established pattern for client-callable test scaffolding. It correctly extends BaseClientCallable, uses the @ClientCallable annotation, and invokes trace() as expected.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonNumber__V.java (1)

1-11: LGTM!

The test class follows the established pattern for legacy client-callable test scaffolding with proper annotation and trace invocation.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonString.java (1)

1-13: LGTM!

The test class correctly implements the legacy client-callable pattern with a JsonString return type. The naming convention (__JsonString indicating a return type with no parameters) is consistent with the project's test scaffolding patterns.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonBoolean__V.java (1)

1-11: LGTM!

The test class follows the established pattern for legacy client-callable test scaffolding with JsonBoolean parameter type.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonBoolean.java (1)

1-13: LGTM!

The test class correctly implements the legacy client-callable pattern with a JsonBoolean return type, using Json.create(true) to construct the return value.

src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationJacksonHelper.java (2)

19-34: Well-structured type mapping logic.

The type conversion logic correctly handles:

  1. Specific type mappings before the generic JsonValue fallback
  2. Uses identity comparison (==) for concrete types, which is appropriate for Class objects
  3. Falls back to JsonNode for any JsonValue-assignable type not explicitly mapped

10-15: Jackson package path is correct and consistent across the codebase.

The project uses Jackson 3.0.0 (as declared in pom.xml with tools.jackson.core:jackson-databind:3.0.0), which correctly uses the tools.jackson.databind package. All imports throughout the codebase consistently use this namespace. No issues found.

src/main/java/com/flowingcode/vaadin/jsonmigration/LegacyJsonMigrationHelper.java (1)

34-39: Clean delegation to instance-based instrumentation.

The refactoring to use ClassInstrumentationUtil with version 24 for Vaadin 24 legacy support is well-structured. The return type Class<? extends T> correctly reflects that instrumentation may produce a subclass.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_String__V.java (1)

1-9: LGTM!

This test helper class correctly implements the expected pattern for testing legacy client callable methods with String parameters.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest24.java (1)

1-44: LGTM!

The implementation correctly provides Vaadin 24-specific instrumentation and JSON fixtures using elemental.json for legacy client callable tests.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest25.java (1)

12-13: Note about test execution requirements.

The comment indicates this test requires Vaadin 25 in the classpath. Ensure test execution is properly configured to skip or conditionally run this test when Vaadin 25 is not available, to avoid build failures.

Consider adding JUnit assumptions or conditional test execution:

@Before
public void checkVaadinVersion() {
  Assume.assumeTrue("Vaadin 25 required", isVaadin25Available());
}
src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java (5)

57-63: LGTM! Instance-based design enables version-aware instrumentation.

The refactoring from static utility to instance-based architecture with a version field is well-designed, allowing different instrumentation strategies for Vaadin 24 vs 25+.


171-176: Excellent validation! Prevents incorrect annotation usage.

This validation correctly prevents the use of @ClientCallable with JsonValue parameters, enforcing the requirement to use @LegacyClientCallable instead. The error message is clear and actionable.


217-217: Good refactoring: non-static inner class enables access to version.

Making InstrumentedClassLoader a non-static inner class allows it to access the outer class's version field (used in hasLegacyVaadin()), which is essential for version-aware instrumentation.


322-336: LGTM! Primitive return handling is correct.

The bytecode generation correctly handles different primitive return types with appropriate opcodes (LRETURN, FRETURN, DRETURN, IRETURN for primitives, ARETURN for objects).


148-150: The version boundary for legacy Vaadin support is correct.

The method uses version <= 24 to determine legacy Vaadin support, which aligns with Vaadin 25 being the version that removes elemental.json and migrates exclusively to Jackson JsonNode/ObjectNode/ArrayNode as the standard JSON API. Vaadin 25 is a breaking change release that dropped support for elemental.json types, confirming that versions 24 and below are legacy and versions 25+ use the modern JSON handling approach.

Copy link

@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)
src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__D.java (1)

6-6: Consider adding class-level documentation.

The class correctly extends BaseClientCallable and follows the established naming pattern for testing double return types. However, class-level Javadoc would help clarify its purpose within the test suite.

Example:

+/**
+ * Test fixture for @ClientCallable methods with double return type and no parameters.
+ */
 public class ClientCallable__D extends BaseClientCallable {
src/main/java/com/flowingcode/vaadin/jsonmigration/UnsupportedJsonValueImpl.java (1)

24-25: Clarify contract that all UnsupportedJsonValueImpl implementors must also be JsonNode

toJson() now assumes this is a tools.jackson.databind.JsonNode. That’s fine for the current Jackson-backed implementations, but any future implementor that isn’t a JsonNode will hit a ClassCastException.

Consider documenting this requirement in the interface Javadoc (or renaming the interface to make the Jackson coupling explicit) so the constraint is clear to future contributors.

Also applies to: 48-51

src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java (1)

375-386: Consider renaming the getConvertedTypeDescriptor field for clarity

Using the same identifier for both the MethodHandle field and the getConvertedTypeDescriptor(Class<?>) method is legal but confusing at a glance.

Renaming the field (e.g. to convertedTypeDescriptorHandle) would make it clearer when code is referring to the cached handle vs. calling the helper method, and reduce the chance of accidental misuse during future edits.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest25.java (1)

21-22: Consider migrating from ExpectedException to assertThrows.

ExpectedException rule is deprecated in JUnit 4.13+. While functional, consider using assertThrows for new code:

assertThrows(IllegalArgumentException.class, () -> {
    new JsonMigrationHelper25().instrumentClass(clazz);
});

This is optional since the current approach works correctly.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest.java (1)

41-45: Consider using assertNotNull for null checks.

Using assertNotNull is more semantic than assertTrue(x != null):

-    assertTrue(MESSAGE, testMethod != null);
+    assertNotNull(MESSAGE, testMethod);

This is a minor readability improvement.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest.java (2)

41-46: Consider using assertNotNull for null checks.

Same suggestion as in LegacyClientCallablesTest:

-    assertTrue(MESSAGE, testMethod != null);
+    assertNotNull(MESSAGE, testMethod);

11-58: Consider consolidating shared test logic with LegacyClientCallablesTest.

Both ClientCallablesTest and LegacyClientCallablesTest share nearly identical structure and test methods. If future maintenance becomes burdensome, consider extracting a common abstract base that both can extend. However, the current separation is acceptable if the two test suites are expected to diverge in behavior.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between caf64ec and 954619b.

📒 Files selected for processing (60)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationJacksonHelper.java (1 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java (8 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNullNode.java (1 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNumberNode.java (1 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/JsonMigrationHelper25.java (1 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/LegacyJsonMigrationHelper.java (1 hunks)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/UnsupportedJsonValueImpl.java (2 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/BaseClientCallable.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_D__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_I__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonArray__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonBoolean__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonNull__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonNumber__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonObject__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonString__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonValue__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_String__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_Z__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__D.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__I.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__Integer.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonArray.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonBoolean.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonNull.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonNumber.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonObject.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonString.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonValue.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__Z.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest24.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest25.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_D__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_I__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonArray__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonBoolean__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonNull__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonNumber__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonObject__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonString__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonValue__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_String__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_Z__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__D.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__I.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__Integer.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonArray.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonBoolean.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNull.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNumber.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonObject.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonString.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonValue.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__V.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__Z.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest24.java (1 hunks)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest25.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (39)
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonString__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonNull__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonObject.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/BaseClientCallable.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonBoolean__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonBoolean.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_Z__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonObject.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonObject__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonValue.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationJacksonHelper.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_I__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__D.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_D__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonString__V.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNullNode.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__I.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_String__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonArray.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonString.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__Z.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonArray__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonValue__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest24.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__I.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonNull__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonBoolean.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__Z.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_D__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonNull.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonArray__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonValue__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest25.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_I__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonNumber__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__Integer.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__Integer.java
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-25T16:35:42.544Z
Learnt from: javier-godoy
Repo: FlowingCode/JsonMigrationHelper PR: 11
File: src/main/java/com/flowingcode/vaadin/jsonmigration/JsonSerializer.java:281-301
Timestamp: 2025-11-25T16:35:42.544Z
Learning: In the JsonMigrationHelper project, code copied from the Vaadin codebase should be kept consistent with the original source unless there's a specific reason to deviate.

Applied to files:

  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest25.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/JsonMigrationHelper25.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/UnsupportedJsonValueImpl.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNumberNode.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonNumber__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonObject__V.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonValue.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest24.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/LegacyJsonMigrationHelper.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNumber.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonBoolean__V.java
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNull.java
  • src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonString.java
🔇 Additional comments (19)
src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_Z__V.java (1)

1-12: ClientCallable boolean fixture looks consistent and correct

Class setup, annotation, and trace() invocation match the pattern of other ClientCallable_*__V test helpers and correctly exercise a boolean (Z) parameter signature for instrumentation tests. No changes needed.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonBoolean__V.java (1)

1-16: LGTM! Test fixture follows the expected pattern.

The test fixture correctly implements the client-callable pattern for JsonBoolean type verification, consistent with the broader test suite. The unused parameter is intentional for type compatibility testing.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable_JsonObject__V.java (1)

7-10: LGTM! Test fixture correctly implements the pattern.

The method serves as a test fixture to verify that @LegacyClientCallable instrumentation works correctly with JsonObject parameters. The unused parameter is intentional, as the fixture tests parameter type handling rather than parameter usage.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNull.java (1)

1-13: LGTM! Consistent test fixture for JsonNull.

The test class follows the established pattern for LegacyClientCallable test fixtures. The implementation correctly returns a JsonNull instance and maintains consistency with other JSON type test classes.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonNumber.java (1)

1-13: LGTM! Consistent test fixture for JsonNumber.

The test class follows the established pattern for LegacyClientCallable test fixtures. The implementation correctly returns a JsonNumber instance and maintains consistency with other JSON type test classes.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__D.java (2)

1-5: LGTM: Package and imports are correct.

The package declaration and import statement are properly structured for this test fixture.


8-12: LGTM: Test method correctly implements the fixture pattern.

The @ClientCallable method correctly:

  • Calls trace() to record invocation
  • Returns a double value (0.0)
  • Follows the established pattern for testing client-callable methods with double return types
src/main/java/com/flowingcode/vaadin/jsonmigration/JsonMigrationHelper25.java (1)

45-50: Instance-based instrumentation wiring for Vaadin 25 looks correct

Using a shared ClassInstrumentationUtil(25) instance and delegating instrumentClass through it is consistent with the new version-aware design and should behave deterministically for all 25+ usages.

src/main/java/com/flowingcode/vaadin/jsonmigration/ElementalNumberNode.java (1)

31-39: toJson() formatting for integral values is reasonable

The new toJson() logic for emitting integral values without a trailing “.0” and delegating to the default implementation for non-integrals is straightforward and should work well for typical JSON numeric usage.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonValue.java (1)

1-13: Legacy JsonValue client-callable fixture looks consistent

This test helper cleanly mirrors the pattern of the other LegacyClientCallable__* fixtures (trace + return a JsonValue) and should integrate well with the existing client-callables test harness.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonArray.java (1)

1-16: JsonArray client-callable test helper is consistent with the suite

The fixture cleanly follows the established BaseClientCallable + @ClientCallable test() pattern and should integrate without surprises into the existing client-callables tests.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable__JsonNumber.java (1)

1-16: JsonNumber client-callable fixture looks good

This class mirrors the existing client-callable fixtures and provides the expected JsonNumber-returning endpoint for instrumentation tests.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_JsonNumber__V.java (1)

1-14: JsonNumber-parameter client-callable fixture is well-formed

The void-return @ClientCallable with a JsonNumber argument and trace() call fits the existing *_JsonX__V pattern and should give good coverage for JsonValue-parameter instrumentation.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallable_String__V.java (1)

1-12: LGTM!

This test fixture correctly follows the established pattern for ClientCallable test variants. The implementation is clean and consistent with other similar test classes in the PR.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallable__JsonString.java (1)

1-13: LGTM!

The test fixture correctly implements the LegacyClientCallable pattern for JsonString return type, consistent with other JSON-returning test variants in this PR.

src/main/java/com/flowingcode/vaadin/jsonmigration/LegacyJsonMigrationHelper.java (1)

34-39: LGTM!

The instrumentation delegation pattern with version-specific ClassInstrumentationUtil(24) is consistent with the approach used in JsonMigrationHelper25. The return type change to Class<? extends T> correctly reflects that the instrumented class may be a subclass.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest24.java (1)

1-44: LGTM!

The implementation correctly provides Vaadin 24-specific instrumentation via LegacyJsonMigrationHelper and uses elemental.json.Json factory methods appropriate for the legacy JSON API.

src/test/java/com/flowingcode/vaadin/jsonmigration/LegacyClientCallablesTest.java (1)

59-265: LGTM!

The test methods comprehensively cover all ClientCallable variants (primitives, wrappers, String, void, and JsonValue types). The pattern of comparing instrumented vs non-instrumented behavior is effective for validating correctness.

src/test/java/com/flowingcode/vaadin/jsonmigration/ClientCallablesTest.java (1)

60-265: LGTM!

The test methods provide comprehensive coverage for all ClientCallable variants. The structure is consistent with the parallel LegacyClientCallablesTest base, ensuring uniform testing across both annotation types.

Copy link

@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 (1)
src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java (1)

265-266: Consider using hasLegacyVaadin() method for consistency.

The inline negation !hasLegacyVaadin() is used here, but the method hasLegacyVaadin() exists at lines 148-150. Using the method directly would improve readability and maintainability.

Apply this diff for consistency:

-      boolean hasJsonValueReturn = !hasLegacyVaadin() && JsonValue.class.isAssignableFrom(method.getReturnType());
-      boolean hasJsonValueParams = !hasLegacyVaadin() && hasJsonValueParameters(method);
+      boolean isLegacy = hasLegacyVaadin();
+      boolean hasJsonValueReturn = !isLegacy && JsonValue.class.isAssignableFrom(method.getReturnType());
+      boolean hasJsonValueParams = !isLegacy && hasJsonValueParameters(method);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 954619b and b1003d2.

📒 Files selected for processing (1)
  • src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java (8 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: javier-godoy
Repo: FlowingCode/JsonMigrationHelper PR: 11
File: src/main/java/com/flowingcode/vaadin/jsonmigration/JsonSerializer.java:281-301
Timestamp: 2025-11-25T16:35:42.544Z
Learning: In the JsonMigrationHelper project, code copied from the Vaadin codebase should be kept consistent with the original source unless there's a specific reason to deviate.
📚 Learning: 2025-11-25T16:35:42.544Z
Learnt from: javier-godoy
Repo: FlowingCode/JsonMigrationHelper PR: 11
File: src/main/java/com/flowingcode/vaadin/jsonmigration/JsonSerializer.java:281-301
Timestamp: 2025-11-25T16:35:42.544Z
Learning: In the JsonMigrationHelper project, code copied from the Vaadin codebase should be kept consistent with the original source unless there's a specific reason to deviate.

Applied to files:

  • src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java
🔇 Additional comments (7)
src/main/java/com/flowingcode/vaadin/jsonmigration/ClassInstrumentationUtil.java (7)

59-59: Instance-scoped cache correctly fixes the version isolation issue.

The change from static to instance-scoped classLoaderCache (line 59), combined with the non-static InstrumentedClassLoader inner class (line 217), properly resolves the issue flagged in the previous review. Each ClassInstrumentationUtil instance now maintains its own cache and loader instances, ensuring that the captured version matches the util instance that created the loader.

Also applies to: 217-217


164-194: Version-aware method filtering logic is correct.

The filtering logic properly handles version-specific instrumentation requirements:

  • Legacy mode (≤24): instruments only @LegacyClientCallable methods
  • Modern mode: instruments @ClientCallable methods with JsonValue return or @LegacyClientCallable methods
  • Clear validation prevents @ClientCallable with JsonValue parameters (lines 171-176)

The implementation aligns with the version-aware design.


321-336: Primitive return type handling is correct.

The bytecode generation properly handles all JVM return instructions:

  • RETURN for void
  • LRETURN/FRETURN/DRETURN for long/float/double
  • IRETURN for int/short/byte/boolean/char
  • ARETURN for reference types

This implementation is complete and correct.


25-27: New imports and constructor support the version-aware design.

The added imports are appropriate:

  • MethodHandle/MethodHandles/MethodType for dynamic descriptor resolution
  • Stream/Collectors for functional method filtering
  • Constructor properly initializes version-specific state

Also applies to: 35-37, 61-63


152-162: Method candidate filtering logic is correct.

The getDeclaredCallables method properly filters for non-static, non-private methods annotated with either @ClientCallable or @LegacyClientCallable. This provides a clean separation of concerns as the first stage of the filtering pipeline.


144-146: Converting needsInstrumentation to instance method is correct.

This change is necessary to support the instance-based getInstrumentableMethods which requires version-specific context. The logic remains sound.


148-150: Version check helper is clear and well-encapsulated.

The hasLegacyVaadin() method provides a clear, named abstraction for the version threshold logic.

@paodb paodb merged commit 17c0dfd into master Dec 1, 2025
3 checks passed
@github-project-automation github-project-automation bot moved this from To Do to Pending release in Flowing Code Addons Dec 1, 2025
@paodb paodb deleted the 20251130 branch December 1, 2025 17:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Pending release

Development

Successfully merging this pull request may close these issues.

3 participants