Skip to content

feat: initial implementation#10

Merged
paodb merged 3 commits into
masterfrom
first-iteration
May 18, 2026
Merged

feat: initial implementation#10
paodb merged 3 commits into
masterfrom
first-iteration

Conversation

@javier-godoy
Copy link
Copy Markdown
Member

@javier-godoy javier-godoy commented May 13, 2026

Summary by CodeRabbit

  • New Features
    • Added EasyGrid with fluent typed-column API, automatic column discovery, typed renderers, per-column/instance/global configuration, and renderer factories.
  • Documentation
    • New configuration-resolution spec and Row Actions roadmap (planned, not implemented); README expanded with getting-started samples.
  • Demos
    • Multiple demo pages for auto-columns, type/number/date rendering, configuration hierarchy, typed and selective columns.
  • Tests
    • Extensive unit/parameterized tests covering configuration layering, renderer factories, delegation, and construction.
  • Chores
    • Project metadata, build config, .gitignore and demo styles updated.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 640b7f5c-b4cd-427d-9c4b-21027a19d7b6

📥 Commits

Reviewing files that changed from the base of the PR and between 2f27c6c and 653cfab.

📒 Files selected for processing (2)
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/InstanceFormatterNullRepresentationTest.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java

Walkthrough

Adds a new EasyGrid API and implementation with multi-level ColumnConfiguration, renderer factories, bean-property support, multiple demos and models, extensive unit tests and parameterized delegation tests, documentation updates, and Maven/build adjustments.

Changes

EasyGrid implementation, configuration, renderers and tests

Layer / File(s) Summary
Core column configuration types & text renderer
src/main/java/.../config/ColumnConfiguration.java, .../ColumnConfigurationImpl.java, .../ColumnConfigurationLink.java, .../ColumnConfigurationTextRenderer.java
Adds sealed ColumnConfiguration<V> API, package-private ColumnConfigurationImpl with parent chaining, ColumnConfigurationLink primary→fallback read-through, and ColumnConfigurationTextRenderer applying nullRepresentation and optional formatter.
Global / instance configuration maps
src/main/java/.../config/EasyGridConfigurationClassMap.java, .../GlobalEasyGridConfiguration.java, .../InstanceEasyGridConfiguration.java
Adds synchronized type→configuration class map with boxed-primitive handling; global defaults, freeze/forType/resolve semantics; instance-level layering that links over global config.
Renderer factory + helpers
src/main/java/.../renderers/RendererFactory.java, .../LocalDateRenderers.java, .../LocalDateTimeRenderers.java, .../LocalTimeRenderers.java, .../NumberRenderers.java
Introduces RendererFactory<T,V> functional interface and utility factories for LocalDate/LocalDateTime/LocalTime/Number with overloads for patterns, locales, suppliers and nullRepresentation.
EasyGrid core, composite and wrapper
src/main/java/.../EasyGrid.java, .../EasyGridWrapper.java, .../EasyGridComposite.java, .../IEasyGridComposite.java
Adds EasyGrid<T> (concrete wrapper creating internal Grid<T>), EasyGridWrapper supporting bean-property-driven column creation, typed addColumn, ordering/hiding, and typeConfiguration; EasyGridComposite and IEasyGridComposite delegate selected Grid APIs.
EasyColumn façade and column interface
src/main/java/.../EasyColumn.java, .../IEasyGridColumn.java
Adds EasyColumn<T,V> attaching a ColumnConfiguration<V> to Grid.Column<T> with fluent setters (setNullRepresentation, setFormatter, setRendererFactory, as(...), setTextAlign) and renderer refresh; adds sealed IEasyGridColumn with many fluent delegation defaults.
Bean introspection & runtime exception helper
src/main/java/.../BeanPropertyDefinition.java, .../RuntimeReflectiveOperationException.java
Adds BeanPropertyDefinition wrapping Vaadin PropertyDefinition with lazy PropertyDescriptor supplier; adds unchecked RuntimeReflectiveOperationException wrapper.
Demo models, data and service fixtures
src/test/java/.../model/Person.java, .../Address.java, .../NumberSample.java, .../data/PersonData.java, .../service/PersonService.java
Adds demo model classes, data generator and simple PersonService used by demos and tests.
Demo views and registration
src/test/java/.../AutoColumnsDemo.java, .../SelectiveColumnsDemo.java, .../ColumnConfigurationDemo.java, .../ConfigurationHierarchyDemo.java, .../TypeRenderingDemo.java, .../TypedColumnDemo.java, .../NumberRenderingDemo.java, .../EasyGridDemoView.java
Adds multiple routed demo views exercising API and configuration; removes obsolete EasyGridDemo; registers demos and imports demo CSS.
Test harness, param tests and helpers
src/test/java/.../test/DelegationTest.java, .../EasyColumnTestHelper.java, .../GridColumnMethodLister.java, .../*DelegationTest.java, .../GlobalEasyGridConfigurationTest.java, .../GlobalEasyGridConfigurationFreezeTest.java, .../GlobalRendererFactoryTest.java, .../EasyGridConstructionTest.java, .../SerializationTest.java
Adds reflective parameterized DelegationTest base, EasyColumnTestHelper, method lister, and many tests validating configuration delegation, renderer factories, construction, freeze semantics, and serialization; removes old integration ViewIT.

Docs, build and miscellaneous

Layer / File(s) Summary
Specifications and feature docs
SPECIFICATIONS.md, CONFIGURATION_RESOLUTION.md, FEATURE_ROW_ACTIONS.md, README.md
Rewrites SPECIFICATIONS.md for the new API and type-resolution; adds CONFIGURATION_RESOLUTION.md documenting scope-first resolution and current implementation details; adds FEATURE_ROW_ACTIONS.md documenting row actions; updates README badge URL casing and expands developer guide.
Maven POM and profiles
pom.xml
Bumps project version and properties, adds jakarta.servlet-api:6.0.0 (provided), adds test dependencies (Mockito, Vaadin testbench-unit, Vaadin, JavaFaker), updates profile javadoc URL and demo-processor dependency, and bumps vaadin.version in v25 profile.
Git ignore and test resources
.gitignore, src/test/resources/.../easy-grid-demo-styles.css, .../shared-styles.css
Updates .gitignore to ignore /src/main/dev-bundle and /.claude/settings.local.json; adds demo CSS rule and updates/adds license headers in test resource CSS.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch first-iteration

Copy link
Copy Markdown

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

🧹 Nitpick comments (5)
src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java (1)

49-52: ⚡ Quick win

Reorganize field declarations before methods.

The active field (line 52) is declared after the getAppointmentTime() method. Java convention is to group all field declarations together before methods. This makes the class structure clearer and easier to navigate.

♻️ Suggested reorganization
   private String phoneNumber;
   private LocalDate birthDate;
   private LocalDateTime appointmentDateTime;
   private boolean subscriber;
+  private boolean active;

   public LocalTime getAppointmentTime() {
     return appointmentDateTime != null ? appointmentDateTime.toLocalTime() : null;
   }
-  private boolean active;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java`
around lines 49 - 52, The field declaration for active is placed after the
method getAppointmentTime() in class Person; move the private boolean active;
declaration up into the block with the other field declarations (i.e. group all
fields together at the top of the class) so that all fields are declared before
any methods, preserving existing modifiers and order of other fields.
src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java (1)

33-33: ⚡ Quick win

Consider adding @FunctionalInterface annotation.

While the interface correctly extends SerializableFunction and will be treated as a functional interface by the compiler, explicitly annotating it with @FunctionalInterface is a Java best practice that makes the intent clear and enables compile-time verification.

📝 Suggested addition
 /**
  * A named functional interface that creates a {`@link` Renderer} for a grid column given a
  * {`@link` com.vaadin.flow.function.ValueProvider}.
  *
  * `@param` <T> the grid bean type
  * `@param` <V> the column value type
  */
