Re: Help - Error trying to run Jakarta Rest RSVP example from jakarta ee tutorial.
Richard Zowalla <[email protected]> Mon, 8 Jun 2026 07:43:52 +0200
| Newsgroups | gmane.comp.java.openejb.user |
|---|---|
| Message-ID | <[email protected]> |
OpenJPA does not implement Entity Graphs and is far away from being JPA = 3.1 compatible in its current version. It might get JPA 3.2 compliance with the next release (there is an open = PR for it). Gru=C3=9F Richard > Am 08.06.2026 um 07:39 schrieb Gabriel Alejandro Soto Rivera = <[email protected]>: >=20 > Best regards to all. > I continued working on the example and managed to get it working using > one of the two > methods. This was using Named Queries, whereas using NamedEntityGraph > still gives me > errors. >=20 >=20 > =C2=ABNamed Queries=C2=BB >=20 > To make it work with Named Queries, I created two queries in the form > =E2=80=98SELECT DISTINCT ... JOIN FETCH ...=E2=80=99. The first query = joined one of the entity=E2=80=99s > one-to-many relationships, and the other joined the next one-to-many > relationship. Both > results were stored in the same list. > Furthermore, I had to configure the entity enhancement at build time. > This is because > when I tried to use enhancement at deployment time with the property > =E2=80=98openejb.jpa.deploy-time-enhancement=3Dtrue=E2=80=99, I = received the following error when > attempting to enhance the entities: > WARNING [main] > org.apache.openejb.assembler.classic.DeployTimeEnhancer.enhance cannot > enhance entities at deployment time > java.lang.reflect.InvocationTargetException ... > Caused by: java.lang.IllegalArgumentException ... > And the entity causing the error has changed as I=E2=80=99ve been = working on > the example. > What confuses me is that I get an error when trying to enhance the > entity at deployment > time, but not at build time. What=E2=80=99s more, if I don=E2=80=99t = enhance the > entity at build time, > I get the previous error: > = org.apache.openejb.core.transaction.EjbTransactionUtil.handleSystemExcepti= on > EjbTransactionUtil.handleSystemException: > Cannot invoke > =E2=80=98org.apache.openjpa.jdbc.meta.ClassMapping.getFieldMappings()=E2= =80=99 because > =E2=80=98cm=E2=80=99 is null > when trying to test the example. >=20 > I have included the log from the working example. Here, you can also > see the error that > occurs when attempting to enhance the entities at deployment time > because the property > =E2=80=98openejb.jpa.deploy-time-enhancement=3Dtrue=E2=80=99 is = enabled. > The log is called rsvp-working-openjpa-join-buildEnhancement >=20 >=20 > =C2=ABNamedEntityGraph=C2=BB >=20 > When I try to use NamedEntityGraph, I keep getting the same error. It > says that the > operation is not supported by JPA 2.1. This is odd, as according to > the OpenJPA website, > version 4.1.1 included in Tomee 10 is a JPA 3.1 implementation. The > error is as follows: > = org.apache.openejb.core.transaction.EjbTransactionUtil.handleSystemExcepti= on > Ejb> > java.lang.UnsupportedOperationException: JPA 2.1 > at = org.apache.openjpa.persistence.EntityManagerImpl.getEntityGraph(EntityMana= gerImpl.java:2126) > ... > I have included the rest of the log in the file > rsvp-error-openjpa-entity-graph-enh-ann >=20 >=20 > You can find the updated example in the fork I created of the original > project on my GitHub: > = https://github.com/Sxtormulo/jakartaee-examples/tree/main/tutorial/jaxrs/r= svp. >=20 > The example currently works correctly with named queries, as the POM > uses tomee-maven-plugin > and the OpenJPA plugin to enhance entities at build time. > However, if you wish to reproduce the error with NamedEntityGraph, you > can replace the > file /src/main/java/jakarta/tutorial/rsvp/ejb/StatusBean.java with the > StatusBean.java > file that I will include in this email. >=20 > Thank you all for your attention. And many thanks to Richard for his > help, which enabled > me to work through the example to this point. > Best regards, Gabriel. >=20 >=20 > El dom, 24 may 2026 a la(s) 1:08=E2=80=AFa.m., Gabriel Alejandro Soto = Rivera > ([email protected]) escribi=C3=B3: >>=20 >> Kind regards. >>=20 >> Thank you very much for your detailed reply. Your explanation of the = problem helped me >> start looking in the right places. To add, having looked at the = example more closely, I >> realise you=E2=80=99re right =E2=80=93 the code is a bit sloppy. Once = I=E2=80=99ve sorted this issue out, I=E2=80=99ll >> try to suggest some improvements via a pull request. >>=20 >> Firstly, I made the specified changes. The example ran successfully, = but the relevant >> part of the website stopped working. This is because = =E2=80=98EventManager.java=E2=80=99 needs to >> retrieve the data declared as transient in the XML. >>=20 >> So, I left the change to =E2=80=98pom.xml=E2=80=99 to continue using = the tomee-maven-plugin but removed >> the @XmlTransient tags. >>=20 >> Whilst searching for more information with the cause of the problem = in mind, I came across >> this blog https://thorben-janssen.com/lazyinitializationexception/ = which helped me find >> two solutions to the problem. >>=20 >> One option is to use =E2=80=98LEFT JOIN FETCH=E2=80=99 to tell JPA = that I need to load not only the >> entity, but also the entities related to it. The other is to use = @NamedEntityGraph to >> specify the relationships with their properties and likewise load the = dependent entities. >>=20 >> Neither option worked, and the following errors were encountered: >> The option with =E2=80=98LEFT JOIN FETCH=E2=80=99 gave me the error: >> = org.apache.openejb.core.transaction.EjbTransactionUtil.handleSystemExcepti= on EjbTransactionUtil.handleSystemException: Cannot invoke = =E2=80=98org.apache.openjpa.jdbc.meta.ClassMapping.getFieldMappings()=E2=80= =99 >> because =E2=80=98cm=E2=80=99 is null >> <openjpa-4.1.1-r9d2f5f8 nonfatal general error> = org.apache.openjpa.persistence.PersistenceException: >> Cannot invoke = =E2=80=98org.apache.openjpa.jdbc.meta.ClassMapping.getFieldMappings()=E2=80= =99 because =E2=80=98cm=E2=80=99 is null >>=20 >> And the second option with @NamedEntityGraph gave me the following = error: >> = org.apache.openejb.core.transaction.EjbTransactionUtil.handleSystemExcepti= on EjbTransactionUtil.handleSystemException: JPA 2.1 >> java.lang.UnsupportedOperationException: JPA 2.1 >>=20 >> So I tried changing the persistence provider in the = tomee-maven-plugin from OpenJPA to >> Hibernate. This made both options run successfully. >>=20 >> Is there a problem with OpenJPA causing it not to work correctly? >>=20 >> As before, I have attached the new errors encountered, which are: >> * rsvp-error-with-openjpa-entity-graph, relating to running the = example using >> @NamedEntityGraph. >> * rsvp-error-with-openjpa-join-fetch: relating to the use of =E2=80=98L= EFT JOIN FETCH=E2=80=99 >>=20 >> You can also find the changes I made to the example on my GitHub: >> = https://github.com/Sxtormulo/jakartaee-examples/tree/main/tutorial/jaxrs/r= svp. >> In the =E2=80=98StatusBean.java=E2=80=99 class, within the = =E2=80=98getAllCurrentEvents=E2=80=99 method, I have commented >> out the code to allow you to switch between the options and test = both. >>=20 >> Thank you very much for your help. Finally, I have a question = unrelated to the problem: >> what is the difference between the Tomee Maven plugin and the Tomee = Embedded Maven plugin? >>=20 >>=20 >>=20 >> El mar, 19 may 2026 a la(s) 12:45=E2=80=AFp.m., Richard Zowalla = ([email protected]) escribi=C3=B3: >>>=20 >>> Hi, >>>=20 >>> thanks for the detailed report and for taking the time to attach = both log >>> variants, that made it possible to reproduce locally on the first = try. >>>=20 >>> Short answer: this is not a bug in your code or in the tutorial = sources. >>>=20 >>> You have hit a known interaction between OpenJPA's lazy-load = behaviour and >>> JAX-RS (CXF) marshalling that runs *after* the EJB transaction has >>> finished. GlassFish + EclipseLink masks the same code's problem = because >>> EclipseLink is more permissive about touching = detached/closed-context >>> proxies. >>>=20 >>> I reproduced this with apache-tomee-plus-10.1.5 on Temurin 17 using = the >>> exact module you linked. Below is a complete breakdown plus a patch = you >>> can apply to your fork. The diff is also attached as rsvp-fix.patch. >>>=20 >>> = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D >>> 1) Why /status/all returns 500 in the "no openjpa trace" log >>> = =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D >>>=20 >>> The relevant lines in your no-trace log are: >>>=20 >>> WARNING ... = org.apache.cxf.jaxrs.provider.JAXBElementProvider.writeTo >>> <openjpa-4.1.1 fatal user error> >>> org.apache.openjpa.util.InvalidStateException: The context has been >>> closed. ... >>> SEVERE ... Problem with writing the data, class >>> org.apache.openjpa.kernel.DelegatingResultList, ContentType: = application/xml >>>=20 >>> What is actually happening, step by step: >>>=20 >>> a) StatusBean#getAllCurrentEvents() executes >>> em.createNamedQuery(...).getResultList() >>> OpenJPA returns an *org.apache.openjpa.kernel.DelegatingResultList*. >>> This is a lazy wrapper, iit does not fully materialise the rows. >>> b) The @Stateless method returns. The container-managed JTA = transaction >>> commits, and the JPA persistence context is closed. >>> c) Only *now* does CXF's JAXBElementProvider start iterating the = list to >>> marshal it to XML. While iterating, the DelegatingResultList tries = to >>> pull the next row from the underlying broker, finds the broker is >>> closed, and throws InvalidStateException("The context has been >>> closed"). CXF maps that to HTTP 500. >>>=20 >>> The same pattern bites again one level deeper: JAXB walks the Event >>> fields (you have @XmlAccessorType(XmlAccessType.FIELD)) and = encounters >>> two LAZY relations: >>>=20 >>> - @OneToMany(mappedBy =3D "event") List<Response> responses >>> - @ManyToMany List<Person> invitees >>>=20 >>> By spec these default to FetchType.LAZY. They are still unresolved = when the persistence context closes, >>> so attempting to read them during marshalling fails for exactly the = same >>> reason. >>>=20 >>> To answer the question you raised: yes, @ManyToOne defaults to >>> FetchType.EAGER, and OpenJPA does honour that. I verified >>> it by leaving Event.owner without @XmlTransient in the fix below; = owner >>> serialises correctly into the response payload, because it was = already >>> fully loaded inside the EJB transaction. So the eagerness behaviour = you >>> expect is working; only the LAZY-by-default collections needed >>> intervention. >>>=20 >>> The other endpoint, GET /status/{eventId}, works because it returns = a >>> single Event fetched with em.find(...), whose scalar fields and = EAGER >>> relations (owner) are fully loaded synchronously. Same reason >>> ConfigBean and ResponseBean behave; they do not return lazy result >>> sets. >>>=20 >>> 2) About the "GlassFish works, TomEE doesn't" difference >>>=20 >>> The tutorial code is sloppy (IMHO) in a way that EclipseLink = tolerates and >>> OpenJPA does not. The JPA spec leaves "what happens if you touch a = lazy >>> proxy after the persistence context is closed" largely >>> implementation-defined; providers are free to throw. EclipseLink >>> typically lets you read whatever state was already loaded and = returns >>> nulls/empties for the rest; OpenJPA is strict and raises >>> InvalidStateException. Both behaviours are within spec; this is = *not* >>> "OpenJPA not being JPA-compliant". The tutorial just happens to be >>> written in a way that exercises one of the edges where providers >>> diverge. The right fix is at the application level (see below), not = in >>> the provider. >>>=20 >>> 3.) The fix >>>=20 >>> Two minimal application-side changes, no provider workarounds: >>>=20 >>> (a) In StatusBean.getAllCurrentEvents(), wrap the result in a plain >>> ArrayList so the data is materialised inside the EJB transaction: >>>=20 >>> this.allCurrentEvents =3D new ArrayList<>( >>> em.createNamedQuery("rsvp.entity.Event.getAllUpcomingEvents", >>> Event.class).getResultList()); >>>=20 >>> After this, CXF marshals a plain java.util.ArrayList instead of an >>> OpenJPA DelegatingResultList. No more "context has been closed" on >>> the outer list. >>>=20 >>> (b) In Event.java, mark the two LAZY collections @XmlTransient: >>>=20 >>> @OneToMany(mappedBy =3D "event") >>> @XmlTransient >>> private List<Response> responses; >>>=20 >>> @ManyToMany >>> @XmlTransient >>> protected List<Person> invitees; >>>=20 >>> These collections are not part of what /status returns >>> anyway (the endpoint reports events, not invitee/response graphs), >>> and excluding them from XML/JSON serialisation means JAXB never >>> tries to walk a LAZY proxy after the persistence context is closed. >>> Event.owner stays as-is, because @ManyToOne is EAGER by default and >>> is already loaded by the time the EJB returns. >>>=20 >>> I have also added the tomee-maven-plugin to rsvp/pom.xml. >>>=20 >>> <plugin> >>> <groupId>org.apache.tomee.maven</groupId> >>> <artifactId>tomee-maven-plugin</artifactId> >>> <version>10.1.5</version> >>> <configuration> >>> <tomeeVersion>10.1.5</tomeeVersion> >>> <tomeeClassifier>plus</tomeeClassifier> >>> <context>rsvp</context> >>> </configuration> >>> </plugin> >>>=20 >>> That makes it trivial to reproduce / regression-test the example = locally: >>>=20 >>> mvn package >>> mvn tomee:run >>>=20 >>> and then GET http://localhost:8080/rsvp/webapi/status/all . >>>=20 >>> Hope this helps - and good luck with the rest of the tutorial! >>>=20 >>> Gru=C3=9F >>> Richard >>>=20 >>>=20 >>>=20 >>>=20 >>>> Am 17.05.2026 um 03:53 schrieb Gabriel Alejandro Soto Rivera = <[email protected]>: >>>>=20 >>>> Warm regards to everyone, and thank you very much in advance. >>>>=20 >>>> I=E2=80=99m just starting to learn Jakarta EE and Tomee, so I=E2=80=99= m not sure if this is the right >>>> place to ask for help with my problem. But I think it is, because = it=E2=80=99s related to Tomee. >>>>=20 >>>> I=E2=80=99m learning about Jakarta EE using the tutorial on their = website: >>>> Jakarta EE Tutorial I=E2=80=99ve just modified the POMs so that = they don=E2=80=99t use GlassFish >>>> by default, but instead run on the Tomee server I=E2=80=99ve = installed locally; and change the >>>> persistence.xml to not use eclipse as persistence provider. And, so = far, the examples >>>> have been working correctly. >>>>=20 >>>> I am using Tomee 10.0.5 with their default configurations, only and = a user in tomcat-users >>>> to access to the html manager. Then, to test if is the example that = is not working or is Tomee >>>> I installed GlassFish 7 and the example works well. But I want to = make it work with Tomee. >>>>=20 >>>> But I got stuck on the example in =E2=80=98Building RESTful Web = Services with Jakarta REST=E2=80=99 >>>> The rsvp Example Application. Making some testing I discover that = the endpoints of >>>> ResponseBean.java works well; and ConfigBean.java make their job. = But the problem >>>> comes from executing the endpoints of StatusBean.java >>>> However, when trying to debug, I get confusing logs depending on = the configuration. >>>> With the default configuration, the log indicates issues related to >>>> =E2=80=98org.apach.cxf.jaxrs.provider.JAXBElementProvider=E2=80=99. >>>> However, when adding >>>> <property name=3D"openjpa.Log" value=3D"DefaultLevel=3DTRACE, = Runtime=3DTRACE, Tool=3DTRACE"/> >>>> to persistence.xml as the log suggests to obtain more information, = the application fails >>>> to deploy. It throws errors relating to >>>> =E2=80=98jdk.internal.reflect.NativeMethodAccessorIpml.invoke=E2=80=99= . >>>> I have the tutorial code with the changes that i make to work with = Tomee in my github: >>>> = https://github.com/Sxtormulo/jakartaee-examples/tree/main/tutorial/jaxrs/r= svp. >>>> These are the errors I get when I try to run the example with and = without the openjpa.Log Trace >>>> property in persistence.xml. >>>> As I=E2=80=99m new to this, I=E2=80=99m not sure if it=E2=80=99s a = configuration error, an app error or a bug. >>>> If it is a bug, I=E2=80=99ll open an issue on GitHub to report it. >>>> Thank you very much in advance for your help. >>>=20 > <StatusBean.java>