Skip to content

Commit

Permalink
CAUSEWAY-3839: fixes former AOPPatch no longer working
Browse files Browse the repository at this point in the history
- by declaring the Spring provided TransactionInterceptor as 'fallback'
we can now override with our own variant, that knows how to translate DN
exceptions
  • Loading branch information
andi-huber committed Dec 23, 2024
1 parent c0d36cb commit 135dbdf
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 139 deletions.
1 change: 0 additions & 1 deletion core/config/src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
module org.apache.causeway.core.config {
exports org.apache.causeway.core.config;
exports org.apache.causeway.core.config.applib;
exports org.apache.causeway.core.config.beans.aoppatch;
exports org.apache.causeway.core.config.beans;
exports org.apache.causeway.core.config.converters;
exports org.apache.causeway.core.config.datasources;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;

import org.apache.causeway.applib.annotation.DomainObject;
Expand All @@ -41,7 +40,6 @@
import org.apache.causeway.commons.internal.base._Timing;
import org.apache.causeway.core.config.CausewayModuleCoreConfig;
import org.apache.causeway.core.config.beans.CausewayBeanTypeClassifier.ContextType;
import org.apache.causeway.core.config.beans.aoppatch.AopPatch;

import lombok.extern.log4j.Log4j2;

Expand All @@ -58,9 +56,6 @@
*/
@Configuration(proxyBeanMethods = false)
@Named(CausewayModuleCoreConfig.NAMESPACE + ".CausewayBeanFactoryPostProcessor")
@Import({
AopPatch.class
})
@Log4j2
public class CausewayBeanFactoryPostProcessor
implements
Expand All @@ -86,6 +81,8 @@ public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFac
var registry = (BeanDefinitionRegistry) beanFactory;
var beanDefNames = registry.getBeanDefinitionNames();

TransactionInterceptorPatcher.setDefaultTransactionInterceptorToFallback(registry);

var componentCollector = new CausewayComponentCollector(registry, causewayBeanTypeClassifier);

Stream.of(beanDefNames)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.causeway.core.config.beans.aoppatch;
package org.apache.causeway.core.config.beans;

import org.springframework.transaction.interceptor.TransactionInterceptor;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;

@FunctionalInterface
public interface TransactionInterceptorFactory {
import lombok.experimental.UtilityClass;

TransactionInterceptor createTransactionInterceptor();
@UtilityClass
class TransactionInterceptorPatcher {

/**
* In support of custom DataNucleus exception translation.
*/
void setDefaultTransactionInterceptorToFallback(final BeanDefinitionRegistry registry) {
if(!registry.containsBeanDefinition("transactionInterceptor")) return;
registry.getBeanDefinition("transactionInterceptor").setFallback(true);
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,23 @@
import org.datanucleus.metadata.PersistenceUnitMetaData;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Role;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import org.apache.causeway.commons.internal.assertions._Assert;
import org.apache.causeway.commons.internal.base._NullSafe;
import org.apache.causeway.core.config.CausewayConfiguration;
import org.apache.causeway.core.config.beans.CausewayBeanMetaData.PersistenceStack;
import org.apache.causeway.core.config.beans.CausewayBeanTypeRegistry;
import org.apache.causeway.core.config.beans.aoppatch.TransactionInterceptorFactory;
import org.apache.causeway.core.metamodel.context.MetaModelContext;
import org.apache.causeway.core.metamodel.services.objectlifecycle.ObjectLifecyclePublisher;
import org.apache.causeway.persistence.jdo.datanucleus.changetracking.JdoLifecycleListener;
Expand Down Expand Up @@ -201,13 +204,15 @@ public JdoTransactionManager getTransactionManager(
}

/**
* AOP PATCH
* @implNote works only with patch package 'org.apache.causeway.core.config.beans.aoppatch'
* Works in combination with org.apache.causeway.core.config.beans.TransactionInterceptorPatcher.
* Replaces the Spring provided {@link TransactionInterceptor}, with an overwritten variant.
*/
@Bean @Primary
@SuppressWarnings("serial")
public TransactionInterceptorFactory getTransactionInterceptorFactory() {
return ()->new TransactionInterceptor() {
@Bean(name = "transactionInterceptorDN")
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(final TransactionAttributeSource transactionAttributeSource) {
return new TransactionInterceptor((TransactionManager)null, transactionAttributeSource) {
private static final long serialVersionUID = 1L;

@Override @SneakyThrows
protected void completeTransactionAfterThrowing(final TransactionInfo txInfo, final Throwable ex) {
super.completeTransactionAfterThrowing(txInfo, ex);
Expand All @@ -216,22 +221,13 @@ protected void completeTransactionAfterThrowing(final TransactionInfo txInfo, fi
var txManager = txInfo.getTransactionManager();
if(txManager instanceof JdoTransactionManager) {
var jdoDialect = ((JdoTransactionManager)txManager).getJdoDialect();
if(jdoDialect instanceof PersistenceExceptionTranslator) {
var translatedEx = ((PersistenceExceptionTranslator)jdoDialect)
.translateExceptionIfPossible((RuntimeException)ex);

if(translatedEx!=null) {
throw translatedEx;
}

if(jdoDialect instanceof PersistenceExceptionTranslator pet) {
var translatedEx = pet.translateExceptionIfPossible((RuntimeException)ex);
if(translatedEx!=null) throw translatedEx;
}

if(ex instanceof JDOException) {
var translatedEx = jdoDialect.translateException((JDOException)ex);

if(translatedEx!=null) {
throw translatedEx;
}
if(ex instanceof JDOException jdoException) {
var translatedEx = jdoDialect.translateException(jdoException);
if(translatedEx!=null) throw translatedEx;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import jakarta.inject.Provider;

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -83,7 +82,7 @@ void aquireLock() {
lock.install();
}

@Disabled("fails on surefire since Spring Boot 3.4.1")
//@Disabled("fails on surefire since Spring Boot 3.4.1")
@Test @Order(1)
void booksUniqueByIsbn_whenViolated_shouldThrowTranslatedException() {

Expand Down

0 comments on commit 135dbdf

Please sign in to comment.