+@FunctionalInterface
 public interface RendererFactory<T, V> extends SerializableFunction<ValueProvider<T, V>, Renderer<T>> {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java`
at line 33, Add the `@FunctionalInterface` annotation to the RendererFactory
interface declaration (RendererFactory<T, V> extends
SerializableFunction<ValueProvider<T, V>, Renderer<T>>) so the compiler enforces
the functional-interface contract and the intent is explicit; simply annotate
the interface line with `@FunctionalInterface` and keep the existing generic
signature unchanged.
src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java (1)

74-80: ⚡ Quick win

Avoid relying on Vaadin internal API for descriptor lookup.

Line 77 calls com.vaadin.flow.internal.BeanUtil, which is explicitly marked "For internal use only. May be renamed or removed in a future release." Use the public JavaBeans API instead: new PropertyDescriptor(propertyName, beanType) directly instantiates the descriptor without requiring Vaadin internals.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java`
around lines 74 - 80, The method getPropertyDescriptor in BeanPropertyDefinition
currently uses the Vaadin internal BeanUtil (BeanUtil.getPropertyDescriptor)
which is unsupported; replace that call with the public JavaBeans API by
creating a new PropertyDescriptor(propertyName, beanType) and keep existing
exception handling (catch IntrospectionException and rethrow as
RuntimeReflectiveOperationException) so behavior remains the same; update
imports to use java.beans.PropertyDescriptor and remove dependency on
com.vaadin.flow.internal.BeanUtil.
src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java (1)

36-41: 💤 Low value

Consider type-safe renderer factory invocation.

The explicit <Object> type parameter combined with the cast to LocalDate bypasses compile-time type safety. While this works in the test context, a more type-safe approach would preserve the resolved type.

♻️ Alternative approach
-    var config = new InstanceEasyGridConfiguration().resolve(LocalDate.class);
-    var renderer = config.<Object>getRendererFactory().apply(v -> (LocalDate) v);
+    var config = new InstanceEasyGridConfiguration().resolve(LocalDate.class);
+    var renderer = config.getRendererFactory().apply(v -> v);

The same pattern applies to the other test methods below.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java`
around lines 36 - 41, The test globalLocalDateRendererFactoryIsApplied uses an
unchecked cast via config.<Object>getRendererFactory().apply(v -> (LocalDate)
v), which bypasses compile-time type safety; change the generic invocation to
the resolved type (use config.<LocalDate>getRendererFactory()) and provide a
type-safe lambda (e.g., v -> v) so no cast is needed; update the same pattern in
the other test methods that call
InstanceEasyGridConfiguration.getRendererFactory to preserve type safety and
avoid raw/unchecked casts, and verify the result is still
instanceOf(LocalDateRenderer.class).
src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java (1)

248-256: 💤 Low value

Consider excluding void.class from the primitive sortability check.

Line 252 uses type.isPrimitive() to determine sortability, but void.class.isPrimitive() returns true even though void values cannot be compared. While this is unlikely to occur in practice (since column value providers wouldn't return void), adding an explicit check would make the code more defensive.

🛡️ Optional defensive check
-    if (Comparable.class.isAssignableFrom(type) || type.isPrimitive()) {
+    if (Comparable.class.isAssignableFrom(type) || (type.isPrimitive() && type != void.class)) {
       column.setComparator((ValueProvider) getter);
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java`
around lines 248 - 256, In createEasyColumn(Class<V> type, ValueProvider<T, V>
getter) the sortability check currently treats all primitives as sortable; make
it defensive by excluding void.class from the primitive branch so void values
aren't considered comparable — change the condition that sets
column.setComparator(...) (referencing createEasyColumn, type.isPrimitive(), and
Comparable.class.isAssignableFrom) to only treat primitives as sortable when
type != void.class.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CONFIGURATION_RESOLUTION.md`:
- Around line 13-20: Several fenced code blocks in CONFIGURATION_RESOLUTION.md
are unlabeled and trigger MD040; update each triple-backtick fence that contains
sequences like "I·Foo → I·Entity → G·Foo → G·Entity → Default", "I·Foo → G·Foo →
I·Entity → G·Entity → Default", "per-column → I·Foo → I·Entity → I·Object →
G·Foo → G·Entity → G·Object → Default", "I·Foo(impl) → I·Entity(impl) →
I·Object(impl)", "G·Foo(impl) → G·Entity(impl) → G·Object(impl)", and
"ColumnConfigurationLink(primary = I·Foo chain, fallback = G·Foo chain)" to use
a language identifier (e.g., text) after the opening ``` so the fences read
```text and satisfy markdown linting.

In `@FEATURE_ROW_ACTIONS.md`:
- Around line 51-54: The example uses easyGrid.addRowAction but refreshes using
grid.getDataProvider().refreshAll(), causing a variable-name mismatch; update
the refresh call to use easyGrid.getDataProvider().refreshAll() (or consistently
rename the grid variable so addRowAction, the deletion call
personService.delete(person), and the subsequent refresh all reference the same
grid instance) so the snippet is internally consistent.

In `@SPECIFICATIONS.md`:
- Around line 184-189: The fenced code block containing the snippet that starts
with "Column·Foo" is missing a language tag; update the opening fence from ```
to ```text so the block is explicitly marked (e.g., change the fence before
"Column·Foo" to "```text") to satisfy MD040; keep the block contents unchanged
and leave the closing fence as ``` to complete the fix.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java`:
- Around line 66-69: The catch block in BeanPropertyDefinition that currently
catches NoSuchElementException | IllegalArgumentException and rethrows a new
IllegalArgumentException for "Can't resolve property name '" + propertyName + "'
from '" + propertySet + "'" must preserve the original exception as the cause;
modify the throw in that catch to pass the caught exception (e) as the cause
when constructing the new IllegalArgumentException so the root cause is retained
in stack traces and logs, keeping the same message but using the constructor
IllegalArgumentException(String, Throwable) (or equivalent) referencing
propertyName and propertySet.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java`:
- Around line 38-41: The class ColumnConfigurationLink currently allows a null
primary which causes setters that call primary.* to NPE at runtime; ensure
primary is non-null by adding an explicit null check (e.g.
Objects.requireNonNull(primary, "primary must not be null")) in the
ColumnConfigurationLink constructor(s) and update any factory methods to enforce
the same, and keep fallback nullable as before; this guarantees setters that
call primary.* (and any methods in ColumnConfigurationLink that assume primary
!= null) are safe.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java`:
- Around line 70-87: There is a race between freeze() and forType(Class<V>)
because the check of the static boolean frozen and the call to
map.getOrCreate(type) are not atomic; fix it by synchronizing access: make
freeze() and forType(...) coordinate on the same lock (e.g., synchronize on
GlobalEasyGridConfiguration.class or add a private static final Object LOCK) and
perform the frozen check and the call to map.getOrCreate(type) inside the same
synchronized block (or use a ReentrantReadWriteLock with write lock in freeze()
and read lock in forType()) so no concurrent thread can create a registration
after freeze() completes.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java`:
- Around line 77-79: The Boolean formatter on
grid.getColumn("subscriber").as(Boolean.class).setFormatter(...) is not
null-safe; update the formatter to guard against null (e.g., treat null as false
or return an explicit placeholder like "Unknown") before dereferencing so it
never throws NPE. Modify the lambda passed to setFormatter on the subscriber
column to first check v for null and then return "Subscribed" or "Not
Subscribed" (or your chosen null placeholder) accordingly.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java`:
- Around line 36-43: The constructor NumberSample(BigDecimal) currently converts
bigDecimal to smaller integer types without overflow checks (fields: bigDecimal,
bigInteger, integer, intValue, longValue, doubleValue), causing silent overflow
for values like 1234567890123.456; either: 1) update the conversions to use
exact checks (use bigInteger = value.toBigInteger(); integer =
bigInteger.intValueExact(); intValue = integer; longValue =
bigInteger.longValueExact();) so an ArithmeticException is thrown on overflow,
or 2) change the demo input in NumberRenderingDemo to a smaller BigDecimal that
fits int/long ranges, or add a comment documenting that overflow is intentional
— pick one approach and apply it consistently to NumberSample's constructor and
the demo.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java`:
- Around line 30-37: The fetch method should validate and clamp pagination
bounds before calling personData.getPersons().subList: ensure offset and limit
are non-negative (treat negative as 0), if limit == 0 return empty list
immediately, clamp offset to be at most size (if offset >= size return empty
list), compute end = min(offset + limit, size) and ensure end >= offset before
calling subList; update the fetch(...) implementation to perform these guards
using the existing fetch method and personData.getPersons() references.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java`:
- Around line 126-133: The buildArg method in DelegationTest only handles
boolean and int primitives and will fail for other primitive parameter types;
update buildArg to cover all primitive types (long, short, byte, char, float,
double) by adding branches like long.class -> Long.valueOf(0L), double.class ->
Double.valueOf(0.0), float.class -> Float.valueOf(0.0f), short.class ->
Short.valueOf((short)0), byte.class -> Byte.valueOf((byte)0), char.class ->
Character.valueOf('\0') while keeping the existing boolean and int branches, and
preserve the existing array and Mockito.mock(type) fallback so arrays and
reference types still behave as before.
- Around line 188-190: The isChainable method is using the wrong variable and a
brittle name-based heuristic; change it to inspect the method's return type
using the targetMethod parameter and treat methods returning void as
non-chainable (e.g., return !targetMethod.getReturnType().equals(Void.TYPE));
update references from method to targetMethod in isChainable to fix the variable
mismatch and derive chainability from the return type instead.

