1

We are building a product, so from performance point of view I need some help. We are using complete Spring (MVC, JPA, Security etc..)

We have a requirement where say for a particular flow there can be 100 Business Rules getting executed at the same time. There can be n number of such flows and business rules.

These rules when executed actually fetch records from tables in database, these will contain few LAZILY INITIALIZED ENTITIES also.

I used Futures/Callables for multi threading purpose, but the problem is it fails to load LAZY variables. It gives Hibernate loading exception, probably some issue in TRANSACTIONAL not getting distributed in different threads.

Please let me know if there is any other way to approach?

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Ankur Singhal
  • 26,012
  • 16
  • 82
  • 116
  • 1
    multiple things. 1. post stack trace. 2. For lazy loading the session should be open. 3. transactions cant span across multiple threads as transactional context cant be propogated 4. use transaction isolation levels. 5. Leverage "read-only" transactions if possible – Aravind Yarram Nov 09 '12 at 16:34
  • See if this helps. http://stackoverflow.com/questions/13070157/transaction-in-jpa-using-multiple-threads/13088670#13088670 – Sashi Nov 09 '12 at 16:42
  • @Pangea I also thought that there is some issue with Transactions with threads. Can you please elaborate on this i low level design, any API which we can use. Since the worker method need to execute the rules in different threads, and each rule comprise of n number of tables and columns. – Ankur Singhal Nov 09 '12 at 16:42
  • 1
    @Sashi Even if we use JTA, it doesn't propogate the trans ctx across multiple threads as thread creation is not in containers control – Aravind Yarram Nov 09 '12 at 16:46
  • @Pangea You are right. May have to use container managed threads. If not the application has to deal with propagating the transaction context. – Sashi Nov 09 '12 at 16:59
  • @Sashi Even container managed threads might not work. It is app server dependent. You need to use the components that are part of the JEE Spec for this to consistently work across containers or re-work the design – Aravind Yarram Nov 09 '12 at 17:03
  • @Pangea At this point I'm not sure if the questioner wants a solution that is container independent. I agree that it's always good to be container independent. A few of the app servers do implement standard WorkManager API - http://docs.oracle.com/cd/E11035_01/wls100/commonj/commonj.html – Sashi Nov 09 '12 at 17:21
  • @Sashi I've used the workmanager api but unfortunately the threads are managed by container but the things like transaction, security contexts are not propogated – Aravind Yarram Nov 09 '12 at 17:28
  • @Pangea You are right, the API does not mandate propagation. It's up to the app servers whether they choose to do so. – Sashi Nov 09 '12 at 17:36

2 Answers2

2

if some Entity /Entity Collection is lazy fetched , and you are accessing it in another thread, you will face LazyInitialization exception, as lazy loaded entities can be accessed only within a transaction, and transaction wont span across, threads.

You can use DTO pattern, or if you are sharing an entity across threads, call its lazy initialized collections getter within the transaction so that they are fetched within transaction itself.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Subin Sebastian
  • 10,870
  • 3
  • 37
  • 42
  • Also to add.. after processing few things i want to distribute the work to a new thread which will run in background. (basically audit logging work), the main thread will return the view. Neither i want to fetch it eager in the entity, again performance issue. Now i have o pass my object to the new transaction, but it will have lazy objects which i do not want to load in main thread due to performance issue. So i try calling getters or hibernate.intialize(), it throws lazy exception, also if i try Merge(), and them i called hibernate.intialize it throws lazy excpetion. – Ankur Singhal Dec 24 '12 at 10:29
  • Also, passed object can be persisted or even not... is there a way i can store that object somewhere from one thread and then later retrive that same object and start doing calling my getters on that – Ankur Singhal Dec 24 '12 at 10:34
  • I have written a service where i get a transaction. Now after doing few task in service, i need to call run method. I have written below task. But it is not able to span the current transaction to another service. The next service starts it own new transaction instead of spanning the original. As a result my proxy objects could not be loaded in new transaction – Ankur Singhal Feb 26 '13 at 09:39
0

If you really need async processing then I suggest you use the Java EE specified way i.e. using JMS/MDB.

Anyways, since it seems like you want all the data to be loaded anyway for your processing. So Eager fetch all the required data and then submit the data for parallel processing. Or let each of the Tasks (Callables) fetch the data they require. Essentially, I am asking you to change your design so that the transactional boundaries doesn't cross multiple threads. Localize the boundaries within a single thread.

naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327