Spring Autowiring stopped working on GAE

后端 未结 3 494
离开以前
离开以前 2020-12-21 22:13

I\'m sure my app worked right until yesterday, when I got this error:

Failed startup of context com.google.apphosting.utils.jetty.RuntimeAppEngineW

相关标签:
3条回答
  • 2020-12-21 22:50

    It seems that SessionFactoryImpl references a class that google doesn't have on it's whiteliste and it cant' be loaded in that case.

    Here's an article about that: http://googlecloudsql.blogspot.de/

    0 讨论(0)
  • 2020-12-21 23:04

    The problem is the @Transactional annotation on the @Service class. It uses javax.naming.NamingException in some part I don't know, and that's not a whitelisted class.

    0 讨论(0)
  • 2020-12-21 23:14

    Fabio helped point me in the right direction. I found that declarative transactions using @Transactional do not work in GAE because Spring scans org.hibernate.impl.SessionFactoryImpl which causes the loading of javax.naming classes which are not on the GAE whitelist. I had the same issue switching to XML based declarations. So I ended up using programmatic transaction management using TransactionTemplate objects and that appears to be working.

    EDIT: Added code sample

    From my spring configuration I removed <tx:annotation-driven/> to disable @Transactional and replaced it with

    <bean id="defaultTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager"><ref local="transactionManager"/></property>
    </bean>
    

    If you're using multiple transaction semantics e.g. PROPAGATION_REQUIRED and PROPAGATION_SUPPORTS, you'll have to create additional beans, one for each scenario e.g.

    <bean id="supportingTransactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="propagationBehaviorName" value="PROPAGATION_SUPPORTS"/>
        <property name="transactionManager"><ref local="transactionManager"/></property>
    </bean>
    

    I left my original service classes with the @Transactional notation. It doesn't matter since <tx:annotation-driven/> has been removed and I might switch back some day if the issue is fixed. Instead I sublcassed them to use TransactionTemplate

    public class GAEUserService extends UserService {
    
        @Autowired
        private TransactionTemplate defaultTransactionTemplate;
    
        @Override
        public void update(final User user) {
            defaultTransactionTemplate.execute(new TransactionCallbackWithoutResult() {
                @Override
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                    UserService.super.update(user);
                }
            });
        }
    }
    

    The one downside I found was that I had to convert checked exceptions thrown by my service methods to unchecked exceptions because checked exceptions don't agree with the signature of doInTransactionWithoutResult

    0 讨论(0)
提交回复
热议问题