user2083529
user2083529

Reputation: 735

Unable to catch TransactionSystemException

I have an Entity class Person which is connected to another entity Address via JoinColumn and has OneToOne relation with Person, the Address entity has a @NotNull annotation on field country.

Simplified Code is below:

@Entity
public class Person {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long PersonId; 

@Valid
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "address_id")
private Address address;
....
..some more fields, getters and setters etc..
...
}

The Address entity is below:

@Entity
public class Address {

@Id
@GeneratedValue
private Long addressId;

private String street;

@NotEmpty(message = "Country should be there")
private String country;

....some more fields and getters and setters etc ....
}

Other than that i have a PersonRepository.

I also have a service method i.e updateAddress, the simplest form of the method is below:

public class Service {

@Transactional
public void updateAddress(Long personId, Address address) {
try {
Person original = findPersonById(personId);

...some validations etc ....

original.setAddress(address);            
personRepository.save(original);
} catch (ConstraintViolationException e) {

    }
}

I have written one small unit test where i am trying to update the address using updateAddress method for a person having no predefined Address.

i.e

@Test
void checkUpdateAddress() {
Person person = new Person();
.....initiate some fields, except address ....
Long personId =personRepository.save(person);

Address address = new Address();
address.street("abcd");

service.updatePerson(personId, address);
//assertions etc
}

The problem is that i get

Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [com.foor.bar.Address] during persist time for groups [javax.validation.groups.Default, ] List of constraint violations:[ ConstraintViolationImpl{interpolatedMessage='Country should be there', propertyPath=country, rootBeanClass=class com.foo.bar.Address, messageTemplate='Country should be there'}

org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction

I have tried using try/catch block, but still unable to catch this exception.

Note: i have simplified the codes to the minimal extent, if there is something i've forgotten or if my problem is unclear then do ask.

EDIT:

Full stack stace

ERROR ExceptionMapperStandardImpl:39 - HHH000346: Error during managed flush [Validation failed for classes [com.foo.bar.Address] during persist time for groups [javax.validation.groups.Default, ] List of constraint violations:[ ConstraintViolationImpl{interpolatedMessage='Country should be there', propertyPath=country, rootBeanClass=class com.foo.bar.Address, messageTemplate='Country should be there'} ]]

org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction

at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:545) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:532) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) at com.foo.bar.service.Service$$EnhancerBySpringCGLIB$$57d9106c.updateAddress() at com.rfoo.bar.service.MyTest.checkUpdateAddressMethod(MyTest.java:956) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:436) at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:115) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:170) at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:166) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:113) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:112) at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120) at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) at java.util.Iterator.forEachRemaining(Iterator.java:116) at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120) at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$2(HierarchicalTestExecutor.java:120) at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) at java.util.Iterator.forEachRemaining(Iterator.java:116) at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:418) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.lambda$executeRecursively$3(HierarchicalTestExecutor.java:120) at org.junit.platform.engine.support.hierarchical.SingleTestExecutor.executeSafely(SingleTestExecutor.java:66) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.executeRecursively(HierarchicalTestExecutor.java:108) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor$NodeExecutor.execute(HierarchicalTestExecutor.java:79) at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:55) at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:43) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154) at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90) at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:74) at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) Caused by: javax.persistence.RollbackException: Error while committing the transaction at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:77) at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:71) at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:536) ... 63 more Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [com.foo.bar.Address] during persist time for groups [javax.validation.groups.Default, ] List of constraint violations:[ ConstraintViolationImpl{interpolatedMessage='Country should be there', propertyPath=transactionId, rootBeanClass=class com.foo.bar.Address, messageTemplate='Country should be there'} ] at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:140) at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:80) at org.hibernate.action.internal.EntityInsertAction.preInsert(EntityInsertAction.java:205) at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:82) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:600) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:474) at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1436) at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:493) at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3206) at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2412) at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:473) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:156) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231) at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:68) ... 64 more

Upvotes: 1

Views: 2081

Answers (2)

Chris
Chris

Reputation: 449

The reason the ConstraintViolationException is not being caught is that the repository is not throwing that exception, it is throwing TransactionSystemException, which has a nested ConstraintViolationException instance.

See this question for more information on catching nested exceptions.

Upvotes: -1

gargkshitiz
gargkshitiz

Reputation: 2168

Try catching PersistenceException. This exception is a wrapped exception and is not directly thrown. You can extract the wrapped ConstraintViolationException using the getCause() method.

Upvotes: 2

Related Questions