Kind regards.

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’re right – the code is a bit sloppy. Once I’ve sorted this
issue out, I’ll
try to suggest some improvements via a pull request.

Firstly, I made the specified changes. The example ran successfully, but
the relevant
part of the website stopped working. This is because ‘EventManager.java’
needs to
retrieve the data declared as transient in the XML.

So, I left the change to ‘pom.xml’ to continue using the tomee-maven-plugin
but removed
the @XmlTransient tags.

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.

One option is to use ‘LEFT JOIN FETCH’ 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.

Neither option worked, and the following errors were encountered:
The option with ‘LEFT JOIN FETCH’ gave me the error:
 org.apache.openejb.core.transaction.EjbTransactionUtil.handleSystemException
EjbTransactionUtil.handleSystemException: Cannot invoke
‘org.apache.openjpa.jdbc.meta.ClassMapping.getFieldMappings()’
because ‘cm’ is null
<openjpa-4.1.1-r9d2f5f8 nonfatal general error>
org.apache.openjpa.persistence.PersistenceException:
Cannot invoke
‘org.apache.openjpa.jdbc.meta.ClassMapping.getFieldMappings()’ because ‘cm’
is null

And the second option with @NamedEntityGraph gave me the following error:
org.apache.openejb.core.transaction.EjbTransactionUtil.handleSystemException
EjbTransactionUtil.handleSystemException: JPA 2.1
    java.lang.UnsupportedOperationException: JPA 2.1

So I tried changing the persistence provider in the tomee-maven-plugin from
OpenJPA to
Hibernate. This made both options run successfully.

Is there a problem with OpenJPA causing it not to work correctly?

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 ‘LEFT JOIN
FETCH’

You can also find the changes I made to the example on my GitHub:
https://github.com/Sxtormulo/jakartaee-examples/tree/main/tutorial/jaxrs/rsvp
.
In the ‘StatusBean.java’ class, within the ‘getAllCurrentEvents’ method, I
have commented
out the code to allow you to switch between the options and test both.

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?



El mar, 19 may 2026 a la(s) 12:45 p.m., Richard Zowalla ([email protected])
escribió:

> Hi,
>
> 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.
>
> Short answer: this is not a bug in your code or in the tutorial sources.
>
> 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.
>
> 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.
>
>
> ==============================================================================
> 1) Why /status/all returns 500 in the "no openjpa trace" log
>
> ==============================================================================
>
> The relevant lines in your no-trace log are:
>
> 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
>
> What is actually happening, step by step:
>
> 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.
>
> The same pattern bites again one level deeper: JAXB walks the Event
> fields (you have @XmlAccessorType(XmlAccessType.FIELD)) and encounters
> two LAZY relations:
>
> - @OneToMany(mappedBy = "event") List<Response> responses
> - @ManyToMany List<Person> invitees
>
> 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.
>
> 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.
>
> 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.
>
> 2) About the "GlassFish works, TomEE doesn't" difference
>
> 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.
>
> 3.) The fix
>
> Two minimal application-side changes, no provider workarounds:
>
> (a) In StatusBean.getAllCurrentEvents(), wrap the result in a plain
> ArrayList so the data is materialised inside the EJB transaction:
>
> this.allCurrentEvents = new ArrayList<>(
> em.createNamedQuery("rsvp.entity.Event.getAllUpcomingEvents",
> Event.class).getResultList());
>
> After this, CXF marshals a plain java.util.ArrayList instead of an
> OpenJPA DelegatingResultList. No more "context has been closed" on
> the outer list.
>
> (b) In Event.java, mark the two LAZY collections @XmlTransient:
>
> @OneToMany(mappedBy = "event")
> @XmlTransient
> private List<Response> responses;
>
> @ManyToMany
> @XmlTransient
> protected List<Person> invitees;
>
> 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.
>
> I have also added the tomee-maven-plugin to rsvp/pom.xml.
>
>             <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>
>
> That makes it trivial to reproduce / regression-test the example locally:
>
> mvn package
> mvn tomee:run
>
> and then GET http://localhost:8080/rsvp/webapi/status/all .
>
> Hope this helps - and good luck with the rest of the tutorial!
>
> Gruß
> Richard
>
>
>
>
> > Am 17.05.2026 um 03:53 schrieb Gabriel Alejandro Soto Rivera <
> [email protected]>:
> >
> > Warm regards to everyone, and thank you very much in advance.
> >
> > I’m just starting to learn Jakarta EE and Tomee, so I’m not sure if this
> is the right
> > place to ask for help with my problem. But I think it is, because it’s
> related to Tomee.
> >
> > I’m learning about Jakarta EE using the tutorial on their website:
> > Jakarta EE Tutorial I’ve just modified the POMs so that they don’t use
> GlassFish
> >  by default, but instead run on the Tomee server I’ve installed locally;
> and change the
> > persistence.xml to not use eclipse as persistence provider. And, so far,
> the examples
> > have been working correctly.
> >
> > 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.
> >
> > But I got stuck on the example in ‘Building RESTful Web Services with
> Jakarta REST’
> > 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
> > ‘org.apach.cxf.jaxrs.provider.JAXBElementProvider’.
> > However, when adding
> > <property name="openjpa.Log" value="DefaultLevel=TRACE, Runtime=TRACE,
> Tool=TRACE"/>
> > to persistence.xml as the log suggests to obtain more information, the
> application fails
> > to deploy. It throws errors relating to
> >  ‘jdk.internal.reflect.NativeMethodAccessorIpml.invoke’.
> > 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/rsvp
> .
> > 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’m new to this, I’m not sure if it’s a configuration error, an app
> error or a bug.
> > If it is a bug, I’ll open an issue on GitHub to report it.
> > Thank you very much in advance for your help.
>
>

Reply via email to