Insert single record in mapping table in spring boot rest - spring

In my project two classes Book and Story as OneToMany relationship I want to insert only records in Story class I have the logic of this
//service class
public Story saveStoryBook(int id, Story story) {
Story stry=new Story();
stry.setStoryName(story.getStoryName());
Book book= bookRepository.findById(id).get();
log.info(book);
book.addStory(stry);
stry.setBook(book);
log.info(stry);
Story s= storyRepository.save(stry);
log.info(s);
return s;
}
then run this code using postman I got 500 error and I show in command prompt
2021-12-30 10:19:05 - Initializing Spring DispatcherServlet 'dispatcherServlet'
2021-12-30 10:19:05 - Initializing Servlet 'dispatcherServlet'
2021-12-30 10:19:05 - Detected StandardServletMultipartResolver
2021-12-30 10:19:05 - Detected AcceptHeaderLocaleResolver
2021-12-30 10:19:05 - Detected FixedThemeResolver
2021-12-30 10:19:05 - Detected org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator#25110bb9
2021-12-30 10:19:05 - Detected org.springframework.web.servlet.support.SessionFlashMapManager#7d49a1a0
2021-12-30 10:19:05 - enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2021-12-30 10:19:05 - Completed initialization in 2 ms
2021-12-30 10:19:05 - POST "/story/save/1", parameters={}
2021-12-30 10:19:05 - Mapped to in.techSoft.OTM.Controller.StoryController#saveStory(int, Story)
2021-12-30 10:19:05 - Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2021-12-30 10:19:05 - Read "application/json;charset=UTF-8" to [Story(storyId=0, storyName=Collection, book=null)]
2021-12-30 10:19:05 - Found thread-bound EntityManager [SessionImpl(1720633741<open>)] for JPA transaction
2021-12-30 10:19:05 - Creating new transaction with name [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findById]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly
2021-12-30 10:19:05 - Setting JDBC Connection [HikariProxyConnection#1983273745 wrapping org.postgresql.jdbc.PgConnection#5787763b] read-only
2021-12-30 10:19:05 - Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle#6ebe9625]
Hibernate: select book0_.id as id1_0_0_, book0_.book_name as book_nam2_0_0_, storylist1_.bid as bid3_1_1_, storylist1_.story_id as story_id1_1_1_, storylist1_.story_id as story_id1_1_2_, storylist1_.bid as bid3_1_2_, storylist1_.story_name as story_na2_1_2_ from book book0_ left outer join story storylist1_ on book0_.id=storylist1_.bid where book0_.id=?
2021-12-30 10:19:05 - Initiating transaction commit
2021-12-30 10:19:05 - Committing JPA transaction on EntityManager [SessionImpl(1720633741<open>)]
2021-12-30 10:19:05 - Resetting read-only flag of JDBC Connection [HikariProxyConnection#1983273745 wrapping org.postgresql.jdbc.PgConnection#5787763b]
2021-12-30 10:19:05 - Not closing pre-bound JPA EntityManager after transaction
2021-12-30 10:19:05 - Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2021-12-30 10:19:05 - Failed to complete request: org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.StackOverflowError
2021-12-30 10:19:05 - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause
java.lang.StackOverflowError: null
at in.techSoft.OTM.Entity.Book.toString(Book.java:12)
at java.base/java.lang.StringConcatHelper.stringOf(StringConcatHelper.java:453)
at in.techSoft.OTM.Entity.Story.toString(Story.java:11)
at java.base/java.lang.String.valueOf(String.java:4215)
at java.base/java.lang.StringBuilder.append(StringBuilder.java:169)
at java.base/java.util.AbstractCollection.toString(AbstractCollection.java:457)
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:622)
at java.base/java.lang.StringConcatHelper.stringOf(StringConcatHelper.java:453)
2021-12-30 10:19:05 - "ERROR" dispatch for POST "/error", parameters={}
2021-12-30 10:19:05 - Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
2021-12-30 10:19:05 - Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2021-12-30 10:19:05 - Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
2021-12-30 10:19:05 - Writing [{timestamp=Thu Dec 30 10:19:05 IST 2021, status=500, error=Internal Server Error, path=/story/save/1 (truncated)...]
2021-12-30 10:19:05 - Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2021-12-30 10:19:05 - Exiting from "ERROR" dispatch, status 500
Repository classes
StoryRepository
#Repository
public interface StoryRepository extends JpaRepository<Story, Integer> {
}
BookRepository
#Repository
public interface BookRepository extends JpaRepository<Book, Integer> {
}
Service interface
#Component
public interface BookService {
public Book saveBook(Book book);
public Book findByBookId(int bookId);
public Story saveStoryBook(int id,Story story);
}
I struggle on inserting data inside story class

Looks like Book.toString uses Story.toString which uses Book.toString. That's why you have StackOverflowError. Refactor Story.toString to not use Book.toString but maybe only use Book id.

Related

SpringBoot Transactional Propagation REQUIRES_NEW doesn't create new Transaction

I have the following scenario:
#Service
public class ServiceA {
#Autowired private ServiceB serviceB;
public void runA(){
serviceB.runB()
}
}
#Service
public class ServiceB {
#Autowired private ServiceC serviceC;
#Transactional
public void runB(){
serviceC.runC()
...rest of the logic
}
}
#Service
public class ServiceC {
#Autowired private TestRepository testRepository;
#Transactional(propagation = Propagation.REQUIRES_NEW)
public boolean runC(){
Optional<TestEntity> testEntityOptional = testRepository.findByKeyAndType("Key", "Type");
if(testEntityOptional.isPresent()) {
testEntityOptional.get().setActive(true);
return true;
}
return false;
}
}
#Transactional
public interface TestRepository
extends JpaRepository<TestEntity, Integer>, JpaSpecificationExecutor<TestEntity> {
#Lock(LockModeType.PESSIMISTIC_WRITE)
#QueryHints({#QueryHint(name = "javax.persistence.lock.timeout", value = "5000")})
Optional<TestEntity> findByKeyAndType(#NotNull String key, #NotNull String type);
}
I expect next flow:
ServiceA.runA() invokes ServiceB.runB()
ServiceB.runB() opens TRANSACTION_1 (or use transaction if it's opened before) as default propagation is REQUIRED
ServiceB.runB() invokes ServiceC.runC()
ServiceC.runC() opens TRANSACTION_2 because propagation is REQUIRED_NEW
ServiceC.runC() invokes TestRepository.findByKeyAndType() to fetch testEntity by some criteria
TestRepository.findByKeyAndType() return record from DB which match the criteria and lock it for read/update
ServiceB.runC() process the record
ServiceB.runC() returns value and TRANSACTION_2 is committed and so lock released
ServiceB.runB() returns and TRANSACTION_1 is committed
But from my testing this is not the case. It seams that ServiceC.runC() do not create new transaction (TRANSACTION_2) even propagation REQUIRED_NEW is set (or it do not commit it at the return), and lock is released only when ServiceB.runB() returns (when TRANSACTION_1 is committed)
Do anyone see what I am doing wrong here? Is this normal behavior of SpringBoot?
Also the lock timeout doesn't work:
I am using Postgress v10 for DB where lock_timeout is set to "0".
So it looks like #QueryHints({#QueryHint(name = "javax.persistence.lock.timeout", value = "5000")}) doesn't work as once record is locked, the other transaction which try to read the record hangs for a while until the record is unlocked
Once I enabled logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG, this is what I see. It includes suspension and resumption.
Is your transaction manager also JpaTransactionManager?
2020-06-30 01:11:53.239 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [com.example.accessingdatajpa.BlogService.save]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
2020-06-30 01:11:57.532 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(1968179698<open>)] for JPA transaction
2020-06-30 01:11:57.538 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle#7f2542f]
2020-06-30 01:12:02.432 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(1968179698<open>)] for JPA transaction
2020-06-30 01:12:04.032 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Suspending current transaction, creating new transaction with name [com.example.accessingdatajpa.Service2.save]
2020-06-30 01:12:06.915 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(2143659352<open>)] for JPA transaction
2020-06-30 01:12:06.916 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle#42fd8f2f]
2020-06-30 01:12:10.196 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(2143659352<open>)] for JPA transaction
2020-06-30 01:12:11.489 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Participating in existing transaction
2020-06-30 01:12:12.227 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
2020-06-30 01:12:13.082 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(2143659352<open>)]
2020-06-30 01:12:13.109 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(2143659352<open>)] after transaction
2020-06-30 01:12:13.110 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Resuming suspended transaction after completion of inner transaction
2020-06-30 01:12:16.409 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
2020-06-30 01:12:17.541 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(1968179698<open>)]
2020-06-30 01:12:17.542 DEBUG 47133 --- [ main] o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(1968179698<open>)] after transaction