In `@src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java`:
- Around line 68-73: The computed-days-until-birthday code in
TypedColumnDemo.java can throw for Feb 29 births when calling
p.getBirthDate().withYear(today.getYear()); fix by computing the birthday via
MonthDay (e.g., MonthDay birthMd = MonthDay.from(p.getBirthDate())), then create
birthday = birthMd.isValidYear(today.getYear()) ?
birthMd.atYear(today.getYear()) : MonthDay.of(2,28).atYear(today.getYear()) (or
another chosen fallback) so Feb 29 is handled safely, then keep the existing
logic that pushes the birthday to next year and returns today.until(birthday,
ChronoUnit.DAYS).

---

Nitpick comments:
In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java`:
- Around line 74-80: The method getPropertyDescriptor in BeanPropertyDefinition
currently uses the Vaadin internal BeanUtil (BeanUtil.getPropertyDescriptor)
which is unsupported; replace that call with the public JavaBeans API by
creating a new PropertyDescriptor(propertyName, beanType) and keep existing
exception handling (catch IntrospectionException and rethrow as
RuntimeReflectiveOperationException) so behavior remains the same; update
imports to use java.beans.PropertyDescriptor and remove dependency on
com.vaadin.flow.internal.BeanUtil.

In `@src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java`:
- Around line 248-256: In createEasyColumn(Class<V> type, ValueProvider<T, V>
getter) the sortability check currently treats all primitives as sortable; make
it defensive by excluding void.class from the primitive branch so void values
aren't considered comparable — change the condition that sets
column.setComparator(...) (referencing createEasyColumn, type.isPrimitive(), and
Comparable.class.isAssignableFrom) to only treat primitives as sortable when
type != void.class.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java`:
- Line 33: Add the `@FunctionalInterface` annotation to the RendererFactory
interface declaration (RendererFactory<T, V> extends
SerializableFunction<ValueProvider<T, V>, Renderer<T>>) so the compiler enforces
the functional-interface contract and the intent is explicit; simply annotate
the interface line with `@FunctionalInterface` and keep the existing generic
signature unchanged.

