Spring Autowiring stopped working on GAE

大兔子大兔子 提交于 2019-12-18 09:39:11

问题


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

Failed startup of context com.google.apphosting.utils.jetty.RuntimeAppEngineWebAppContext@1079ff{/,/ base/data/home/apps/s~trewnewmedia/1.357617962256387950} org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scadenziarioController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void it.trew.prove.web.controllers.ScadenziarioController.setScadenzaService(it. trew.prove.services.ScadenzaService); nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scadenzaService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void it.trew.prove.services.ScadenzaService.setSocietaService(it.trew.prove.serv ices.SocietaService); nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'societaService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void it.trew.prove.services.SocietaService.setSocietaDao(it.trew.prove.model.dao .Dao); nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dao': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mySessionFactory': Post-processing of the FactoryBean's object failed; nested exception is java.lang.SecurityException: Unable to get members for class org.hibernate.impl.SessionFactoryImpl

I am using Hibernate with Google Cloud SQL, and it always worked.

On my local machine, with local MySQL, it still works!

I don't think it's a Cloud SQL issue, because removing some autowiring (a test) it still connects and so on. Here's my xml:

<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="myDataSource" />
        <property name="annotatedClasses">
            <list>
                <value>it.trew.prove.model.beans.Scadenza</value>
                <value>it.trew.prove.model.beans.Fornitore</value>
                <value>it.trew.prove.model.beans.Societa</value>
            </list>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
                <!-- <prop key="hibernate.hbm2ddl.import_files">/setup.sql</prop> -->
            </props>
        </property>
    </bean>

A piece of my DAO:

@Component
public class Dao {

    @Resource(name = "mySessionFactory")
    private SessionFactory sessionFactory;
...

And my service:

@Service
@Transactional
public class SocietaService {

    private Dao societaDao;

    @Autowired
    public void setSocietaDao(Dao societaDao) {
        this.societaDao = societaDao;
    }
...

I can't find what's different between GAE and my local (mvn gae:run). And why last week that worked perfectly.

Please GAE team, support me! I'm going crazy on this issue

(I'll probably start a bounty, it's too much urgent)

EDIT my pom.xml hibernate part:

<!-- Hibernate framework -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>3.3.2.GA</version>
        <type>pom</type>
        <!--hibernate-dependencies is a pom, not needed for hibernate-core-->
      </dependency>
      <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-annotations</artifactId>
        <version>3.4.0.GA</version>
    </dependency>
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.12.1.GA</version>
    </dependency>

回答1:


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/




回答2:


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




回答3:


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.



来源:https://stackoverflow.com/questions/9783773/spring-autowiring-stopped-working-on-gae

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!