Not fetch a LAZY relation if I call from a method which calls after another Transactional method

In my Spring Boot 2.2.5.RELEASE application I have a problem when I try to fetch a LAZY field.
The problem occurs in a service method, createWayBillFromInvoice, which marked as #Transactional.
Case A: I call this method from a controller directly it executes with no problem.
Case B: I call the same method from another service method which is not itself Transactional
my LAZY fields not fetch.
So I assume it is about Transaction management but I could not find the reason.
The method where my LAZY fields not fetched (and fetched in a direct-call):
#Transactional
public createWayBillFromInvoice(){
Invoice invoice = invoiceRepository.getInvoice(invoiceId);//invoice is selected
Order order = invoice.getOrder();
}
Here my order relation is not null but not initialized and not proxied, so If I call order.getOtherRelations it returns empty.
In case B I call something like:
public void create(){ //This method IS NOT Transactional
invoiceService.createInvoice();//This method is Transactional
waybillService.createWaybilFromInvoice();//The method declared above
}
I tried:
Make the create method Transactional
Set propagation to REQUIRES_NEW for createWaybillFromInvoice
Here are some logs:
2020-06-04 17:17:16.337 DEBUG 1208 --- [nio-9002-exec-4] o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [io.salesart.billingservice.service.impl.WaybillServiceImpl.createWayBillFromInvoice]:
2020-06-04 17:17:16.376 DEBUG 1208 --- [nio-9002-exec-4] o.s.jdbc.datasource.DataSourceUtils : Changing isolation level of JDBC Connection [HikariProxyConnection#2044564149 wrapping org.postgresql.jdbc.PgConnection#27db45f] to 2
2020-06-04 17:17:16.450 DEBUG 1208 --- [nio-9002-exec-4] o.h.e.t.internal.TransactionImpl : On TransactionImpl creation, JpaCompliance#isJpaTransactionComplianceEnabled == false
2020-06-04 17:17:16.451 DEBUG 1208 --- [nio-9002-exec-4] o.h.e.t.internal.TransactionImpl : begin
2020-06-04 17:17:16.451 DEBUG 1208 --- [nio-9002-exec-4] org.postgresql.jdbc.PgConnection : setAutoCommit = false
2020-06-04 17:17:16.457 DEBUG 1208 --- [nio-9002-exec-4] o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle#caf1ee0]
2020-06-04 17:17:19.532 DEBUG 1208 --- [nio-9002-exec-4] o.s.orm.jpa.JpaTransactionManager : Found thread-bound EntityManager [SessionImpl(1021250378<open>)] for JPA transaction

Spring transactions - isolation and propagation understanding

I am exploring spring transactions and after going through the spring docs and the following link i still have few questions. If I have a parent method with Propogation.REQUIRED which is calling 3 methods with Propogation.REQUIRES_NEW as follows:
//#Transactional(isolation=Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
public Contact saveContactInSteps(Contact contact, String newFirstName, String newLastName, Date bDate) throws Exception {
contact.setFirstName(newFirstName);
try {
updateContactFirstName(contact);
} catch (Exception e) {
LOG.error("Contact first name could not be saved !!");
e.printStackTrace();
throw e;
}
contact.setLastName(newLastName);
try {
updateContactLastName(contact);
} catch (Exception e) {
LOG.error("Contact Last name could not be saved !!");
e.printStackTrace();
throw e;
}
contact.setBirthDate(bDate);
updateContactBday(contact);
return contact;
}
public Contact saveById(Contact contact) {
sessionFactory.getCurrentSession().saveOrUpdate(contact);
LOG.info("Contact " + contact + " saved successfully");
return contact;
}
//#Transactional(isolation=Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
public Contact updateContactFirstName(Contact contact) throws Exception {
throw new Exception("Cannot update first name");
//sessionFactory.getCurrentSession().saveOrUpdate(contact);
//LOG.info("Contact First name saved successfully");
//return contact;
}
//#Transactional(isolation=Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
public Contact updateContactLastName(Contact contact) throws Exception {
throw new Exception("Cannot update last name");
//sessionFactory.getCurrentSession().saveOrUpdate(contact);
//LOG.info("Contact " + contact + " saved successfully");
//return contact;
}
//#Transactional(isolation=Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
public Contact updateContactBday(Contact contact) {
sessionFactory.getCurrentSession().saveOrUpdate(contact);
LOG.info("Contact Birth Date saved successfully");
return contact;
}
Whenever i process the parent method i.e. saveContactInSteps, even the last name is getting updated in database. I am not sure how that is happening. If i throw the exception from first child method nothing gets updated. Is it because of the fact that i am setting the attributes i.e. names and birthdate in the parent method ? Even if i am setting the attributes in the parent method, i am not letting the parent method complete as well. Does the isolation level play any part here ? I believe it's for concurrent transactions ? Is there something i am missing ?
EDIT 1:
After going through the article i did realize what i was missing. I needed AOP proxies in place which i have added as follows:
<aop:config>
<aop:pointcut
expression="execution(* org.pack.spring.transactions.ContactService.*(..))"
id="updateOperation" />
<aop:advisor pointcut-ref="updateOperation" advice-ref="saveUpdateAdvice" />
</aop:config>
<tx:advice id="saveUpdateAdvice">
<tx:attributes>
<tx:method name="update*" propagation="REQUIRES_NEW" isolation="DEFAULT" rollback-for="Exception"/>
<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>
Log output is as follows:
01:23:57.535 [main] DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'ContactService.save' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
01:23:57.550 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0'
01:23:57.552 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating shared instance of singleton bean 'saveUpdateAdvice'
01:23:57.552 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean 'saveUpdateAdvice'
01:23:57.552 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Eagerly caching bean 'saveUpdateAdvice' to allow for resolving potential circular references
01:23:57.553 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'transactionManager'
01:23:57.553 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Creating instance of bean '(inner bean)#56ac5c80'
01:23:57.553 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
01:23:57.553 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0'
01:23:57.557 [main] DEBUG o.s.t.i.NameMatchTransactionAttributeSource - Adding transactional method [update*] with attribute [PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,-Exception]
01:23:57.557 [main] DEBUG o.s.t.i.NameMatchTransactionAttributeSource - Adding transactional method [save*] with attribute [PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-Exception]
01:23:57.557 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
01:23:57.557 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0'
01:23:57.557 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor'
01:23:57.557 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0'
01:23:57.558 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean '(inner bean)#56ac5c80'
01:23:57.558 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'saveUpdateAdvice'
01:23:57.558 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'saveUpdateAdvice'
01:23:57.568 [main] DEBUG o.s.a.a.a.AspectJAwareAdvisorAutoProxyCreator - Creating implicit proxy for bean 'springTxContactService' with 0 common interceptors and 3 specific interceptors
01:23:57.575 [main] DEBUG o.s.aop.framework.CglibAopProxy - Creating CGLIB proxy: target source is SingletonTargetSource for target object [org.pack.ch9.spring.transactions.hibernate.home.ContactService#598260a6]
01:23:57.654 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public org.pack.ch9.spring.transactions.hibernate.home.Contact org.pack.ch9.spring.transactions.hibernate.home.ContactService.save(org.pack.ch9.spring.transactions.hibernate.home.Contact)
01:23:57.654 [main] DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'ContactService.saveContactInSteps' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
01:23:57.655 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public org.pack.ch9.spring.transactions.hibernate.home.Contact org.pack.ch9.spring.transactions.hibernate.home.ContactService.saveContactInSteps(org.pack.ch9.spring.transactions.hibernate.home.Contact,java.lang.String,java.lang.String,java.util.Date) throws java.lang.Exception
01:23:57.655 [main] DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'ContactService.findAll' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
01:23:57.656 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public java.util.List org.pack.ch9.spring.transactions.hibernate.home.ContactService.findAll()
01:23:57.656 [main] DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'ContactService.findById' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
01:23:57.656 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public org.pack.ch9.spring.transactions.hibernate.home.Contact org.pack.ch9.spring.transactions.hibernate.home.ContactService.findById(java.lang.Long)
01:23:57.657 [main] DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'ContactService.saveById' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
01:23:57.657 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public org.pack.ch9.spring.transactions.hibernate.home.Contact org.pack.ch9.spring.transactions.hibernate.home.ContactService.saveById(org.pack.ch9.spring.transactions.hibernate.home.Contact)
01:23:57.657 [main] DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'ContactService.updateContactFirstName' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
01:23:57.657 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public org.pack.ch9.spring.transactions.hibernate.home.Contact org.pack.ch9.spring.transactions.hibernate.home.ContactService.updateContactFirstName(org.pack.ch9.spring.transactions.hibernate.home.Contact) throws java.lang.Exception
01:23:57.658 [main] DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'ContactService.updateContactLastName' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
01:23:57.658 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public org.pack.ch9.spring.transactions.hibernate.home.Contact org.pack.ch9.spring.transactions.hibernate.home.ContactService.updateContactLastName(org.pack.ch9.spring.transactions.hibernate.home.Contact) throws java.lang.Exception
01:23:57.658 [main] DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'ContactService.updateContactBday' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
01:23:57.658 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public org.pack.ch9.spring.transactions.hibernate.home.Contact org.pack.ch9.spring.transactions.hibernate.home.ContactService.updateContactBday(org.pack.ch9.spring.transactions.hibernate.home.Contact)
01:23:57.659 [main] DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'ContactService.setSessionFactory' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
01:23:57.660 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public void org.pack.ch9.spring.transactions.hibernate.home.ContactService.setSessionFactory(org.hibernate.SessionFactory)
01:23:57.661 [main] DEBUG o.s.t.a.AnnotationTransactionAttributeSource - Adding transactional method 'ContactService.getSessionFactory' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
01:23:57.661 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public org.hibernate.SessionFactory org.pack.ch9.spring.transactions.hibernate.home.ContactService.getSessionFactory()
01:23:57.661 [main] DEBUG o.s.aop.framework.CglibAopProxy - Found 'equals' method: public boolean java.lang.Object.equals(java.lang.Object)
01:23:57.662 [main] DEBUG o.s.aop.framework.CglibAopProxy - Unable to apply any optimisations to advised method: public java.lang.String java.lang.Object.toString()
01:23:57.698 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Finished creating instance of bean 'org.springframework.context.event.internalEventListenerFactory'
01:23:57.698 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.aop.support.DefaultBeanFactoryPointcutAdvisor#0'
01:23:57.698 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'saveUpdateAdvice'
01:23:57.698 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'sessionFactory'
01:23:57.698 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'hibernateProperties'
01:23:57.698 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor'
01:23:57.698 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor'
01:23:57.699 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.transaction.config.internalTransactionalEventListenerFactory'
01:23:57.699 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
01:23:57.746 [main] DEBUG o.s.c.s.GenericXmlApplicationContext - Unable to locate LifecycleProcessor with name 'lifecycleProcessor': using default [org.springframework.context.support.DefaultLifecycleProcessor#21d1b321]
01:23:57.747 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'
01:23:57.750 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Could not find key 'spring.liveBeansView.mbeanDomain' in any property source
01:23:57.752 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'springTxContactService'
01:23:57.755 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'transactionManager'
01:23:57.762 [main] DEBUG o.s.o.h.HibernateTransactionManager - Creating new transaction with name [org.pack.ch9.spring.transactions.hibernate.home.ContactService.findById]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
01:23:57.962 [main] DEBUG o.s.o.h.HibernateTransactionManager - Opened new Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for Hibernate transaction
01:23:57.964 [main] DEBUG o.s.o.h.HibernateTransactionManager - Preparing JDBC Connection of Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
01:23:57.965 [main] DEBUG o.s.j.d.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/springorm]
01:23:57.977 [main] DEBUG o.s.jdbc.datasource.DataSourceUtils - Setting JDBC Connection [com.mysql.jdbc.JDBC4Connection#2a685eba] read-only
01:23:57.983 [main] DEBUG o.s.o.h.HibernateTransactionManager - Exposing Hibernate transaction as JDBC transaction [com.mysql.jdbc.JDBC4Connection#2a685eba]
Hibernate: select distinct contact0_.ID as ID1_0_0_, contacttel1_.ID as ID1_2_1_, hobby3_.HOBBY_ID as HOBBY_ID1_3_2_, contact0_.BIRTH_DATE as BIRTH_DA2_0_0_, contact0_.FIRST_NAME as FIRST_NA3_0_0_, contact0_.LAST_NAME as LAST_NAM4_0_0_, contact0_.VERSION as VERSION5_0_0_, contacttel1_.CONTACT_ID as CONTACT_5_2_1_, contacttel1_.TEL_NUMBER as TEL_NUMB2_2_1_, contacttel1_.TEL_TYPE as TEL_TYPE3_2_1_, contacttel1_.VERSION as VERSION4_2_1_, contacttel1_.CONTACT_ID as CONTACT_5_2_0__, contacttel1_.ID as ID1_2_0__, hobbies2_.CONTACT_ID as CONTACT_2_1_1__, hobbies2_.HOBBY_ID as HOBBY_ID1_1_1__ from contact contact0_ left outer join contact_tel_detail contacttel1_ on contact0_.ID=contacttel1_.CONTACT_ID left outer join contact_hobby_detail hobbies2_ on contact0_.ID=hobbies2_.CONTACT_ID left outer join hobby hobby3_ on hobbies2_.HOBBY_ID=hobby3_.HOBBY_ID where contact0_.ID=?
01:23:58.099 [main] DEBUG o.s.o.h.HibernateTransactionManager - Initiating transaction commit
01:23:58.101 [main] DEBUG o.s.o.h.HibernateTransactionManager - Committing Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[org.pack.ch9.spring.transactions.hibernate.home.Contact#6], EntityKey[org.pack.ch9.spring.transactions.hibernate.home.ContactTelDetail#6], EntityKey[org.pack.ch9.spring.transactions.hibernate.home.ContactTelDetail#7]],collectionKeys=[CollectionKey[org.pack.ch9.spring.transactions.hibernate.home.Contact.contactTelDetails#6], CollectionKey[org.pack.ch9.spring.transactions.hibernate.home.Contact.hobbies#6]]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
01:23:58.103 [main] DEBUG o.s.jdbc.datasource.DataSourceUtils - Resetting read-only flag of JDBC Connection [com.mysql.jdbc.JDBC4Connection#2a685eba]
01:23:58.103 [main] DEBUG o.s.o.h.HibernateTransactionManager - Closing Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[org.pack.ch9.spring.transactions.hibernate.home.Contact#6], EntityKey[org.pack.ch9.spring.transactions.hibernate.home.ContactTelDetail#6], EntityKey[org.pack.ch9.spring.transactions.hibernate.home.ContactTelDetail#7]],collectionKeys=[CollectionKey[org.pack.ch9.spring.transactions.hibernate.home.Contact.contactTelDetails#6], CollectionKey[org.pack.ch9.spring.transactions.hibernate.home.Contact.hobbies#6]]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] after transaction
01:23:58.117 [main] DEBUG o.s.o.h.HibernateTransactionManager - Creating new transaction with name [org.pack.ch9.spring.transactions.hibernate.home.ContactService.saveContactInSteps]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
01:23:58.117 [main] DEBUG o.s.o.h.HibernateTransactionManager - Opened new Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for Hibernate transaction
01:23:58.117 [main] DEBUG o.s.o.h.HibernateTransactionManager - Preparing JDBC Connection of Hibernate Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
01:23:58.117 [main] DEBUG o.s.j.d.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/springorm]
01:23:58.127 [main] DEBUG o.s.o.h.HibernateTransactionManager - Exposing Hibernate transaction as JDBC transaction [com.mysql.jdbc.JDBC4Connection#1daf3b44]
01:23:58.127 [main] DEBUG o.s.o.h.HibernateTransactionManager - Found thread-bound Session [SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])] for Hibernate transaction
01:23:58.127 [main] DEBUG o.s.o.h.HibernateTransactionManager - Participating in existing transaction
01:23:58.127 [main] ERROR o.p.c.s.t.h.home.ContactService - Contact First name could not be saved !!
01:23:58.127 [main] ERROR o.p.c.s.t.h.home.ContactService - Contact Last name could not be saved !!
01:23:58.137 [main] INFO o.p.c.s.t.h.home.ContactService - Contact Birth Date saved successfully
01:23:58.138 [main] DEBUG o.s.o.h.HibernateTransactionManager - Initiating transaction commit
01:23:58.138 [main] DEBUG o.s.o.h.HibernateTransactionManager - Committing Hibernate transaction on Session [SessionImpl(PersistenceContext[entityKeys=[EntityKey[org.pack.ch9.spring.transactions.hibernate.home.Contact#6], EntityKey[org.pack.ch9.spring.transactions.hibernate.home.ContactTelDetail#6], EntityKey[org.pack.ch9.spring.transactions.hibernate.home.ContactTelDetail#7]],collectionKeys=[CollectionKey[org.pack.ch9.spring.transactions.hibernate.home.Contact.contactTelDetails#6], CollectionKey[org.pack.ch9.spring.transactions.hibernate.home.Contact.hobbies#6]]];ActionQueue[insertions=ExecutableList{size=0} updates=ExecutableList{size=0} deletions=ExecutableList{size=0} orphanRemovals=ExecutableList{size=0} collectionCreations=ExecutableList{size=0} collectionRemovals=ExecutableList{size=0} collectionUpdates=ExecutableList{size=0} collectionQueuedOps=ExecutableList{size=0} unresolvedInsertDependencies=null])]
Note - I have removed the #Transactional annotations from the methods as i am relying on proxy to achieve the same.
From the logs, it seems that the proxies are getting created but again as pointed out in the comment, will the 3 methods invoked from saveContactInSteps not have a transaction against them as mentioned in the documentation :
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation, in effect, a method within the target object calling another method of the target object, will not lead to an actual transaction at runtime even if the invoked method is marked with #Transactional. Also, the proxy must be fully initialized to provide the expected behaviour so you should not rely on this feature in your initialization code, i.e. #PostConstruct
Is there a way to get around this ? Is AspectJ the only solution ?

HttpRequestMethodNotSupportedException: Request method 'POST' not supported

Creating a unit test with MockMvc I am running into:
HttpRequestMethodNotSupportedException: Request method 'POST' not supported
Which causes the test case to fail expecting a '200' but getting a '405'. Some of the additional things you may see in the Junit are for Spring Rest Docs and can be ignored. Such as the #Rule or the .andDo() on the mockMvc Call. I have followed the following documentation Spring Rest Docs - Path Parameter and cannot seem to get it working.
Here is the Controller:
#RestController("/transferObjects")
public class TransferObjectController {
#RequestMapping(method=RequestMethod.GET, produces="application/json")
public List<TransferObject> getTransferObjects(){
// do some magic
return null;
}
#RequestMapping(value = "/{name}", method=RequestMethod.POST)
#ResponseStatus(HttpStatus.OK)
public void addTransferObject(#PathVariable("name")String name){
// do magic
}
#RequestMapping(value = "/{name}", method=RequestMethod.DELETE)
#ResponseStatus(HttpStatus.OK)
public void deleteTransferObject(#PathVariable("name")String name){
// do magic
}
Here is the Junit Class:
public class TransferObjectControllerTest {
#Rule
public RestDocumentation restDocumentation = new RestDocumentation("target/generated-snippets");
private MockMvc mockMvc;
#Before
public void setUp() throws Exception {
this.mockMvc = MockMvcBuilders.standaloneSetup(new TransferObjectController())
.apply(documentationConfiguration(this.restDocumentation))
.build();
}
#Test
public void testAddTransferObject() throws Exception {
this.mockMvc.perform(post("/transferObjects/{name}", "hi"))
.andExpect(status().isOk()).andDo(document("transferObject",
pathParameters(
parameterWithName("name").description("The name of the new Transfer Object to be created."))));
}
And here is the console while running the test:
11:20:48.148 [main] INFO o.s.w.s.m.m.a.RequestMappingHandlerAdapter - Looking for #ControllerAdvice: org.springframework.test.web.servlet.setup.StubWebApplicationContext#5ab785fe
11:20:48.205 [main] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Looking for exception mappings: org.springframework.test.web.servlet.setup.StubWebApplicationContext#5ab785fe
11:20:48.283 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Initializing servlet ''
11:20:48.307 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [servletConfigInitParams] PropertySource with lowest search precedence
11:20:48.307 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [servletContextInitParams] PropertySource with lowest search precedence
11:20:48.312 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [systemProperties] PropertySource with lowest search precedence
11:20:48.312 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Adding [systemEnvironment] PropertySource with lowest search precedence
11:20:48.313 [main] DEBUG o.s.w.c.s.StandardServletEnvironment - Initialized StandardServletEnvironment with PropertySources [servletConfigInitParams,servletContextInitParams,systemProperties,systemEnvironment]
11:20:48.313 [main] INFO o.s.mock.web.MockServletContext - Initializing Spring FrameworkServlet ''
11:20:48.313 [main] INFO o.s.t.w.s.TestDispatcherServlet - FrameworkServlet '': initialization started
11:20:48.318 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Unable to locate MultipartResolver with name 'multipartResolver': no multipart request handling provided
11:20:48.318 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using LocaleResolver [org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver#63238bf4]
11:20:48.318 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using ThemeResolver [org.springframework.web.servlet.theme.FixedThemeResolver#32b97305]
11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using RequestToViewNameTranslator [org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator#2d2e6747]
11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Using FlashMapManager [org.springframework.web.servlet.support.SessionFlashMapManager#417e7d7d]
11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Published WebApplicationContext of servlet '' as ServletContext attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.]
11:20:48.319 [main] INFO o.s.t.w.s.TestDispatcherServlet - FrameworkServlet '': initialization completed in 6 ms
11:20:48.319 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Servlet '' configured successfully
11:20:48.361 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - DispatcherServlet with name '' processing POST request for [/transferObjects/hi]
11:20:48.364 [main] DEBUG o.s.t.w.s.s.StandaloneMockMvcBuilder$StaticRequestMappingHandlerMapping - Looking up handler method for path /transferObjects/hi
11:20:48.368 [main] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
11:20:48.369 [main] DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
11:20:48.369 [main] DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
11:20:48.369 [main] WARN o.s.web.servlet.PageNotFound - Request method 'POST' not supported
11:20:48.370 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Null ModelAndView returned to DispatcherServlet with name '': assuming HandlerAdapter completed request handling
11:20:48.370 [main] DEBUG o.s.t.w.s.TestDispatcherServlet - Successfully completed request
It appears I was able to fix this problem.
Taking a closer look at the console while running the test I noticed:
Mapped "{[],methods=[GET],produces=[application/json]}" onto public java.util.List<common.to.TransferObject> sf.common.controller.TransferObjectController.getTransferObjects()
Mapped "{[/{name}],methods=[POST]}" onto public void sf.common.controller.TransferObjectController.addTransferObject(java.lang.String)
Mapped "{[/{name}],methods=[DELETE]}" onto public void sf.common.controller.TransferObjectController.deleteTransferObject(java.lang.String)
this shows that it is mapping the controller request mappings to the specific RequestMapping the method holds. #RestController("/transferObjects") is not actually defining the mapping as a parent. For me to do that I must include #RequestMapping("/transferObjects") underneath the #RestController.
So by changing the parent mapping I can now use the following test case:
#Test
public void testAddTransferObject() throws Exception {
this.mockMvc.perform(post("/transferObjects/{name}", "hi"))
.andExpect(status().isOk()).andDo(document("transferObject",
pathParameters(
parameterWithName("name").description("The name of the new Transfer Object to be created."))));
}

Sharing transaction with AbstractRoutingDataSource

I've a problem very close to this one Sharing a transaction while using AbstractRoutingDataSource to switch datasources but I'm not able to solve using the accepted answer. I've a transactional method who have to write the same entity into two different datasource in transactional mode. When transaction commit I've a
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (VETO_PROD.SYS_C0013988) violated
This is my Transalctional method:
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW)
public ContactTypeJson definisciNuovaContactType(String descrizione) throws Exception {
String functionCode = RandomStringUtils.randomAlphanumeric(5).toUpperCase();
LOGGER.debug("Ho generato la functionCode[" + functionCode + "]");
while (!isContactTypeAvailable(functionCode) || !notificatorService.isFunctionCodeAvailable(functionCode)) {
LOGGER.debug("La functionCode[" + functionCode + "] e' gia' in utilizzo, genero una nuova...");
functionCode = RandomStringUtils.randomAlphanumeric(5).toUpperCase();
LOGGER.debug("...la nuova functionCode generata e' [" + functionCode + "]");
}
ContactType contactType = new ContactType();
contactType.setName(functionCode);
contactType.setDescription(descrizione);
notificatorService.insertNewFunction(functionCode, descrizione);
entityManagerFRVP0.flush();
entityManagerFRVP0.clear();
VetrinaContextHolder.setTargetDataSource(VetrinaToolConstants.FRVP_DATASOURCE);
entityManagerFRVP0.persist(contactType);
entityManagerFRVP0.flush();
entityManagerFRVP0.clear();
VetrinaContextHolder.setTargetDataSource(VetrinaToolConstants.PWVP_DATASOURCE);
ContactType contactType1 = new ContactType();
contactType1.setName(functionCode);
contactType1.setDescription(descrizione);
entityManagerFRVP0.persist(contactType1);
VetrinaContextHolder.clearTargetDataSource();
ContactTypeToJsonConverter converter = new ContactTypeToJsonConverter();
return converter.convert(contactType);
}
This is the JPA log:
2013-07-15 10:47:59,570 DEBUG [sql] 2013-07-15 10:47:59.569--ServerSession(26361419)--Connection(16434777)--Thread(Thread[[ACTIVE] ExecuteThread: '18' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--SELECT VET_SEQ_CONTACT_TYPE.NEXTVAL FROM DUAL
2013-07-15 10:47:59,581 DEBUG [sql] 2013-07-15 10:47:59.58--ClientSession(21299255)--Connection(17900213)--Thread(Thread[[ACTIVE] ExecuteThread: '18' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--INSERT INTO S_VET_CONTACT_TYPE (ID, DESCRIPTION, NAME, FASEDIDEFAULT_ID) VALUES (81, Prova doppione, 16XOV, NULL)
2013-07-15 10:47:59,596 DEBUG [sql] 2013-07-15 10:47:59.595--ClientSession(21299255)--Connection(17900213)--Thread(Thread[[ACTIVE] ExecuteThread: '18' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--SELECT VET_SEQ_CONTACT_TYPE.NEXTVAL FROM DUAL
2013-07-15 10:47:59,601 DEBUG [sql] 2013-07-15 10:47:59.6--ClientSession(21299255)--Connection(17900213)--Thread(Thread[[ACTIVE] ExecuteThread: '18' for queue: 'weblogic.kernel.Default (self-tuning)',5,Pooled Threads])--INSERT INTO S_VET_CONTACT_TYPE (ID, DESCRIPTION, NAME, FASEDIDEFAULT_ID) VALUES (82, Prova doppione, 16XOV, NULL)
This the stack:
2013-07-15 10:47:59,421 DEBUG [WebLogicJtaTransactionManager] Creating new transaction with name [com.intesasanpaolo.frvp0.alten.vetrinatool.service.console.ConsoleServiceImpl.definisciNuovaContactType]: PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT; ''
2013-07-15 10:47:59,430 DEBUG [EntityManagerFactoryUtils] Opening JPA EntityManager
2013-07-15 10:47:59,430 DEBUG [EntityManagerFactoryUtils] Registering transaction synchronization for JPA EntityManager
2013-07-15 10:47:59,483 DEBUG [TransactionalRepositoryProxyPostProcessor$CustomAnnotationTransactionAttributeSource] Adding transactional method 'findOne' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly; ''
2013-07-15 10:47:59,483 DEBUG [DefaultListableBeanFactory] Returning cached instance of singleton bean 'transactionManager'
2013-07-15 10:47:59,483 DEBUG [WebLogicJtaTransactionManager] Participating in existing transaction
2013-07-15 10:47:59,483 DEBUG [EntityManagerFactoryUtils] Opening JPA EntityManager
2013-07-15 10:47:59,483 DEBUG [EntityManagerFactoryUtils] Registering transaction synchronization for JPA EntityManager
2013-07-15 10:47:59,542 DEBUG [AnnotationTransactionAttributeSource] Adding transactional method 'insertNewFunction' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2013-07-15 10:47:59,543 DEBUG [DefaultListableBeanFactory] Returning cached instance of singleton bean 'transactionManager'
2013-07-15 10:47:59,543 DEBUG [WebLogicJtaTransactionManager] Participating in existing transaction
2013-07-15 10:47:59,543 DEBUG [DefaultListableBeanFactory] Returning cached instance of singleton bean 'transactionManager'
2013-07-15 10:47:59,543 DEBUG [WebLogicJtaTransactionManager] Participating in existing transaction
2013-07-15 10:47:59,549 DEBUG [TransactionalRepositoryProxyPostProcessor$CustomAnnotationTransactionAttributeSource] Adding transactional method 'save' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
2013-07-15 10:47:59,549 DEBUG [DefaultListableBeanFactory] Returning cached instance of singleton bean 'transactionManager'
2013-07-15 10:47:59,550 DEBUG [WebLogicJtaTransactionManager] Participating in existing transaction
2013-07-15 10:47:59,600 DEBUG [EntityManagerFactoryUtils] Closing JPA EntityManager
2013-07-15 10:47:59,600 DEBUG [EntityManagerFactoryUtils] Closing JPA EntityManager
2013-07-15 10:47:59,600 DEBUG [WebLogicJtaTransactionManager] Initiating transaction commit
2013-07-15 10:47:59,827 DEBUG [DispatcherServlet] Handler execution resulted in exception - forwarding to resolved error view: ModelAndView: reference to view with name 'jsonView'; model is {hasErrors=true, errorCode=GEN_EX, errorMessages=Errore generico}
org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is weblogic.transaction.RollbackException: Unexpected exception in beforeCompletion: sync=org.eclipse.persistence.transaction.JTASynchronizationListener#2f0af4
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: ORA-00001: unique constraint (VETO_PROD.SYS_C0013988) violated
Error Code: 1
Call: INSERT INTO S_VET_CONTACT_TYPE (ID, DESCRIPTION, NAME, FASEDIDEFAULT_ID) VALUES (82, 'Prova doppione', '16XOV', NULL)
Query: InsertObjectQuery(ContactType [id=82, name=16XOV, description=Prova doppione, fasiAssociate={[]}, faseDiDefault=null])
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1014)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:387)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy310.definisciNuovaContactType(Unknown Source)
at com.intesasanpaolo.frvp0.alten.vetrinatool.mvc.console.controller.CreaContactTypeController.creaNuovaContactType(CreaContactTypeController.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
I'm using WebLogic 10.3.5 with XA datasources and org.springframework.transaction.jta.WebLogicJtaTransactionManager
Any idea?
You are violating a unique constraint. I assume you have one defined on the Contact name, so you cannot insert two contacts with the same name.
Trying to switch the connection under a DataSource on the fly seems like a very, very, bad idea. Instead you should have two persistence units, one going to one database, and one going to the other.
You may also want to investigate EclipseLink's data partitioning, or composite persistence units.
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Partitioning
http://wiki.eclipse.org/EclipseLink/Examples/JPA/Composite

Resources