quarkusio/quarkus · error · IllegalArgumentException
Methods that are annotated with JPA Listener annotations sho
Error message
Methods that are annotated with JPA Listener annotations should not be private. Offending method is '${declaringClass}#${method}' What it means
Hibernate ORM's CDI processor transforms JPA listener callback methods (e.g. @PrePersist, @PostLoad annotated methods on entity listeners) to work with Quarkus bean injection. A private callback method cannot be safely transformed because the client proxy would copy the method without the injected fields, so the build fails fast with an IllegalArgumentException naming the offending class#method.
Source
Thrown at extensions/hibernate-orm/deployment/src/main/java/io/quarkus/hibernate/orm/deployment/HibernateOrmCdiProcessor.java:325
MethodInfo method = target.asMethod();
if (Modifier.isPrivate(method.flags())) {
if (beanScope.getDotName().equals(BuiltinScope.SINGLETON.getName())) {
// we can safely transform in this case
producer.produce(new BytecodeTransformerBuildItem(method.declaringClass().name().toString(),
new BiFunction<>() {
@Override
public ClassVisitor apply(String cls, ClassVisitor clsVisitor) {
var classTransformer = new ClassTransformer(cls);
classTransformer.modifyMethod(MethodDescriptor.of(method))
.removeModifiers(Modifier.PRIVATE);
return classTransformer.applyTo(clsVisitor);
}
}));
} else {
// we can't transform because the client proxy does not know about the transformation and
// will therefore simply copy the private method which will then likely fail because it does
// not contain the injected fields
throw new IllegalArgumentException(
"Methods that are annotated with JPA Listener annotations should not be private. Offending method is '"
+ method.declaringClass().name() + "#" + method.name() + "'");
}
}
}
}
} else {
// we don't really know what to do here, just bail and CDI will figure it out
}
}
}
@BuildStep
void registerAnnotations(BuildProducer<AdditionalBeanBuildItem> additionalBeans,
BuildProducer<BeanDefiningAnnotationBuildItem> beanDefiningAnnotations) {
// add the @PersistenceUnit, @PersistenceUnitExtension, @JsonFormat and @XmlFormat classes
// otherwise they won't be registered as qualifiers
additionalBeans.produce(AdditionalBeanBuildItem.builder()View on GitHub (pinned to e1c734241f)
Solutions
- Change the offending method's visibility from private to at least package-private (recommended by the JPA spec) or public
- Remove bean injection from the listener so no transformation is needed, keeping in mind private listeners are still non-standard
- Refactor the callback logic into a CDI event observer instead of a JPA listener
Example fix
// before
@Entity
public class User {
@PrePersist
private void onCreate() { ... }
}
// after
@Entity
public class User {
@PrePersist
void onCreate() { ... }
} Defensive patterns
Strategy: validation
Validate before calling
// In your entity/listener classes, audit callbacks before build:
for (java.lang.reflect.Method m : MyListener.class.getDeclaredMethods()) {
if (java.lang.reflect.Modifier.isPrivate(m.getModifiers()) &&
java.util.Arrays.stream(m.getAnnotations()).anyMatch(a ->
a.annotationType().getName().startsWith("jakarta.persistence."))) {
throw new IllegalStateException("JPA callback must not be private: " + m);
}
} Prevention
- Never declare @PrePersist/@PostLoad/etc. methods private; use package-private or public
- Keep entity listeners free of field injection unless you know Quarkus can transform them
- Code-review entity lifecycle callbacks during legacy migrations
When it happens
Trigger: A build-step in transformBeans encounters an entity listener or entity method annotated with a JPA listener annotation (@PrePersist, @PostUpdate, @PreRemove, @PostPersist, @PostUpdate, @PostLoad) that is declared private and whose declaring class cannot be transformed (the client proxy would not know about the transformation).
Common situations: Defining lifecycle callback methods as private inside @Entity or @EntityListener classes; migrating a legacy Hibernate app where callbacks were made private for encapsulation.
Related errors
- An extension attempted to contribute the default persistence
- @PersistenceUnit annotations are not supported at the class
- This PersistenceProvider does not support createEntityManage
- The FastbootHibernateProvider PersistenceProvider can not su
- Hibernate ORM activated explicitly for persistence unit '<pu
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/e27b81df736d8bb5.
Report an issue: GitHub.