10 Replies Latest reply on Nov 15, 2007 4:13 AM by bucegi omu

    jboss 4.2.1 with spring 2.0.6 causes NoTransactionException

    bucegi omu Newbie

      Yes, jboss 4.2.1 causes org.springframework.transaction.NoTransactionException.

      The integration between Spring and JBOSS does not work properly anymore after upgrading jboss from 4.0.4 to 4.2.1. Basically I have a CMT Stateless Session Bean EJB (SubscrFacadeBean) which is calling a spring bean (KtfPerformerImpl) as follows:

      ... SubscrFacadeBean.createSubscr(...)
      {
       // Get KtfPerformerImpl from Bean Factory
       KtfPerformerImpl impl = ...;
      
       // Call implementation
       impl.createSubscr(...);
      }
      

      The EJB method createSubscr is marked (CMT) with a "Required" transaction attribute.
      The KtfPerformerImpl.createSubscr method is marked "PROPAGATION_REQUIRED, -Exception" using an TransactionProxyFactoryBean.
      In spring I'm using the JTA transaction manager as follows:

      <bean id="txManager"
      class="org.springframework.transaction.jta.JtaTransactionManager">
       <property name="transactionManagerName" value="java:/TransactionManager"/>
       <property name="userTransactionName" value="UserTransaction"/>
      </bean>
      

      So, having enabled the DEBUG logging level for "org.springframework.transaction", I can see (while debugging) after entering KtfPerformerImpl.createSubscr(...):
      2007-08-24 15:59:36,146 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Using tran
      saction object [org.springframework.transaction.jta.JtaTransactionObject@c82a01]
      2007-08-24 15:59:36,146 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Using tran
      saction object [org.springframework.transaction.jta.JtaTransactionObject@c82a01]
      2007-08-24 15:59:39,646 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Participat
      ing in existing transaction
      2007-08-24 15:59:39,646 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Participat
      ing in existing transaction
      2007-08-24 15:59:39,646 DEBUG [org.springframework.transaction.support.TransactionSynchronizationMan
      ager] Initializing transaction synchronization
      2007-08-24 15:59:39,646 DEBUG [org.springframework.transaction.support.TransactionSynchronizationMan
      ager] Initializing transaction synchronization
      2007-08-24 15:59:39,646 DEBUG [org.springframework.transaction.interceptor.TransactionInterceptor] G
      etting transaction for [com.picsel.server.ezine.subscr.domain.subscrregalg.impl.KtfPerformerImpl.cre
      ateSubscr]
      2007-08-24 15:59:39,646 DEBUG [org.springframework.transaction.interceptor.TransactionInterceptor] G
      etting transaction for [com.picsel.server.ezine.subscr.domain.subscrregalg.impl.KtfPerformerImpl.cre
      ateSubscr]

      So far it's cool: KtfPerformerImpl.createSubscr(...) was enlisted in the transaction opened by EJB CMT. Then an application exception is raised in KtfPerformerImpl.createSubscr(...):
      com.picsel.server.ezine.subscr.exception.SubscriptionException: "ERROR_CODE 2 (not 0!) received!

      which SHOULD rollback the transaction, but look what I get in the log:
      2007-08-24 16:00:34,396 ERROR [EzineSubscrSrv.SUBSCR_REG_ALG__KTF_PERF_IMPL] CREATE SUBSCR: KTF request NOK after 2 tries => ABANDONING!
      com.picsel.server.ezine.subscr.exception.SubscriptionException: "ERROR_CODE 2 (not 0!) received!
       ErrorCode=SUBSCR_EXTERNAL_CREATE_FAILED
       at com.picsel.server.ezine.subscr.domain.subscrregalg.impl.KtfPerformerImpl.createSubscr(KtfPerform
      erImpl.java:203)
       at com.picsel.server.ezine.subscr.domain.subscrregalg.impl.KtfPerformerImpl$$FastClassByCGLIB$$1834
      b76.invoke(<generated>)
       at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
       at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2Aop
      Proxy.java:695)
       at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.
      java:139)
       at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor
      .java:107)
       at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.
      java:161)
       at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopPr
      oxy.java:630)
       at com.picsel.server.ezine.subscr.domain.subscrregalg.impl.KtfPerformerImpl$$EnhancerByCGLIB$$aed74
      6d5.createSubscr(<generated>)
       at com.picsel.server.ezine.subscr.ejb.SubscrFacadeBean.createSubscr(SubscrFacadeBean.java:165)
       ...
      2007-08-24 16:00:35,021 WARN [EzineSubscrSrv.SUBSCR_REG_ALG__KTF_PERF_IMPL] CREATE SUBSCR: NOK: usi
      ng reqData {msisdn=987656789, magId=98627ed10a03127f0047f959316507ea}!SUBSCR_EXTERNAL_CREATE_FAILED:
       com.picsel.server.ezine.subscr.exception.SubscriptionException: "ERROR_CODE 2 (not 0!) received!
      2007-08-24 16:00:35,990 DEBUG [org.springframework.transaction.interceptor.TransactionInterceptor] C
      ompleting transaction for [com.picsel.server.ezine.subscr.domain.subscrregalg.impl.KtfPerformerImpl.
      createSubscr] after exception: com.picsel.server.ezine.subscr.exception.SubscriptionException: "ERROR_CODE 2 (not 0!) received!
       ErrorCode=SUBSCR_EXTERNAL_CREATE_FAILED
      2007-08-24 16:00:35,990 DEBUG [org.springframework.transaction.interceptor.TransactionInterceptor] C
      ompleting transaction for [com.picsel.server.ezine.subscr.domain.subscrregalg.impl.KtfPerformerImpl.
      createSubscr] after exception: com.picsel.server.ezine.subscr.exception.SubscriptionException: "ERROR_CODE 2 (not 0!) received!
       ErrorCode=SUBSCR_EXTERNAL_CREATE_FAILED
      2007-08-24 16:00:35,990 DEBUG [org.springframework.transaction.interceptor.RuleBasedTransactionAttri
      bute] Applying rules to determine whether transaction should rollback on com.picsel.server.ezine.sub
      scr.exception.SubscriptionException: "ERROR_CODE 2 (not 0!) received!
       ErrorCode=SUBSCR_EXTERNAL_CREATE_FAILED
      2007-08-24 16:00:35,990 DEBUG [org.springframework.transaction.interceptor.RuleBasedTransactionAttri
      bute] Applying rules to determine whether transaction should rollback on com.picsel.server.ezine.sub
      scr.exception.SubscriptionException: "ERROR_CODE 2 (not 0!) received!
       ErrorCode=SUBSCR_EXTERNAL_CREATE_FAILED
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.interceptor.RuleBasedTransactionAttri
      bute] Winning rollback rule is: RollbackRuleAttribute with pattern [Exception]
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.interceptor.RuleBasedTransactionAttri
      bute] Winning rollback rule is: RollbackRuleAttribute with pattern [Exception]
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Triggering
       beforeCompletion synchronization
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Triggering
       beforeCompletion synchronization
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Participat
      ing transaction failed - marking existing transaction as rollback-only
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Participat
      ing transaction failed - marking existing transaction as rollback-only
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Setting JT
      A transaction rollback-only
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Setting JT
      A transaction rollback-only
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Registerin
      g after-completion synchronization with existing JTA transaction
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.jta.JtaTransactionManager] Registerin
      g after-completion synchronization with existing JTA transaction
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.support.TransactionSynchronizationMan
      ager] Clearing transaction synchronization
      2007-08-24 16:00:36,006 DEBUG [org.springframework.transaction.support.TransactionSynchronizationMan
      ager] Clearing transaction synchronization
      2007-08-24 16:00:36,006 ERROR [org.springframework.transaction.interceptor.TransactionInterceptor] A
      pplication exception overridden by rollback exception
      com.picsel.server.ezine.subscr.exception.SubscriptionException: "ERROR_CODE 2 (not 0!) received!
       ErrorCode=SUBSCR_EXTERNAL_CREATE_FAILED
       at com.picsel.server.ezine.subscr.domain.subscrregalg.impl.KtfPerformerImpl.createSubscr(KtfPerform
      erImpl.java:203)
       ...
      2007-08-24 16:00:36,006 ERROR [org.springframework.transaction.interceptor.TransactionInterceptor] A
      pplication exception overridden by rollback exception
      com.picsel.server.ezine.subscr.exception.SubscriptionException: "ERROR_CODE 2 (not 0!) received!
       ErrorCode=SUBSCR_EXTERNAL_CREATE_FAILED
       at com.picsel.server.ezine.subscr.domain.subscrregalg.impl.KtfPerformerImpl.createSubscr(KtfPerform
      erImpl.java:203)
      2007-08-24 16:00:36,006 ERROR [org.jboss.ejb.plugins.LogInterceptor] RuntimeException in method: pub
      lic abstract com.picsel.server.ezine.subscr.dto.Subscription com.picsel.server.ezine.subscr.ejb.inte
      rfaces.SubscrFacadeLocal.createSubscr(com.picsel.server.ezine.subscr.dto.ProviderAccountDto,java.uti
      l.Map) throws com.picsel.server.ezine.subscr.exception.SubscriptionException:
      org.springframework.transaction.NoTransactionException: No active JTA transaction
       at org.springframework.transaction.jta.JtaTransactionManager.registerAfterCompletionWithExistingTra
      nsaction(JtaTransactionManager.java:903)
       at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerAfterCompletio
      n(AbstractPlatformTransactionManager.java:885)
       at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(Abstr
      actPlatformTransactionManager.java:782)
       at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlat
      formTransactionManager.java:730)
       at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThr
      owing(TransactionAspectSupport.java:332)
       at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor
      .java:111)
       at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.
      java:161)
       at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopPr
      oxy.java:630)
       at com.picsel.server.ezine.subscr.domain.subscrregalg.impl.KtfPerformerImpl$$EnhancerByCGLIB$$aed74
      6d5.createSubscr(<generated>)
       at com.picsel.server.ezine.subscr.ejb.SubscrFacadeBean.createSubscr(SubscrFacadeBean.java:165)
       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.invocation.Invocation.performCall(Invocation.java:359)
       at org.jboss.ejb.StatelessSessionContainer$ContainerInterceptor.invoke(StatelessSessionContainer.ja
      va:237)
       at org.jboss.resource.connectionmanager.CachedConnectionInterceptor.invoke(CachedConnectionIntercep
      tor.java:158)
       at org.jboss.ejb.plugins.StatelessSessionInstanceInterceptor.invoke(StatelessSessionInstanceInterce
      ptor.java:169)
       at org.jboss.ejb.plugins.CallValidationInterceptor.invoke(CallValidationInterceptor.java:63)
       at org.jboss.ejb.plugins.AbstractTxInterceptor.invokeNext(AbstractTxInterceptor.java:121)
       at org.jboss.ejb.plugins.TxInterceptorCMT.runWithTransactions(TxInterceptorCMT.java:350)
       at org.jboss.ejb.plugins.TxInterceptorCMT.invoke(TxInterceptorCMT.java:181)
       at org.jboss.ejb.plugins.SecurityInterceptor.invoke(SecurityInterceptor.java:168)
       at org.jboss.ejb.plugins.LogInterceptor.invoke(LogInterceptor.java:205)
       at org.jboss.ejb.plugins.ProxyFactoryFinderInterceptor.invoke(ProxyFactoryFinderInterceptor.java:13
      8)
       at org.jboss.ejb.SessionContainer.internalInvoke(SessionContainer.java:648)
       at org.jboss.ejb.Container.invoke(Container.java:960)
       at org.jboss.ejb.plugins.local.BaseLocalProxyFactory.invoke(BaseLocalProxyFactory.java:430)
       at org.jboss.ejb.plugins.local.StatelessSessionProxy.invoke(StatelessSessionProxy.java:103)
       at $Proxy263.createSubscr(Unknown Source)
       at com.picsel.server.ezine.subscr.web.servlet.CreateSubscrServlet.doPost(CreateSubscrServlet.java:1
      33)
       at com.picsel.server.ezine.subscr.web.servlet.CreateSubscrServlet.doGet(CreateSubscrServlet.java:70
      )
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:690)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
       at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290
      )
       at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
       at com.picsel.server.common.web.filter.RemoteIpAddrFilter.doFilter(RemoteIpAddrFilter.java:78)
       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:179)
      
       at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:525)
       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.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:543)
       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)
       ...

      So the transaction is marked for rollback by spring, but afterwards an org.springframework.transaction.NoTransactionException is thrown, WHICH WAS NOT HAPPENING WHEN USING JBOSS 4.0.4. The result is that the application exception is overridden by the rollback exception.
      Could somebody from JBOSS team help me with this, please.

        • 1. Re: jboss 4.2.1 with spring 2.0.6 causes NoTransactionExcept
          Ales Justin Master

          Moving this to Transactions forum, since it has nothing to do with actual JBoss/Spring integration (see Sticky).

          • 2. Re: jboss 4.2.1 with spring 2.0.6 causes NoTransactionExcept
            Jonathan Halliday Master

            Mail me a test case, I'll take a look at it when I get a chance.

            • 3. Re: jboss 4.2.1 with spring 2.0.6 causes NoTransactionExcept
              bucegi omu Newbie

              So nobody from JBOSS team cares about this IMPORTANT problem that makes jboss unusable with Spring. You know, jboss team guys, after the VERY PAINFUL upgrade from jboss 4.0.4 to jboss 4.2.1 which dissapointed us already a lot, your indiference for this problem can result in only one possible solution: give up jboss and continue with spring and some other container. I'm sure that other people must hve had the same problem, so, do you, jboss team, really not care about this???!!!

              • 4. Re: jboss 4.2.1 with spring 2.0.6 causes NoTransactionExcept
                Jonathan Halliday Master

                Sorry to hear you are still having problems. Of course I care, but right now I'm busy solving problems for paying customers. Buy a support contract or be patient. Freeloaders don't have whining privileges. This applies especially ones who don't bother to submit test cases.

                • 5. Re: jboss 4.2.1 with spring 2.0.6 causes NoTransactionExcept
                  Adrian Brock Master

                  WRT http://jira.jboss.com/jira/browse/JBAS-4803

                  1) This is not a bug report. There is a large message saying READ THIS FIRST
                  on what is required to raise a bug report before you enter one, READ IT.
                  http://wiki.jboss.org/wiki/Wiki.jsp?page=HelpBugReport

                  It also says not to change the priority that is for "developers use only"
                  We'd make it protected if the JIRA software let us, instead we have to ask
                  you to follow basic instructions.

                  2) If you read the above link, you'll learn that one stacktrace does not make a bug report
                  - unless the error message is an NPE or says to report it as a bug and it is generated by JBoss code.
                  It needs context, e.g. a testcase that reproduces the problem or some
                  reasonable logging so we can tell what is going on.

                  3) None of the stacktrace above contains any JBoss AS or JBoss TM code
                  (except the container calling code - e.g. the jboss log interceptor reporting the error)
                  it's all your code and Spring

                  4) It's a Spring error message -ask them

                  5) I don't use Spring, but I'd **guess** from the error there really is no *ACTIVE* transaction.
                  This could because the transaction is marked rollback or it has been already rolledback
                  (e.g. transaction timeout). You can't register a transaction synchronization like Spring is trying to do if the transaction is not active.

                  6) Please try again when you can properly explain what the problem is,
                  rather than just dumping random (non jboss) error messages in the forums or bug reports.

                  • 6. Re: jboss 4.2.1 with spring 2.0.6 causes NoTransactionExcept
                    Adrian Brock Master

                    DO NOT re-open this bug report until it has been confirmed in the forums
                    that it is a bug in JBoss rather than Spring or your code/configuration.

                    So far you have:

                    1) Whined in the forums when really you should have been ignored for posting in the
                    wrong forum and with incomplete information.

                    2) Raised a "critical" bug report with no reason to do so.

                    There is no way we can "fix" anything from the information provided.
                    Bug reports are not there to escalate unanswered or in your case unanswerable
                    questions in the forums.

                    3) Sent me an unsolicted private e-mail (who knows who else?), i.e. spam

                    If its really that important to you, buy a support contract and get professional help
                    with a guaranteed SLA and somebody who will hold your hand to get the information
                    required to properly answer your question (most likely a configuration issue).

                    It doesn't have to be from Redhat if you don't like us. :-)

                    • 7. Re: jboss 4.2.1 with spring 2.0.6 causes NoTransactionExcept
                      bucegi omu Newbie

                      Adrian,
                      Because I cannot attach files to this topic, I have been trying to send you a private email (to adrian@jboss.org) containing a small ear to reproduce the error together with the sources for it. But it looks like the email server on your side does allow only really tiny zip files, so I was not able to send the email. How can I send you the small test ear that reproduces the error together with source files. Alternatively, is there any way to attach files to this topic?

                      • 8. Re: jboss 4.2.1 with spring 2.0.6 causes NoTransactionExcept
                        bucegi omu Newbie

                        By the way: I tried with jboss 4.2.2 and got the same error.

                        • 9. Re: jboss 4.2.1 with spring 2.0.6 causes NoTransactionExcept
                          Adrian Brock Master

                           

                          "bucegiomu@yahoo.com" wrote:
                          Adrian,
                          Because I cannot attach files to this topic, I have been trying to send you a private email (to adrian@jboss.org) containing a small ear to reproduce the error together with the sources for it. But it looks like the email server on your side does allow only really tiny zip files, so I was not able to send the email. How can I send you the small test ear that reproduces the error together with source files. Alternatively, is there any way to attach files to this topic?


                          Please don't send things by private e-mail.
                          In some counties it against the law to send unsoliceted e-mails!

                          You should have just added them to the bug report or created your own
                          since the original is closed.

                          The complaint about the original bug report is that is was unanswerable,
                          amongst other things it just showed one spring generated error message
                          with no indication on how to reproduce the problem.

                          Anyway, I raised a new bug report
                          http://jira.jboss.com/jira/browse/JBAS-4972
                          where the question is answered in the same way as before.

                          i.e. Spring bug => ask Spring

                          Since this time I could reproduce the problem, there is more
                          detailed "guesswork" on that bug report about where the problem lies.

                          I'd further guess that the Spring code is fundamentally broken for JTA.

                          The only place that actually checks the JTA transaction status
                          (javax.transaction.Transaction.getStatus())
                          is in the UserTransaction handling, so it isn't going to understand
                          some of the edge cases like heuristics or asynchronous changes to the
                          state like transaction timeouts.

                          [ejort@warjort transaction]$ grep -ri getStatus *
                          jta/JtaTransactionManager.java: return (txObject.getUserTransaction().getStatus() != Status.STATUS_NO_TRANSACTION);
                          jta/JtaTransactionManager.java: throw new TransactionSystemException("JTA failure on getStatus", ex);
                          jta/JtaTransactionManager.java: if (txObject.getUserTransaction().getStatus() != Status.STATUS_NO_TRANSACTION) {
                          jta/JtaTransactionManager.java: if (txObject.getUserTransaction().getStatus() != Status.STATUS_NO_TRANSACTION) {
                          jta/UserTransactionAdapter.java: public int getStatus() throws SystemException {
                          jta/UserTransactionAdapter.java: return this.transactionManager.getStatus();
                          jta/JtaTransactionObject.java: return (getUserTransaction().getStatus() == Status.STATUS_MARKED_ROLLBACK);
                          jta/JtaTransactionObject.java: throw new TransactionSystemException("JTA failure on getStatus", ex);
                          support/SmartTransactionObject.java: * @see javax.transaction.UserTransaction#getStatus
                          


                          • 10. Re: jboss 4.2.1 with spring 2.0.6 causes NoTransactionExcept
                            bucegi omu Newbie

                            Thank you very much Adrian.

                            I will put these results and a link to the bug in the topic that exists in spring forum about the same problem and, if I get any updates from spring guys, I will post them here too.

                            The spring forum topic is:
                            http://forum.springframework.org/showthread.php?t=27867