In `@src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java`:
- Around line 49-52: The field declaration for active is placed after the method
getAppointmentTime() in class Person; move the private boolean active;
declaration up into the block with the other field declarations (i.e. group all
fields together at the top of the class) so that all fields are declared before
any methods, preserving existing modifiers and order of other fields.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java`:
- Around line 36-41: The test globalLocalDateRendererFactoryIsApplied uses an
unchecked cast via config.<Object>getRendererFactory().apply(v -> (LocalDate)
v), which bypasses compile-time type safety; change the generic invocation to
the resolved type (use config.<LocalDate>getRendererFactory()) and provide a
type-safe lambda (e.g., v -> v) so no cast is needed; update the same pattern in
the other test methods that call
InstanceEasyGridConfiguration.getRendererFactory to preserve type safety and
avoid raw/unchecked casts, and verify the result is still
instanceOf(LocalDateRenderer.class).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a325efc3-43a7-4ca9-b6f0-4641a95438d9

📥 Commits

Reviewing files that changed from the base of the PR and between f30af8c and 219354b.

📒 Files selected for processing (56)
  • .gitignore
  • CONFIGURATION_RESOLUTION.md
  • FEATURE_ROW_ACTIONS.md
  • README.md
  • SPECIFICATIONS.md
  • pom.xml
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGrid.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/RuntimeReflectiveOperationException.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationImpl.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationTextRenderer.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/EasyGridConfigurationClassMap.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/InstanceEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/NumberRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/AutoColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ConfigurationHierarchyDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/DemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/GridColumnMethodLister.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/NumberRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/SelectiveColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypeRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/data/PersonData.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/AbstractViewTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Address.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationImplParentDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationLinkDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnTestHelper.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToConfigurationDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToGridColumnDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/SerializationTest.java
  • src/test/resources/META-INF/frontend/styles/easy-grid-demo-styles.css
  • src/test/resources/META-INF/frontend/styles/shared-styles.css
💤 Files with no reviewable changes (2)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java

Comment on lines +13 to +20
```
I·Foo → I·Entity → G·Foo → G·Entity → Default
```

**Type-first** exhausts all Foo-specific settings before looking at Entity:
```
I·Foo → G·Foo → I·Entity → G·Entity → Default
```
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 13, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add language identifiers to fenced code blocks.

Line 13, Line 18, Line 78, Line 86, Line 92, and Line 98 use unlabeled fences, which triggers MD040 and can fail markdown lint gates.

Suggested fix
-```
+```text
 I·Foo → I·Entity → G·Foo → G·Entity → Default

- +text
I·Foo → G·Foo → I·Entity → G·Entity → Default


-```
+```text
per-column → I·Foo → I·Entity → I·Object → G·Foo → G·Entity → G·Object → Default

- +text
I·Foo(impl) → I·Entity(impl) → I·Object(impl)


-```
+```text
G·Foo(impl) → G·Entity(impl) → G·Object(impl)

- +text
ColumnConfigurationLink(primary = I·Foo chain, fallback = G·Foo chain)

Also applies to: 78-100

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 13-13: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 18-18: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CONFIGURATION_RESOLUTION.md` around lines 13 - 20, Several fenced code blocks
in CONFIGURATION_RESOLUTION.md are unlabeled and trigger MD040; update each
triple-backtick fence that contains sequences like "I·Foo → I·Entity → G·Foo →
G·Entity → Default", "I·Foo → G·Foo → I·Entity → G·Entity → Default",
"per-column → I·Foo → I·Entity → I·Object → G·Foo → G·Entity → G·Object →
Default", "I·Foo(impl) → I·Entity(impl) → I·Object(impl)", "G·Foo(impl) →
G·Entity(impl) → G·Object(impl)", and "ColumnConfigurationLink(primary = I·Foo
chain, fallback = G·Foo chain)" to use a language identifier (e.g., text) after
the opening ``` so the fences read ```text and satisfy markdown linting.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Defer to reviewers' judgment. This file is intended for AI consumption.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@javier-godoy, understood — I'll dismiss this concern. Since CONFIGURATION_RESOLUTION.md is intended for AI consumption rather than human readers or standard documentation pipelines, markdown lint compliance is not a meaningful concern here.


