-
1. Re: Transactional propagation types
luxspes Aug 25, 2009 5:56 PM (in response to asookazian)So... let see:
Option 1) Move your method to another class without @Transactional at class level and keep it as a WAR (I might take you around... 10 minutes?)
Option 2) Reorganize your project in to an sluggish and cumbersome EAR (It may take you a whole day, and that without the extra productivity loss your are going to have to live with now that your project is sluggishly slow)
It is such a hard choice ;-)
-
2. Re: Transactional propagation types
israel.bgf Aug 25, 2009 7:01 PM (in response to asookazian)Strange, the @Transactional(TransactionPropagationType.NEVER) should override the @Transactional put in the class. Anyway, aren't you using seam-global-transactions? As far I know the @Transactional annotations are ignored when using global transactions.
-
3. Re: Transactional propagation types
asookazian Aug 25, 2009 8:41 PM (in response to asookazian)The context of this use case is as follows. A LRC is begun when the user navigates to the page in question:
<page view-id="/EquipmentProcessingView.xhtml"> <begin-conversation join="true" flush-mode="manual"/> .... </page>
This may eventually change, I'm just experimenting with starting a LRC immediately when user first navigates to the page.
There is an @Begin(join=true) on one of the @Factory methods which probably is not necessary if the LRC is configured in pages.xml.
@Begin(join=true) public void getCustomerInformation(){...}
There is @Transactional at the class level so that means by default all business methods require a tx. I can probably remove this and annotate each business method accordingly.
But really what's happening is that a tx is already running when the business method annotated with @Transactional(TransactionPropagationType.NEVER) is executed. This would be illegal as per JSR220 as well.
I'm not moving back to EJB yet. I got the Seam interceptor working for my ProfilingInterceptor which was cool, now I know how long my business methods take to execute (again!) thx.
-
4. Re: Transactional propagation types
asookazian Aug 25, 2009 8:42 PM (in response to asookazian)
Israel Fonseca wrote on Aug 25, 2009 19:01:
Strange, the @Transactional(TransactionPropagationType.NEVER) should override the @Transactional put in the class. Anyway, aren't you using seam-global-transactions? As far I know the @Transactional annotations are ignored when using global transactions.Sorry, being lazy. How would I know if I'm using Seam global tx's or not? I think you have to configure manually to turn them off, no?
-
5. Re: Transactional propagation types
israel.bgf Aug 25, 2009 8:55 PM (in response to asookazian)"Note, however, that the @Transactional annotation is irrele-
vant during a JSF request when using Seam global transactions.
"
That's from Seam in Action. And to deactivate the global-transactions you have to put this in components.xml:
<core:init transaction-management-enabled="false"/>
It's true by default so that's your case. But that's make the things more strange, because if the @Transactional should be ignored, why is it throwing an exception?
Strange... -
6. Re: Transactional propagation types
asookazian Aug 25, 2009 11:50 PM (in response to asookazian)This is what I have in components.xml:
<core:init debug="@debug@" jndi-pattern="@jndiPattern@"/>
Seam wraps a built-in method interceptor around components that contain
the @Transactional annotation, which interprets this annotation and drives the
transaction accordingly. Note, however, that the @Transactional annotation is irrelevant
during a JSF request when using Seam global transactions.I'm wondering if the underlined above is a typo in the book. It doesn't seem to be true in my case definitely. And I believe DAllen goes on to state that turning off global tx's is not a good idea either.
-
7. Re: Transactional propagation types
swd847 Aug 26, 2009 1:05 PM (in response to asookazian)I think what he meant was that @Transactional is irrelevant for the most common case (i.e. when you want to mark a method as running inside a transaction).
NEVER and global transactions are not compatible, global transaction means there is always a transaction, which means that methods marked with NEVER will always throw an exception.
This is why I use ejb3.
-
8. Re: Transactional propagation types
israel.bgf Aug 26, 2009 2:22 PM (in response to asookazian)I really like Seam, but i cant tell you: I always disable the global transactions. I don't like the fact to do a redirect just to show an error message, I want an message triggered by ajax, and global transactions don't give this control. And i'm still reluctant about the conversation context when a lot of data is involved, tons of results handling in the persistence context looks a little dangerous when a lot of users are using the system at the same time, i'm really well with the
transactional persistence context
, it's not difficult do handle LIEs anyway. -
9. Re: Transactional propagation types
luxspes Aug 26, 2009 5:50 PM (in response to asookazian)
Stuart Douglas wrote on Aug 26, 2009 13:05:
NEVER and global transactions are not compatible, global transaction means there is always a transaction, which means that methods marked with NEVER will always throw an exception.
This is why I use ejb3.So, the annotation NEVER means :
You will NEVER be able to execute this method if there is a transaction
While NOT_SUPPORTED means:
While you run this method, if there is a running transaction, I'll susppend it, and resume it after the method has finished
. (Not a very intuitive name)More info here.
Now, what I really would like to know, is why do you ever want to suspend a transaction? and more particularly: why (exactly) do you want to suspend a transaction? What concrete feature or behavior in your system makes you need that?.
(I have built several systems I still have not needed to do so, so I am extremely curious on why would you want to do it)
-
10. Re: Transactional propagation types
luxspes Aug 26, 2009 6:07 PM (in response to asookazian)According to EJB docs , NOT_SUPPORTED should be used:
Transaction Attributes in the JEE Tutorial:
[...]for methods that don’t need transactions. Because transactions involve overhead, this attribute may improve performance.So... that is what it is for? better performance? are you actually experiencing slower performance and trying to optimize? (because if that is the purpose of NOT_SUPPORTED, any performance advantage you get by using it will totally disappear thanks to huge performance penalty EJBs will bring in your application. Don't fall the hell of premature optimization.
-
11. Re: Transactional propagation types
israel.bgf Aug 26, 2009 6:11 PM (in response to asookazian)At least with plain EJB, if you suspend a transaction, the entities retrieved by a query are NOT going to be in the persistence context, and it's going to give you a performance boost (the provider don't lost it time managing the result list).
-
12. Re: Transactional propagation types
asookazian Aug 26, 2009 6:15 PM (in response to asookazian)I have a functional requirement as follows:
insert record into remote db via web service call
insert record into local db
Do not treat as a distribute tx (i.e. if one or the other fails if SQLServerException is thrown or network error, etc. do not rollback the other one)
So if there is already a tx running, then this business method is called, I need to suspend the tx, execute the method with both inserts, then continue tx.
I could probably create two methods instead of one, but I am considering this one logical unit of work w/o tx.
-
13. Re: Transactional propagation types
luxspes Aug 26, 2009 6:43 PM (in response to asookazian)
Israel Fonseca wrote on Aug 26, 2009 18:11:
At least with plain EJB, if you suspend a transaction, the entities retrieved by a query are NOT going to be in the persistence context,Interesting... lets review what is a persistency context:
Persistence context
A persistence context is a set of entity instances in which for any persistent entity identity there is a unique entity instance. Within the persistence context, the entity instances and their lifecycle is managed by a particular entity manager. The scope of this context can either be the transaction, or an extended unit of work.I might be understading it wrong, but it seems to me that a PersistencyContext is an abstract concept that pretty much maps 1 to 1 to an entityManager intance (I of course might be wrong, if I am please correct me) now you say that
the entities retrieved by a query are NOT going to be in the persistence context
, I guess that should be (after correction):the entities retrieved by a query are going to be in a DIFFERENT persistence context
... Now...what is the speed advantage in that? that since it is a new persistence context it has less entities loaded in it?
and it's going to give you a performance boost (the provider don't lost it time managing the result list).And exactly how many nanoseconds per entity am I going to get? or maybe nanoseconds per query? how many entities (or queries) do I need to be doing to make it significant?
-
14. Re: Transactional propagation types
asookazian Aug 26, 2009 6:55 PM (in response to asookazian)So I did the following in components.xml:
<core:init debug="@debug@" jndi-pattern="@jndiPattern@" transaction-management-enabled="false"/>
And this to my Seam component:
@Name("equipmentProcessingView") @Scope(ScopeType.CONVERSATION) @ProfilingThisClass //@Transactional public class EquipmentProcessingViewAction implements Serializable { ... @Transactional(TransactionPropagationType.NEVER) //don't use local tx b/c we want either process to complete even if the other throws an exception @End public void apply() { progressBarWebService.startProcess(); //web service remote db insert progressBarLocalDB.startProcess(); insertStatusAndErsNote(); //local db inserts //force re-fresh of the status @DataModels customerEquipmentOneStatusList = null; customerEquipmentOtherStatusesList = null; currentlySelectedEquipmentBean = null; icomsNote = null; ersNote = null; selectedListValueForNewStatus = null; } }
@SuppressWarnings("unchecked") //@Transactional <-- only applies for public business methods private void insertStatusAndErsNote(){ //we need to insert into two tables: EquipmentRecoveryStatusChangeLog and EquipmentNotes /* a. Status: EquipmentRecoveryStatusChangeLog: equipmentrecoveryid, equipmentstatusid, iscurrent (1 = latest, 0 = older, requires insert and update existing record with 1 to 0) b. ERS Note: EquipmentNotes */ Long equipmentRecoveryId = currentlySelectedEquipmentBean.getEquipmentRecoveryId(); EquipmentRecovery equipmentRecovery = entityManager.find(EquipmentRecovery.class, equipmentRecoveryId); int equipmentStatusId = selectedListValueForNewStatus.getCode(); EquipmentStatus equipmentStatus = entityManager.find(EquipmentStatus.class, equipmentStatusId); Date today = new Date(); //update existing record in EquipmentRecoveryStatusChangeLog which has isCurrent = 1 List<EquipmentRecoveryStatusChangeLog> ersclList = entityManager.createQuery("select erscl "+ " from EquipmentRecoveryStatusChangeLog erscl "+ " where erscl.equipmentRecovery.equipmentRecoveryId = :equipmentRecoveryId "+ " and erscl.isCurrent = 1") .setParameter("equipmentRecoveryId", equipmentRecoveryId) .getResultList(); if (ersclList != null && ersclList.size() > 0){ EquipmentRecoveryStatusChangeLog myErscl = ersclList.get(0); myErscl.setIsCurrent(false); entityManager.flush(); } //insert record in EquipmentRecoveryStatusChangeLog EquipmentRecoveryStatusChangeLog erscl = new EquipmentRecoveryStatusChangeLog( equipmentStatus, equipmentRecovery, true ); entityManager.persist(erscl); entityManager.flush(); List<ListValue> listValueList = entityManager.createQuery("select lv "+ " from ListValue lv "+ " where lv.list.listName = :listName "+ " and lv.listValue = :listValue ") .setParameter("listName", NOTE_TYPES) .setParameter("listValue", USER) .getResultList(); if (listValueList != null && listValueList.size() > 0){ ListValue myLV = listValueList.get(0); String noteTypeCode = Integer.toString(myLV.getCode()); //insert record into EquipmentNotes EquipmentNotes equipmentNotes = new EquipmentNotes(equipmentRecovery, ersNote, noteTypeCode ); entityManager.persist(equipmentNotes); entityManager.flush(); } }
I get this:
09:36:56,649 ERROR [ExceptionFilter] exception root cause javax.faces.FacesException: #{equipmentProcessingView.apply}: javax.persistence.TransactionRequiredException: no transaction is in progress at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118) at javax.faces.component.UICommand.broadcast(UICommand.java:387) at org.ajax4jsf.component.AjaxActionComponent.broadcast(AjaxActionComponent.java:55) at org.ajax4jsf.component.AjaxViewRoot.processEvents(AjaxViewRoot.java:321) at org.ajax4jsf.component.AjaxViewRoot.broadcastEvents(AjaxViewRoot.java:296) at org.ajax4jsf.component.AjaxViewRoot.processPhase(AjaxViewRoot.java:253) at org.ajax4jsf.component.AjaxViewRoot.processApplication(AjaxViewRoot.java:466) at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:82) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100) at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:265) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at jcifs.http.NtlmHttpFilter.doFilter(NtlmHttpFilter.java:125) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83) at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:68) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.MultipartFilter.doFilter(MultipartFilter.java:85) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.ExceptionFilter.doFilter(ExceptionFilter.java:64) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.RedirectFilter.doFilter(RedirectFilter.java:45) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:178) at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290) at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:368) at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:495) at org.jboss.seam.web.Ajax4jsfFilter.doFilter(Ajax4jsfFilter.java:60) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.web.LoggingFilter.doFilter(LoggingFilter.java:58) at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:69) at org.jboss.seam.servlet.SeamFilter.doFilter(SeamFilter.java:158) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.jboss.web.tomcat.filters.ReplyHeaderFilter.doFilter(ReplyHeaderFilter.java:96) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) at org.jboss.web.tomcat.security.SecurityAssociationValve.invoke(SecurityAssociationValve.java:182) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433) at org.jboss.web.tomcat.security.JaccContextValve.invoke(JaccContextValve.java:84) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104) at org.jboss.web.tomcat.service.jca.CachedConnectionValve.invoke(CachedConnectionValve.java:157) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:241) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:580) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447) at java.lang.Thread.run(Thread.java:595) Caused by: javax.faces.el.EvaluationException: javax.persistence.TransactionRequiredException: no transaction is in progress at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102) at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102) ... 52 more Caused by: javax.persistence.TransactionRequiredException: no transaction is in progress at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:301) at org.jboss.seam.persistence.EntityManagerProxy.flush(EntityManagerProxy.java:90) at com.cox.ers.session.EquipmentProcessingViewAction.insertStatusAndErsNote(EquipmentProcessingViewAction.java:151) at com.cox.ers.session.EquipmentProcessingViewAction.apply(EquipmentProcessingViewAction.java:108) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.jboss.seam.util.Reflections.invoke(Reflections.java:21) at org.jboss.seam.intercept.RootInvocationContext.proceed(RootInvocationContext.java:31) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:56) at com.cox.ers.utils.ProfilingInterceptor.profile(ProfilingInterceptor.java:22) at sun.reflect.GeneratedMethodAccessor392.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.jboss.seam.util.Reflections.invoke(Reflections.java:21) at org.jboss.seam.intercept.Interceptor.aroundInvoke(Interceptor.java:177) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:72) at org.jboss.seam.core.BijectionInterceptor.aroundInvoke(BijectionInterceptor.java:46) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) at org.jboss.seam.persistence.ManagedEntityIdentityInterceptor.aroundInvoke(ManagedEntityIdentityInterceptor.java:48) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) at org.jboss.seam.transaction.RollbackInterceptor.aroundInvoke(RollbackInterceptor.java:31) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) at org.jboss.seam.core.ConversationInterceptor.aroundInvoke(ConversationInterceptor.java:56) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) at org.jboss.seam.transaction.TransactionInterceptor$1.work(TransactionInterceptor.java:38) at org.jboss.seam.util.Work.workInTransaction(Work.java:41) at org.jboss.seam.transaction.TransactionInterceptor.aroundInvoke(TransactionInterceptor.java:32) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) at org.jboss.seam.core.MethodContextInterceptor.aroundInvoke(MethodContextInterceptor.java:42) at org.jboss.seam.intercept.SeamInvocationContext.proceed(SeamInvocationContext.java:68) at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:107) at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:166) at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:102) at com.cox.ers.session.EquipmentProcessingViewAction_$$_javassist_7.apply(EquipmentProcessingViewAction_$$_javassist_7.java) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:585) at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:329) at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:342) at org.jboss.el.parser.AstPropertySuffix.invoke(AstPropertySuffix.java:58) at org.jboss.el.parser.AstValue.invoke(AstValue.java:96) at org.jboss.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276) at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:68) at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88) ... 53 more
If you refer to persist() method in EntityManager.java you can see the javadocs clearly mention that persist throws javax.persistence.TransactionRequiredException if there is no transaction.source: http://weblogs.java.net/blog/ss141213/archive/2005/12/entitymanagerpe_1.html
That's interesting, I did not know that. Pretty much means that JPA cannot operate in auto-commit mode I guess if you want to save data to db. Seems to have nothing to do with the flushMode either.
Anyways, in EJB, a business method is typically defined as a public method that is exposed in a local/remote interface. Seam JavaBean components do not have to implement any interfaces, so how does the Seam container know which methods in the JavaBean component are business methods (wild guess: those marked public?) So that means private methods
join
the tx of theirparent
public method.So this is getting overly-complicated and messy. I want to keep the hot deploy with JavaBeans but also need the tx flexibility for my functional requirement.
Am I missing something here or what? And out of curiosity, how would you implement this, from a tx-al perspective, for this requirement if you used session beans?