• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Rob Spoor
  • Tim Cooke
  • Junilu Lacar
Sheriffs:
  • Henry Wong
  • Liutauras Vilda
  • Jeanne Boyarsky
Saloon Keepers:
  • Jesse Silverman
  • Tim Holloway
  • Stephan van Hulst
  • Tim Moores
  • Carey Brown
Bartenders:
  • Al Hobbs
  • Mikalai Zaikin
  • Piet Souris

e: A JTA EntityManager cannot use getTransaction()

 
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi all,

I'm working on what I thought would be a really simple feature, but alas, I keep hitting this blocking bug:



Here is the method that I'm calling that results in the above exception:


For reference, too, here is my persistence.xml:

Other info:

I've combed through a lot of stackoverflow threads and jboss.org threads and tried quite a few things, but to no avail.  Fundamentally, it seems like with how the configuration is now, is that it's blocking my UPDATE query and not allowing it to run. How can I get the UPDATE query to run correctly?  I'd appreciate any feedback.  Thanks everyone!

 
Saloon Keeper
Posts: 24325
167
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
First and foremost, I have doubts about the @TransactionAttribute annotation. I've always used simply @Transactional. I AM assuming that you're using Spring Data, by the way.

Secondly, the EntityManager shouldn't have to invoke beginTransaction because - again, I'm assuming that this is Spring Data - the Spring Data framework makes the entire method transactional automatically.

In other words, I think you're trying to mix brute-force and framework-based design styles together and they don't like it.
 
Fred Moose
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:First and foremost, I have doubts about the @TransactionAttribute annotation. I've always used simply @Transactional. I AM assuming that you're using Spring Data, by the way.

Secondly, the EntityManager shouldn't have to invoke beginTransaction because - again, I'm assuming that this is Spring Data - the Spring Data framework makes the entire method transactional automatically.

In other words, I think you're trying to mix brute-force and framework-based design styles together and they don't like it.




I'm not actually using Spring, but Hibernate/JPA.  I've seen @Transactional mentioned a lot, but it's not relevant to my case it seems.

So with Spring out of the question, any idea how I can move forward and get past this error?  I tried a Native SQL query too, and got slammed with complaints about a missing "hibernate.cfg.xml".  

I really appreciate the help, and I'm glad an "old school" friendly forum like this still exists, you guys rock.  Thanks.
 
Tim Holloway
Saloon Keeper
Posts: 24325
167
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hibernate comes in two flavors: Legacy Hibernate (which I discourage), and Hibernate JPA, which is Hibernate's implementation of the Java Persistence Architecture.

I always use Hibernate JPA via Spring Data myself, so I don't know that much about how it would look bare-metal. Spring handles so much of the grunt work of JPA that I have no desire to find out, actually.

But I'm FAIRLY sure that Hibernate doesn't handle any sort of transaction-related annotations, nor does the underlying JPA standard. I'm fairly certain that Spring Data or some similar framework would have to handle that.

On the other hand, @TransactionAttribute annotation is part of EJB3, and JPA is a subset of EJB3. And while Hibernate JPA does serve as the basis for EJBs in some of the full-stack JEE containers (like Wildfly), at that point, you're no longer "Hibernate", not solely "JPA".

EJBs deal with transactions as part of their deployment definitions, and the EJB container manages them. So here again, the EntityManager should not begin transactions on its own. And unless you are using EJBs, @TransactionAttribute won't work. It does not apply to non-EJB JPA.
 
Fred Moose
Greenhorn
Posts: 21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes, I believe I'm using Hibernate JPA.

I guess the question is, given my configuration, what is the best way to perform an UPDATE query?  The framework seems to make it really complicated, and I'm not quite sure why.
 
Tim Holloway
Saloon Keeper
Posts: 24325
167
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think your biggest problem is that you're getting your information from several sources and not all of them cover the same use of Hibernate. So the logic clashes.

First, have you tried removing the transaction annotaion? As I said, it's useless, but Hibernate may be trying to hook it to a non-existent EJB container with unpredictable results.