✏️ Learnings added
Learnt from: javier-godoy
Repo: FlowingCode/EasyGridAddon PR: 10
File: CONFIGURATION_RESOLUTION.md:13-20
Timestamp: 2026-05-14T12:05:24.375Z
Learning: The file `CONFIGURATION_RESOLUTION.md` in the `FlowingCode/EasyGridAddon` repository is intended for AI consumption, not for human readers or standard documentation pipelines. Markdown style/lint issues (e.g., MD040 unlabeled fenced code blocks) should not be flagged in this file during code reviews.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is okay for me to dismiss this.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Comment thread FEATURE_ROW_ACTIONS.md
Comment thread SPECIFICATIONS.md
Comment thread src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java Outdated
Copy link
Copy Markdown

@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.

♻️ Duplicate comments (1)
src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java (1)

67-73: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle leap-day birthdays safely in computed column logic.

Line 69/Line 72 can throw at runtime for Feb 29 birthdays in non-leap years due to withYear(...), which can break rendering for those rows.

Suggested fix
 import java.time.LocalDate;
+import java.time.MonthDay;
 import java.time.temporal.ChronoUnit;
@@
     grid.addColumn(Integer.class, p -> {
       LocalDate today = LocalDate.now();
-      LocalDate birthday = p.getBirthDate().withYear(today.getYear());
+      MonthDay birthMd = MonthDay.from(p.getBirthDate());
+      LocalDate birthday = birthMd.atYear(today.getYear());
 
       if (birthday.isBefore(today)) {
-        birthday = p.getBirthDate().withYear(today.getYear() + 1);
+        birthday = birthMd.atYear(today.getYear() + 1);
       }
 
       return (int) ChronoUnit.DAYS.between(today, birthday);
     }).setHeader("Days Until Birthday");
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java`
around lines 67 - 73, The computed-birthday logic in grid.addColumn (the lambda
using p.getBirthDate() and withYear(...)) can throw for Feb 29 birthdays in
non-leap years; update the code that computes birthday to choose a valid day for
the target year instead of blindly calling withYear. Concretely, compute
targetYear = today.getYear() (and targetYear+1 where used), then build birthday
using LocalDate.of(targetYear, birthDate.getMonthValue(),
Math.min(birthDate.getDayOfMonth(), Year.of(targetYear).length())) (or wrap
withYear in a try/catch and fallback to the last valid day of the month) so Feb
29s are mapped safely to Feb 28 in non-leap years before the before/after
comparisons.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java`:
- Around line 67-73: The computed-birthday logic in grid.addColumn (the lambda
using p.getBirthDate() and withYear(...)) can throw for Feb 29 birthdays in
non-leap years; update the code that computes birthday to choose a valid day for
the target year instead of blindly calling withYear. Concretely, compute
targetYear = today.getYear() (and targetYear+1 where used), then build birthday
using LocalDate.of(targetYear, birthDate.getMonthValue(),
Math.min(birthDate.getDayOfMonth(), Year.of(targetYear).length())) (or wrap
withYear in a try/catch and fallback to the last valid day of the month) so Feb
29s are mapped safely to Feb 28 in non-leap years before the before/after
comparisons.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1b032e9f-8d3a-46cd-983c-6557e27a2096

📥 Commits

Reviewing files that changed from the base of the PR and between 12bc9bb and 031a694.

📒 Files selected for processing (11)
  • pom.xml
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java
🚧 Files skipped from review as they are similar to previous changes (10)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • pom.xml
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java

Copy link
Copy Markdown

@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/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java (1)

51-54: 💤 Low value

Consider clarifying the test name.

The test name suggests it verifies that an entry is created, but the implementation only checks that resolve() returns non-null without verifying whether a new entry was actually created. Since LocalDate is pre-registered (per the comment on line 71), this test may be verifying retrieval rather than creation. Consider renaming to something like resolveBeforeFreezeReturnsNonNull or adding assertions to explicitly verify creation behavior if that's the intent.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java`
around lines 51 - 54, The test name resolveBeforeFreezeCreatesEntry is
misleading because it only asserts
GlobalEasyGridConfiguration.resolve(LocalDate.class) != null; either rename the
test to resolveBeforeFreezeReturnsNonNull (or similar) to reflect its behavior,
or modify the test to explicitly verify creation (e.g., assert absence in the
registry before calling resolve and presence after) by using the registry
accessors used elsewhere in GlobalEasyGridConfiguration; update the method name
and any references accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java`:
- Around line 55-59: The test currently uses hasItems(...) which allows extra
unexpected columns; update the assertion in EasyGridConstructionTest so the
collected keys (from grid.getWrappedGrid().getColumns() -> keys) are asserted
for exact content/size — e.g., replace the hasItems assertion with an
exact-match assertion (such as assertThat(keys, contains(...)) or assertEquals
on a List of expected keys) to ensure no extra columns are present.

---

Nitpick comments:
In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java`:
- Around line 51-54: The test name resolveBeforeFreezeCreatesEntry is misleading
because it only asserts GlobalEasyGridConfiguration.resolve(LocalDate.class) !=
null; either rename the test to resolveBeforeFreezeReturnsNonNull (or similar)
to reflect its behavior, or modify the test to explicitly verify creation (e.g.,
assert absence in the registry before calling resolve and presence after) by
using the registry accessors used elsewhere in GlobalEasyGridConfiguration;
update the method name and any references accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 17eb997e-af69-427a-8309-02c50e552807

