refactor: remove jackson dependency - #101
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe project updates to version 5.4.0-SNAPSHOT, removes test Jackson Databind usage, adds generated-file cleanup, and replaces Jackson string serialization with Vaadin JSON values for OrgChart server-to-client updates. ChangesOrgChart JSON migration
Estimated code review effort: 3 (Moderate) | ~20 minutes Mergeability Score: ⚪ Minimal · up to This dependency-removal refactor has no identified merge-blocking risk at the current head and is merge-ready after normal checks and review. Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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 `@pom.xml`:
- Around line 609-617: Align the frontend cleanup and ignore paths with the
canonical generated frontend directory: update the clean-plugin filesets in
pom.xml lines 609-617, and update both ignore rules in .gitignore lines 25-26 to
reference that same directory.
🪄 Autofix
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 Plus
Run ID: fc2d3570-8691-4bae-adaf-db82b3030ada
📒 Files selected for processing (6)
.gitignorepom.xmlsrc/main/java/com/flowingcode/vaadin/addons/orgchart/OrgChart.javasrc/main/java/com/flowingcode/vaadin/addons/orgchart/OrgChartItem.javasrc/main/java/com/flowingcode/vaadin/addons/orgchart/client/OrgChartState.javasrc/main/resources/META-INF/frontend/fc-orgchart.js
b0e618f to
3b523c2
Compare
|
paodb
left a comment
There was a problem hiding this comment.
I tested this locally in v25 profile and I'm getting the following error in my IDE console when adding a child to a node in the Edit Chart demo:
[qtp2075982863-59] ERROR com.vaadin.flow.server.DefaultErrorHandler - Unexpected error: Cannot deserialize JSON to type elemental.json.JsonArray: Cannot construct instance of `elemental.json.JsonArray` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [No location information]
java.lang.IllegalArgumentException: Cannot deserialize JSON to type elemental.json.JsonArray: Cannot construct instance of `elemental.json.JsonArray` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [No location information]
at com.vaadin.flow.internal.JacksonCodec.decodeAs(JacksonCodec.java:259)
at com.vaadin.flow.server.communication.rpc.DefaultRpcDecoder.decode(DefaultRpcDecoder.java:49)
at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.decodeArg(PublishedServerEventHandlerRpcHandler.java:332)
at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.decodeArgs(PublishedServerEventHandlerRpcHandler.java:268)
at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.invokeMethod(PublishedServerEventHandlerRpcHandler.java:222)
at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.invokeMethod(PublishedServerEventHandlerRpcHandler.java:200)
at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.invokeMethod(PublishedServerEventHandlerRpcHandler.java:146)
at com.vaadin.flow.server.communication.rpc.PublishedServerEventHandlerRpcHandler.handleNode(PublishedServerEventHandlerRpcHandler.java:129)
at com.vaadin.flow.server.communication.rpc.AbstractRpcInvocationHandler.handle(AbstractRpcInvocationHandler.java:80)
at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocationData(ServerRpcHandler.java:640)
at com.vaadin.flow.server.communication.ServerRpcHandler.lambda$handleInvocations$6(ServerRpcHandler.java:613)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at com.vaadin.flow.server.communication.ServerRpcHandler.handleInvocations(ServerRpcHandler.java:613)
at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:433)
at com.vaadin.flow.server.communication.ServerRpcHandler.handleRpc(ServerRpcHandler.java:364)
at com.vaadin.flow.server.communication.UidlRequestHandler.synchronizedHandleRequest(UidlRequestHandler.java:147)
at com.vaadin.flow.server.SynchronizedRequestHandler.handleRequest(SynchronizedRequestHandler.java:73)
at com.vaadin.flow.server.VaadinService.handleRequest(VaadinService.java:2014)
at com.vaadin.flow.server.VaadinServlet.service(VaadinServlet.java:404)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:587)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:764)
at org.eclipse.jetty.servlet.ServletHandler$ChainEnd.doFilter(ServletHandler.java:1665)
at org.eclipse.jetty.websocket.servlet.WebSocketUpgradeFilter.doFilter(WebSocketUpgradeFilter.java:170)
at org.eclipse.jetty.servlet.FilterHolder.doFilter(FilterHolder.java:202)
at org.eclipse.jetty.servlet.ServletHandler$Chain.doFilter(ServletHandler.java:1635)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:527)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:131)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:598)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:223)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1580)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:221)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1381)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:176)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:484)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1553)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:174)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1303)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:129)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:149)
at org.eclipse.jetty.server.handler.HandlerList.handle(HandlerList.java:51)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:122)
at org.eclipse.jetty.server.Server.handle(Server.java:563)
at org.eclipse.jetty.server.HttpChannel$RequestDispatchable.dispatch(HttpChannel.java:1598)
at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:753)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:501)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:287)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:314)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:100)
at org.eclipse.jetty.io.SelectableChannelEndPoint$1.run(SelectableChannelEndPoint.java:53)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.runTask(AdaptiveExecutionStrategy.java:421)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.consumeTask(AdaptiveExecutionStrategy.java:390)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.tryProduce(AdaptiveExecutionStrategy.java:277)
at org.eclipse.jetty.util.thread.strategy.AdaptiveExecutionStrategy.run(AdaptiveExecutionStrategy.java:199)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:411)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:969)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.doRunJob(QueuedThreadPool.java:1194)
at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1149)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: tools.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `elemental.json.JsonArray` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [No location information]
at tools.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:70)
at tools.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1995)
at tools.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:511)
at tools.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1525)
at tools.jackson.databind.deser.AbstractDeserializer.deserialize(AbstractDeserializer.java:254)
at tools.jackson.databind.deser.DeserializationContextExt.readRootValue(DeserializationContextExt.java:266)
at tools.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:2610)
at tools.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:978)
at tools.jackson.databind.ObjectMapper.treeToValue(ObjectMapper.java:1291)
at com.vaadin.flow.internal.JacksonCodec.decodeAs(JacksonCodec.java:255)
... 58 more
Worth checking before approving this PR.
|
@ Tracked separately in #102. |



Close #100
The problem is structural, not a stale version
The v25 build fails at prepare-frontend with NoClassDefFoundError: com/fasterxml/jackson/annotation/JsonSerializeAs. Diffing the effective POM for 25.2.6 against 25.3-SNAPSHOT shows why: Vaadin's BOM manages ~130 com.fasterxml.jackson.* artifacts in 25.2.6 and none in 25.3-SNAPSHOT.
While the BOM was managing those versions, our own pin was being silently overridden and we never noticed it existed. Once that management disappeared, our jackson-databind:2.13.4.2 — a 2023 Dependabot security bump, chosen for Vaadin 14 — became authoritative and pulled jackson-annotations:2.13.4 onto the classpath. Flow 25.3 runs on Jackson 3, whose JacksonAnnotationIntrospector requires jackson-annotations ≥ 2.21. Maven's nearest-wins mediation is explicit about the collision:
tools.jackson.core:jackson-databind:jar:3.1.5:compile
- (com.fasterxml.jackson.core:jackson-annotations:jar:2.21 - omitted for conflict with 2.13.4)
So the add-on had a latent, invisible dependency on Vaadin continuing to manage a transitive artifact on our behalf. That's the actual defect. The NoClassDefFoundError is a symptom.
Why not just bump the pin
I tried this first: 2.13.4.2 → 2.22.1 turns all four profiles green today. I'm not proposing it, because it only works by coincidence of alignment.
jackson-annotations is the one artifact Jackson 2 and Jackson 3 still share — it stayed under com.fasterxml.jackson.core when core/databind moved to tools.jackson.*. Pinning it means pinning a shared artifact whose floor is set by Vaadin's internals and rises with Flow releases. We'd re-break on some future 25.x, discover it only at prepare-frontend on a snapshot profile, and repeat this investigation. We'd also be exporting a hard Jackson pin to every downstream consumer of the add-on.
Why not migrate to Jackson 3
Not available to us. tools.jackson.core:jackson-databind:3.1.5 is compiled to class file major version 61 — Java 17 (checked against the jar's bytecode header). This add-on builds one source tree against four baselines: v14→Java 8, v23→11, v24→17, v25→21. An import of tools.jackson.databind.ObjectMapper compiles fine under -source 8 and then throws UnsupportedClassVersionError the first time a v14 or v23 user renders a chart. Supporting both would mean profile-specific source sets for a single serialization method.
Why elemental.json
We used Jackson for exactly one thing: turning OrgChartItem into a JSON string for the client widget. That's ~30 lines of explicit construction, and it buys:
Summary by CodeRabbit
Improvements
Maintenance