JPAContainer - should i use it?

Hi,

So far most issues are working very well. But i am fighting with containment references related to the SQLContainer. I am not sure whether it was a good decision to use it. Since business applications heavily use complex data models with different kind of references, maybe the JPAContainer can meet my objectives a better way.

Eg my current problem:
I am using a master detail block to visualize master data. For instance the customer records.

A table shows all the records. If a record becomes selected, it will be shown in the detail editor and can be changed there.

The customer item has a lot of attributes, references and four ZERO_TO_MANY-Containment references like the InvoiceAddress. Containment reference means aggregation, which describes the lifecycle of the reference target. The InvoiceAddress will be deleted if the customer was deleted.
The ZERO_TO_MANY-Containment references are also visualized as master detail blocks in the detail editor.

So i have to deal with containment trees. If a customer was selected in the table, i am creating a copy of the bean (which is related with the RowItem), put the copy to the editor. Then changes can be made to the mutable copy. If the editor changes are accepted, the changes will be applied to the original container and all changed containers have to be commited.
To do exactly what i described above, i have to write my own entity and entity manager layer which builds an abstraction above the different containers inside the containment tree. Additionally i have forked the SQLContainer and have created a RVContainer since the SQLContainer does not offer functions that are required.

Now i am not really happy with the solution since i a have forked the SQLContainer and there are some issues that have to be done.

What do you think,
should i use the JPAContainer? Would it solve my problems? Does it support ONE_TO_ONE-, ONE_TO_MANY- Containment references out of the box?

Thanks,
Florian Pirchner

Hi,

any suggestions are highly welcome.

Thanks, Florian

I guess, the question above can be answered with: Yes, we should use the JPAContainer!

During the last weeks Matti Tahvonen and Jonatan Kronqvist did a really good job implementing JPAContainer 2.0.
Based on the source code of the svn repository i was running some tests against it and the performance is really amazing. Since redVoodo deals with business applications and business data we have to be aware of large tables containing a lot of records.

So i have created a table called SimplePerson and added
4.500.000
records to it. The JPAContainer based on that table was the input datasource of an UI-table.
For normal, nobody will do so, but i thought it might be interesting whether the JPAContainer faces the same problems as redVoodods RVContainer (forked SQLContainer with some special enhancements). But no, scrolling the table from
row#1
to
row#4.000.000
took only about
2 seconds
. An amazing response time for such a big table.

Than i tested the methods getIdByIndex and indexOfId.


getIdByIndex
: To lookup the record with index
3.000.000
took about
1270ms
for first access and
1ms
for second. → Pretty good results!

indexOfId
: Does not seem to finish in a usable time.

Conclusion:
I guess the JPAContainer is a great component to implement business applications based on vaadin. The performance is great and it seems to be ready for real world scenarios!
Although programmers have to be aware about one issue. The indexOfId-method has to be avoided at all. So you have to be careful specifying your configuration for AbstractSelects (ui-components). But if you run your tests against tables with a lot of records, such settings will be detected really fast!

Now redVoodo.org continues the integration of JPAContainer as it’s main container. And i am looking forward to nice business applications using the JPAContainer.

Thanks a lot to Matti and Jonatan,
Florian Pirchner

Hello Florian, I have read and enjoyed your post, I was encouraged by it and I tried to insert into my project JPAContainer 2.0.
Since my application has many readings and a few updates I have used the provider Cached.

Just as the use case you described my application in the table shows some of the information of the business object and then editing the mask show all details, including references ZERO_TO_MANY.

The problem is that with the Cached provider when I open the form I get an LazyLoadingException,
using a Not-Cached provider everything works correctly, but obviously the performance scrolling the table are very low.

For now I used a workaround by setting:

  • provider.setCacheEnabled(false);
  • Then I open the form after editing
  • and re-setting provider.setCacheEnabled(true);
    but I’m not happy with this workaround.

Have you had the same problem? how did you solved?
Thanks for your help

Hi Pietro,