📥 Commits

Reviewing files that changed from the base of the PR and between 031a694 and 8002919.

📒 Files selected for processing (3)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java

@paodb
Copy link
Copy Markdown
Member

paodb commented May 14, 2026

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

✅ Actions performed

Full review triggered.

Copy link
Copy Markdown

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

♻️ Duplicate comments (1)
src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java (1)

30-31: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Validate pagination inputs before skip/limit.

offset < 0 or limit < 0 will fail at runtime. Guard and clamp bounds before slicing.

Suggested fix
   public List<Person> fetch(int offset, int limit) {
-    return personData.getPersons().stream().skip(offset).limit(limit).toList();
+    if (offset < 0 || limit < 0) {
+      throw new IllegalArgumentException("offset and limit must be non-negative");
+    }
+    List<Person> persons = personData.getPersons();
+    int size = persons.size();
+    if (offset >= size || limit == 0) {
+      return List.of();
+    }
+    int end = (int) Math.min((long) size, (long) offset + limit);
+    return persons.subList(offset, end);
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java`
around lines 30 - 31, The fetch method may throw for negative pagination values;
in PersonService.fetch validate and clamp offset/limit before slicing the list
from personData.getPersons(): compute safeOffset = max(0, offset) and safeLimit
= max(0, limit), get the list size, return empty list if safeOffset >= size,
otherwise call stream().skip(safeOffset).limit(min(safeLimit, size -
safeOffset)).toList() so skip/limit never receive negative or out-of-range
values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java`:
- Around line 104-106: resolve(...) returns the actual mutable
ColumnConfiguration instance when frozen, so callers can still mutate global
state; change resolve to return a defensive copy or an immutable/read-only view
when frozen (e.g., if frozen return a copy or an unmodifiable wrapper of
map.get(type) instead of the live instance). Locate the resolve method and
replace the frozen branch to return a safe copy (or wrap via a new
ReadOnlyColumnConfiguration(map.get(type)) or map.get(type).copy() / clone()),
ensuring nulls are handled the same as forType(type).

In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnTestHelper.java`:
- Around line 45-46: The mocked renderer factory ignores its input and always
renders item.toString(); update the Mockito stub for mock.getRendererFactory()
in EasyColumnTestHelper to use the provided getter parameter: return a
TextRenderer that calls getter.apply(item) (or getter.apply(item)::toString as
appropriate) so the renderer uses the actual value-provider passed into the
factory instead of Object::toString; keep using
com.vaadin.flow.data.renderer.TextRenderer and ensure the lambda references the
factory parameter named getter.

In `@src/test/resources/META-INF/frontend/styles/shared-styles.css`:
- Around line 1-20: The CSS comment blocks in shared-styles.css violate the
comment-whitespace-inside rule; fix by ensuring all block comments use a single
space after the opening /* and a single space before the closing */, e.g. change
/*- and /*Demo styles*/ to /* - ... */ and /* Demo styles */ (apply consistently
across the header license block and any short comments) so stylelint passes.

---

Duplicate comments:
In
`@src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java`:
- Around line 30-31: The fetch method may throw for negative pagination values;
in PersonService.fetch validate and clamp offset/limit before slicing the list
from personData.getPersons(): compute safeOffset = max(0, offset) and safeLimit
= max(0, limit), get the list size, return empty list if safeOffset >= size,
otherwise call stream().skip(safeOffset).limit(min(safeLimit, size -
safeOffset)).toList() so skip/limit never receive negative or out-of-range
values.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 25cf5000-9af9-424b-8b60-6f55ca439bbe

📥 Commits

Reviewing files that changed from the base of the PR and between f30af8c and 23b26a3.

📒 Files selected for processing (58)
  • .gitignore
  • CONFIGURATION_RESOLUTION.md
  • FEATURE_ROW_ACTIONS.md
  • README.md
  • SPECIFICATIONS.md
  • pom.xml
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGrid.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/RuntimeReflectiveOperationException.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationImpl.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationTextRenderer.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/EasyGridConfigurationClassMap.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/InstanceEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/NumberRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/AutoColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ConfigurationHierarchyDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/DemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/GridColumnMethodLister.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/NumberRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/SelectiveColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypeRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/data/PersonData.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/AbstractViewTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Address.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationImplParentDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationLinkDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnTestHelper.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToConfigurationDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToGridColumnDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/SerializationTest.java
  • src/test/resources/META-INF/frontend/styles/easy-grid-demo-styles.css
  • src/test/resources/META-INF/frontend/styles/shared-styles.css
💤 Files with no reviewable changes (2)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java

Comment on lines +104 to +106
public <V> ColumnConfiguration<V> resolve(Class<V> type) {
return frozen ? map.get(type) : forType(type);
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 14, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

resolve() currently allows post-freeze global mutation.

After freeze(), callers can still do GlobalEasyGridConfiguration.resolve(type).set..., which mutates global config and bypasses the “locked after startup” contract.

🔧 Minimal fix
-  public <V> ColumnConfiguration<V> resolve(Class<V> type) {
+  static <V> ColumnConfiguration<V> resolve(Class<V> type) {
     return frozen ? map.get(type) : forType(type);
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public <V> ColumnConfiguration<V> resolve(Class<V> type) {
return frozen ? map.get(type) : forType(type);
}
static <V> ColumnConfiguration<V> resolve(Class<V> type) {
return frozen ? map.get(type) : forType(type);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java`
around lines 104 - 106, resolve(...) returns the actual mutable
ColumnConfiguration instance when frozen, so callers can still mutate global
state; change resolve to return a defensive copy or an immutable/read-only view
when frozen (e.g., if frozen return a copy or an unmodifiable wrapper of
map.get(type) instead of the live instance). Locate the resolve method and
replace the frozen branch to return a safe copy (or wrap via a new
ReadOnlyColumnConfiguration(map.get(type)) or map.get(type).copy() / clone()),
ensuring nulls are handled the same as forType(type).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@javier-godoy is this resolved?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

Copy link
Copy Markdown
Member Author

@javier-godoy javier-godoy May 18, 2026

Choose a reason for hiding this comment

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

Yes. resolve() is package-private, so external callers cannot invoke it. The public API entry point is forType(), which throws IllegalStateException when frozen. The only remaining theoretical gap is a caller who retained a ColumnConfiguration reference obtained from forType() before freezing could still mutate it afterwards, but that is a general Java object-mutability concern rather than something this method exposes.

Comment thread src/test/resources/META-INF/frontend/styles/shared-styles.css Outdated
Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@CONFIGURATION_RESOLUTION.md`:
- Around line 31-33: Update the docs to use the canonical API name: replace
examples calling easyGrid.configuration.forType(...) with the spec-defined
easyGrid.typeConfiguration(Class) usage; ensure all occurrences (including the
other example block currently showing easyGrid.configuration.forType) are
changed so the docs consistently reference easyGrid.typeConfiguration and its
Class-based signature.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cd8a906a-8d1b-4d18-b379-b191c49380a3

📥 Commits

Reviewing files that changed from the base of the PR and between 8002919 and 0691f32.

📒 Files selected for processing (58)
  • .gitignore
  • CONFIGURATION_RESOLUTION.md
  • FEATURE_ROW_ACTIONS.md
  • README.md
  • SPECIFICATIONS.md
  • pom.xml
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGrid.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/RuntimeReflectiveOperationException.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationImpl.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationTextRenderer.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/EasyGridConfigurationClassMap.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/InstanceEasyGridConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/NumberRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/AutoColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ConfigurationHierarchyDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/DemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/GridColumnMethodLister.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/NumberRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/SelectiveColumnsDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypeRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/data/PersonData.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/AbstractViewTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Address.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationImplParentDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationLinkDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnTestHelper.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToConfigurationDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToGridColumnDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/SerializationTest.java
  • src/test/resources/META-INF/frontend/styles/easy-grid-demo-styles.css
  • src/test/resources/META-INF/frontend/styles/shared-styles.css
💤 Files with no reviewable changes (3)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemo.java
  • src/test/resources/META-INF/frontend/styles/shared-styles.css
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/ViewIT.java
✅ Files skipped from review due to trivial changes (8)
  • .gitignore
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/RuntimeReflectiveOperationException.java
  • src/test/resources/META-INF/frontend/styles/easy-grid-demo-styles.css
  • README.md
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/InstanceEasyGridConfiguration.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/it/AbstractViewTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/DemoView.java
  • src/test/java/com/flowingcode/vaadin/addons/DemoLayout.java
🚧 Files skipped from review as they are similar to previous changes (44)
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/EasyGridDemoView.java
  • FEATURE_ROW_ACTIONS.md
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Address.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/NumberSample.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/GridColumnMethodLister.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/model/Person.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/EasyGridConfigurationClassMap.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateTimeRenderers.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationTextRenderer.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/RendererFactory.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToGridColumnDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/NumberRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalEasyGridConfigurationFreezeTest.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGrid.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyGridConstructionTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypedColumnDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/SerializationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/SelectiveColumnsDemo.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationLink.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfiguration.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/NumberRenderers.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ConfigurationHierarchyDemo.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridColumn.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnTestHelper.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/service/PersonService.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalDateRenderers.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/TypeRenderingDemo.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/GlobalRendererFactoryTest.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridComposite.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/data/PersonData.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/ColumnConfigurationImpl.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyGridWrapper.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/BeanPropertyDefinition.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/EasyColumn.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/EasyColumnToConfigurationDelegationTest.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/renderers/LocalTimeRenderers.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationImplParentDelegationTest.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/ColumnConfigurationLinkDelegationTest.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/config/GlobalEasyGridConfiguration.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/ColumnConfigurationDemo.java
  • src/main/java/com/flowingcode/vaadin/addons/easygrid/IEasyGridComposite.java
  • src/test/java/com/flowingcode/vaadin/addons/easygrid/test/DelegationTest.java
  • pom.xml

Comment thread CONFIGURATION_RESOLUTION.md
@javier-godoy javier-godoy requested review from paodb and scardanzan May 14, 2026 17:37
@javier-godoy javier-godoy marked this pull request as ready for review May 14, 2026 17:38
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread FEATURE_ROW_ACTIONS.md
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
@github-project-automation github-project-automation Bot moved this from To Do to In Progress in Flowing Code Addons May 15, 2026
@javier-godoy javier-godoy requested a review from paodb May 18, 2026 12:35
Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Around line 86-95: The snippet declares the same variable name twice (grid)
causing a compile error; rename the second EasyGrid instance and its usages to a
unique identifier such as explicitGrid: change the second declaration
EasyGrid<Person> grid to EasyGrid<Person> explicitGrid and update subsequent
calls grid.setItems(...) and add(grid) to explicitGrid.setItems(...) and
add(explicitGrid) to keep both examples in the same scope.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: cd55f30e-3865-428f-9d5e-7279f1aad07a

📥 Commits

Reviewing files that changed from the base of the PR and between de3c379 and 2f27c6c.

📒 Files selected for processing (2)
  • FEATURE_ROW_ACTIONS.md
  • README.md
✅ Files skipped from review due to trivial changes (1)
  • FEATURE_ROW_ACTIONS.md

Comment thread README.md
Comment on lines +86 to +95
```java
// Auto-discover columns from bean properties
EasyGrid<Person> grid = new EasyGrid<>(Person.class);
grid.setItems(personService.findAll());
add(grid);

// Or specify columns explicitly
EasyGrid<Person> grid = new EasyGrid<>(Person.class, "firstName", "lastName", "email");
grid.setItems(personService.findAll());
add(grid);
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 18, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In Java, can a local variable be redeclared in the same scope (e.g., EasyGrid grid twice in one method/block)?

💡 Result:

No, in Java, a local variable cannot be redeclared within the same scope [1][2][3]. If you attempt to declare a variable with the same name as an existing local variable in the same block or method, the Java compiler will report a compilation error [1][2][3]. Java uses block scoping, meaning a variable's scope is defined by the nearest enclosing curly braces {} [1][4]. Within that specific scope, each identifier must be unique [1][2]. For example, the following code is invalid and will fail to compile: void myMethod { EasyGrid grid = new EasyGrid<>; //... EasyGrid grid = new EasyGrid<>; // Compilation error: variable grid is already defined } However, you can declare a variable with the same name if it is in a different, nested scope (such as inside an inner block or a loop) [1][3]. In this case, the inner declaration shadows the outer one, meaning the outer variable becomes inaccessible by its simple name within that inner block [1][5][3]. void myMethod { EasyGrid grid = new EasyGrid<>; { EasyGrid grid = new EasyGrid<>; // This is allowed because it is in a new, nested scope } }

Citations:


Split the two Java examples or rename the second variable.

grid is declared twice in the same scope, preventing the code snippet from compiling. Rename the second instance to explicitGrid:

Proposed doc fix
 ```java
 // Auto-discover columns from bean properties
 EasyGrid<Person> grid = new EasyGrid<>(Person.class);
 grid.setItems(personService.findAll());
 add(grid);

 // Or specify columns explicitly
-EasyGrid<Person> grid = new EasyGrid<>(Person.class, "firstName", "lastName", "email");
-grid.setItems(personService.findAll());
-add(grid);
+EasyGrid<Person> explicitGrid = new EasyGrid<>(Person.class, "firstName", "lastName", "email");
+explicitGrid.setItems(personService.findAll());
+add(explicitGrid);
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` around lines 86 - 95, The snippet declares the same variable name
twice (grid) causing a compile error; rename the second EasyGrid instance and
its usages to a unique identifier such as explicitGrid: change the second
declaration EasyGrid<Person> grid to EasyGrid<Person> explicitGrid and update
subsequent calls grid.setItems(...) and add(grid) to explicitGrid.setItems(...)
and add(explicitGrid) to keep both examples in the same scope.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's just a readme example, no need to fix anything.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

Understood, @paodb — README snippets are illustrative and don't need to compile. I'll dismiss this comment.

(ˆ ᴗ ˆ)っ


🏁 Script executed:

#!/bin/bash
# Resolve the review comment
gh pr view 10 --repo FlowingCode/EasyGridAddon --json reviews,comments

# List bot comments to find the one to resolve
gh api graphql -f query='
{
  repository(owner: "FlowingCode", name: "EasyGridAddon") {
    pullRequest(number: 10) {
      reviewThreads(first: 50) {
        nodes {
          id
          isResolved
          comments(first: 5) {
            nodes {
              id
              body
              author { login }
              url
            }
          }
        }
      }
    }
  }
}'

Length of output: 233729


@paodb Understood. I’ll treat this README snippet as illustrative and won’t push this change. Marking it non-blocking on my side.


✏️ Learnings added
Learnt from: paodb
Repo: FlowingCode/EasyGridAddon PR: 10
File: README.md:86-95
Timestamp: 2026-05-18T14:34:28.752Z
Learning: Repo: FlowingCode/EasyGridAddon
Context: README.md code snippets
Learning: README examples are illustrative and need not be strictly compilable; avoid nitpicks like duplicate local variable declarations within a single snippet unless the team explicitly requests such edits.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Copy link
Copy Markdown
Member

@paodb paodb left a comment

Choose a reason for hiding this comment

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

On a Claude review, this was mention. I think it's worth taking a look:

null-representation falls off the chain when setFormatter is called on an instance-type config.

ColumnConfigurationImpl.setFormatter (ColumnConfigurationImpl.java:87) captures this — the impl — in the renderer:
setRendererFactory(getter -> new ColumnConfigurationTextRenderer<>(getter, this, formatter));
When the call comes through EasyColumn.setFormatter (per-column layer above the Link), this is the column-level impl whose parent chain does include the Link, so it works. But when the call comes through EasyGrid.typeConfiguration(X).setFormatter(...), Link.setFormatter forwards to primary.setFormatter, so this ends up being I·X_impl. Its parent chain is purely the instance side (I·X → I·Object) and never reaches the global chain — so G·Object.nullRepresentation = "" (the built-in default) is not honored, and null values fall through to null/empty in the renderer. Fix would be to have Link.setFormatter build the renderer using the link itself, or have setFormatter accept the lookup config explicitly.

@javier-godoy javier-godoy requested a review from paodb May 18, 2026 17:32
@paodb paodb merged commit bd4afd2 into master May 18, 2026
3 of 4 checks passed
@paodb paodb deleted the first-iteration branch May 18, 2026 18:18
@github-project-automation github-project-automation Bot moved this from In Progress to Pending release in Flowing Code Addons May 18, 2026
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.

2 participants