I\'m sure my app worked right until yesterday, when I got this error:
Failed startup of context com.google.apphosting.utils.jetty.RuntimeAppEngineW
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/
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.
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