I'm also not sure you should be closing the EntityManager. But I recommend wrapping the whole update process in a try-with-resources. It's cleaner than doing things the old-fahioned hard way. You should, incidentally rollback transactions if they cannot be committed. Otherwise the database context ends up in limbo.

One of the biggest problems you're going to have is that almost EVERYONE uses JPA either with Spring or in a JEE EJB3 container. Pure Hibernate JPA just isn't that popular. So less places to look on the Internet and less experts available to help you.

If you're building your project with a system like Maven or Gradle, it's relatively easy to drop Spring into it. The Spring Foundation claims you can get an application up and running from scratch in 15 minutes. Yeah, right. But it's not actually much worse than that and you can be assured that there are plenty of people in our Object Relational Forum who can help there. Some useful things to know is that their demo project uses an H2 database, which keeps stuff in memory, but switching from H2 to Hibernate JPA should be simple. I switched from Apache OpenJPA to Hibernate JPA once in 15 minutes myself. The other thing to note is that it's building a Spring Boot app, which seems to be the popular way to go these days. If you're looking to work with a traditional Java command-line Application, the configuration changes a bit (should actually be simpler) and if you're looking for a deployable webapp, people move WARs from Spring Boot to stand-alone all the time.

Anyway, if you'd like to try that option out: https://spring.io/guides/gs/accessing-data-jpa/ and Baeldun has a similar tutorial. So do several others.

One thing to know about Spring is that despite its fearsome reputation, Spring's core is very small and simple. It basically just defines beans, and provides a factory to build beans and inject properties (including other beans) into them. You can then leverage this by employing one or more Spring modules, and there are a lot of modules, covering different types of database persistence (including raw JDBC, JPA, graph databases, NoSQL, and so forth) as well as many other topics such as email, directory services (like LDAP), scheduling, batch processing and much much more and they're all optional so you can create a monster or a mouse, as your needs require.
 
Marshal
Posts: 22457
121
Eclipse IDE Spring VI Editor Chrome Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
@TransactionAttribute is part of JTA, which is a subset of JEE / JakartaEE. @Transactional comes in two flavours - one for Spring and one for CDI.

Since you're using @TransactionAttribute, I'm assuming this is a JEE / JakartaEE application. You've probably injected the entity manager as well, as you should.
In JEE / JakartaEE, there are two ways to handle transactions - container managed and bean managed. The default is container managed, and you need to explicitly annotate your bean class with @TransactionManagement(TransactionManagementType.BEAN) to activate bean managed transaction transactions.

If you use bean managed transactions, any @TransactionAttribute annotation is ignored (or it may cause an exception to be thrown, I'm not 100% sure). You handle your transactions not through the entity manager, but by injecting (with @Resource) a UserTransaction instance. You use this to start, commit, rollback, etc.

If you use container managed transactions, you let the container handle the transactions. You annotate your class or method with @TransactionAttribute, with the default being @TransactionAttribute(TransactionAttributeType.REQUIRED). The container wraps your method call in a transaction - a new one or an existing one, depending on the annotation and any already active transaction. You don't start the transaction yourself, the container does that for you. You don't commit the transaction yourself, the container does that for you when the methods ends successfully or with a non-system exception. You can rollback the transaction yourself by injecting an EJBContext or SessionContext and calling setRollbackOnly on it, or by throwing a system exception. In both cases, a system exception is a runtime exception that is not marked as application exception using either @ApplicationException or in ejb-jar.xml. @ApplicationException can also indicate that the exception will trigger a rollback; you can use this for checked exceptions as well.


In your case your code indicates that you want to have a transaction for each element separately. That's not going to work with container managed transactions - the entire method uses the same transaction. The only ways to get a smaller part to run in its own transaction is to:
  • Put it in a different bean, and the bean or method is annotated with @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW).
  • Like the previous one but in the same bean. However, you need to call the bean through SessionContext.getBusinessObject, otherwise it's just a normal POJO method call and all annotations are skipped.
  • Use bean managed transactions with UserTransaction.
  •  
    You showed up just in time for the waffles! And this tiny ad:
    Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
    https://coderanch.com/wiki/718759/books/Building-World-Backyard-Paul-Wheaton
    reply
      Bookmark Topic Watch Topic
    • New Topic