due to customer requests i did not find the time to migrate the opensource project to JPAContainer yet.
But we (me and Hans-Georg) started to write the UI components for it, but without having any dependencies to the JPAContainer, nor using it right now.

But it did some tests. They have been based on the examples of the JPAContainer and showed incredible good results!!! So i am looking forward to find the required time to migrate to the JPAContainer soon.

I am really sorry. But currently i do not have the required experience in optimizing the JPAContainer. All my current knowledge is based on the tests done. So i can not give you any hint about it…

Sorry again…
Best, Florian

Thanks, I appreciate your kindness anyway.
If you were to get news about this issue, please let me know, as will I

no one else knows the answer to the question asked?

Regards

Pietro, I have three good solutions for you:

  1. use EclipseLink instead of Hibernate
  2. use EclipseLink instead of Hibernate
  3. use EclipseLink instead of Hibernate

:slight_smile:

If you really need to go on with Hibernate, have you noticed LazyLoadingDelegate helper in JPAContainer 2 ? HibernateLazyLoadingDelegate tries to workaround with most common Hibernate lazy load issues automatically.

cheers,
matti

Thanks for your reply.
Well, option 1,2 and even 3 require to me to code changes ;-), I’ll try using HibernateLazyLoadingDelegate
otherwise I’ll try to cange provider.

I’ll keep you and the post update.

I tried with LazyLoadingDelegate,
It works but same time I have an exception on the stacktrace:


2012-04-23 18:30:34,992 [tomcat-http--24]
 ERROR org.hibernate.LazyInitializationException - failed to lazily initialize a collection of role: it.demanio.agenda.domain.Attivita.documenti, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: it.mydomain.myproject.domain.MyObject.myCollection, no session or session was closed
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:368)
	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
	at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:186)
	at com.vaadin.addon.jpacontainer.JPAContainerItem$ItemProperty.ensurePropertyLoaded(JPAContainerItem.java:238)
	at com.vaadin.addon.jpacontainer.JPAContainerItem$ItemProperty.getRealValue(JPAContainerItem.java:171)
	at com.vaadin.addon.jpacontainer.JPAContainerItem$ItemProperty.cacheRealValue(JPAContainerItem.java:99)
	at com.vaadin.addon.jpacontainer.JPAContainerItem$ItemProperty.<init>(JPAContainerItem.java:76)
	at com.vaadin.addon.jpacontainer.JPAContainerItem.getItemProperty(JPAContainerItem.java:429)
	at com.vaadin.addon.jpacontainer.JPAContainerItem.getItemProperty(JPAContainerItem.java:39)
	at com.vaadin.ui.Form.setItemDataSource(Form.java:765)
	at com.vaadin.addon.beanvalidation.BeanValidationForm.setItemDataSource(BeanValidationForm.java:103)
	at it.demanio.agenda.admin.AttivitaForm.createAllegatiComponent(AttivitaForm.java:220)
	at it.demanio.agenda.admin.AttivitaForm.init(AttivitaForm.java:77)
	at it.demanio.agenda.admin.AttivitaForm.<init>(AttivitaForm.java:53)
	at it.demanio.agenda.admin.AttivitaList$3.buttonClick(AttivitaList.java:109)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:616)
	at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:512)
	at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:164)
	at com.vaadin.ui.AbstractComponent.fireEvent(AbstractComponent.java:1219)
	at com.vaadin.ui.Button.fireClick(Button.java:550)
	at com.vaadin.ui.Button.changeVariables(Button.java:217)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.changeVariables(AbstractCommunicationManager.java:1445)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariableBurst(AbstractCommunicationManager.java:1393)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1312)
	at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:763)
	at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:296)
	at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:501)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:311)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:101)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
	at org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter.doFilter(AbstractPreAuthenticatedProcessingFilter.java:88)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:173)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:147)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.invoke(HttpRequestOperationCollectionValve.java:84)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:279)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:679)

Anyone knows why?

Unfortunately I know the error but I have not found the solution also :frowning: