Skip to content

CAMEL-24604: camel-jpa - Mark KeyValueEntry.isExpired() as @Transient - #26068

Open
JiriOndrusek wants to merge 1 commit into
apache:mainfrom
JiriOndrusek:fix/CAMEL-24604
Open

CAMEL-24604: camel-jpa - Mark KeyValueEntry.isExpired() as @Transient#26068
JiriOndrusek wants to merge 1 commit into
apache:mainfrom
JiriOndrusek:fix/CAMEL-24604

Conversation

@JiriOndrusek

Copy link
Copy Markdown
Contributor

Fixes CAMEL-24604
Follow-up ticket: https://issues.apache.org/jira/browse/CAMEL-24615

KeyValueEntry uses property access, so the derived isExpired() getter was treated as a persistent property without a setter and Hibernate failed to build the SessionFactory (Could not locate setter method for property 'expired'). On Quarkus, where every classpath @Entity is auto-discovered and mapped with Hibernate, this broke any application having camel-jpa on the classpath. @Transient excludes the helper from the persistent metamodel — no schema or behavior change.

The fix is covered by the new KeyValueEntryHibernateMappingTest, which verifies the Hibernate mapping in every build (native Hibernate bootstrap, so the rest of the suite keeps using OpenJPA; the default persistence units are pinned to the OpenJPA provider to keep resolution deterministic with two providers on the classpath)

🤖 Generated with Claude Code

Description

Target

  • I checked that the commit is targeting the correct branch (Camel 4 uses the main branch)

Tracking

  • If this is a large change, bug fix, or code improvement, I checked there is a JIRA issue filed for the change (usually before you start working on it).

Apache Camel coding standards and style

  • I checked that each commit in the pull request has a meaningful subject line and body.
  • I have run mvn clean install -DskipTests locally from root folder and I have committed all auto-generated changes.

AI-assisted contributions

  • If this PR includes AI-generated code, commits have proper co-authorship attribution (e.g., Co-authored-by trailers) and the PR description identifies the AI tool used.

  The entity uses property access, so the derived isExpired() getter was
  treated as a persistent property without a setter and Hibernate failed to
  build the SessionFactory ("Could not locate setter method for property
  'expired'"). On Quarkus this broke any application with camel-jpa on the
  classpath, since the entity is auto-discovered and mapped with Hibernate.

  The fix is covered by the new KeyValueEntryHibernateMappingTest, which runs
  in every bu.

  The OpenJPA enhancer -javaagent is now configured only while the openjpa
  profile is active: the agent jar is copied to target/ by that profile alone,
  so with -Dhibernate the forked test JVM pointed at a missing jar and failed
  to start. The OpenJPA persistence.xml configuresopenjpa provcider
  (as hibernate is now on classpath)

  Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@JiriOndrusek
JiriOndrusek requested a review from gnodet September 3, 2026 08:20
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • components/camel-jpa

🔬 Scalpel shadow comparison — Scalpel: 9 tested, 27 compile-only — current: 9 all tested

Maveniverse Scalpel detected 36 affected modules (current approach: 9).

⚠️ Modules only in Scalpel (27)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

Skip-tests mode would test 9 modules (1 direct + 8 downstream), skip tests for 27 (generated code, meta-modules)

Modules Scalpel would test (9)
  • camel-jbang-mcp
  • camel-jbang-plugin-mcp
  • camel-jbang-plugin-route-parser
  • camel-jbang-plugin-tui
  • camel-jbang-plugin-validate
  • camel-jpa
  • camel-launcher-container
  • camel-yaml-dsl-validator
  • camel-yaml-dsl-validator-maven-plugin
Modules with tests skipped (27)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

All tested modules (36 modules)
  • Camel :: All Components Sync point
  • Camel :: Assembly
  • Camel :: Catalog :: Camel Catalog
  • Camel :: Catalog :: Camel Report Maven Plugin
  • Camel :: Catalog :: Camel Route Parser
  • Camel :: Catalog :: Console
  • Camel :: Catalog :: Dummy Component
  • Camel :: Catalog :: Maven
  • Camel :: Catalog :: Suggest
  • Camel :: Component DSL
  • Camel :: Coverage
  • Camel :: Docs
  • Camel :: Endpoint DSL
  • Camel :: Endpoint DSL :: Support
  • Camel :: Integration Tests
  • Camel :: JBang :: Core
  • Camel :: JBang :: Integration tests
  • Camel :: JBang :: MCP
  • Camel :: JBang :: Main
  • Camel :: JBang :: Plugin :: Edit
  • Camel :: JBang :: Plugin :: Generate
  • Camel :: JBang :: Plugin :: Kubernetes
  • Camel :: JBang :: Plugin :: MCP
  • Camel :: JBang :: Plugin :: Route Parser
  • Camel :: JBang :: Plugin :: TUI
  • Camel :: JBang :: Plugin :: Testing
  • Camel :: JBang :: Plugin :: Validate
  • Camel :: JPA
  • Camel :: Kamelet Main
  • Camel :: Launcher
  • Camel :: Launcher :: Container
  • Camel :: YAML DSL
  • Camel :: YAML DSL :: Deserializers
  • Camel :: YAML DSL :: Maven Plugins
  • Camel :: YAML DSL :: Validator
  • Camel :: YAML DSL :: Validator Maven Plugin

⚙️ View full build and test results

@Croway

Croway commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Thanks for the fix, it is correct as is. A few suggestions before merging:

1. Consider field access instead of @Transient (KeyValueEntry.java)
The root cause is that the entity uses property access (annotations on getters) while the constructor, isExpired() and toString() read the fields directly. OpenJPA already warns about this on every run ("KeyValueEntry" uses property access, but its field "expiresAt" is accessed directly in method "isExpired"). Since the entity is @since 4.23 and unreleased, moving @Id/@Column/@Lob onto the fields (as Customer/VersionedItem/Address already do) makes any future helper getter safe by construction, removes the need for @Transient, and silences the OpenJPA warning. I verified JpaKeyValueRepositoryTest passes 23/23 under both providers with field access and no @Transient.

2. Map MessageProcessed too (KeyValueEntryHibernateMappingTest.java)
org.apache.camel.processor.idempotent.jpa.MessageProcessed is the other property-access @Entity shipped in the jar, is auto-discovered by Quarkus the same way, and no CI job ever maps it with Hibernate. Adding .addAnnotatedClass(MessageProcessed.class) (or mapping every shipped entity) closes the same gap for it.

3. persistence.xml comment is now stale (src/test/resources/META-INF/persistence.xml)
With hibernate-core unconditionally on the test classpath, Hibernate is the first PersistenceProvider and claims any unit without <provider>. The PR pins the four unpinned units, but the header comment still says the element is "optional if OpenJPA is the only JPA provider". Removing the keyvalueDb pin fails all 23 key-value tests with Unable to determine Dialect without JDBC metadata. Suggest rewording the comment to say <provider> is required because hibernate-core is on the classpath.

4. The javaagent comment states the wrong cause (pom.xml, openjpa profile)
"with -Dhibernate the agent jar is not copied" is not accurate: the jar is copied by the full profile independently of -Dhibernate (mvn -pl components/camel-jpa validate -Dhibernate produces target/openjpa-4.1.1.jar). The fork actually died because PCEnhancerAgent.premain threw NoClassDefFoundError: org/apache/xbean/asm9/ClassVisitor, since the OpenJPA transitives live only in the openjpa profile. Moving the agent into the profile is the right fix; suggest the comment (and commit body) say "the agent needs the OpenJPA classpath" instead.

Claude Code on behalf of Croway

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

see @Croway comments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants