how to manually force commit #Transactional spring boot? - spring-boot

serviceA.save(x);
syncToOtherServiceWithAPI(x.id);
// otherservice
//fetchA(x.id) - but still haven't got the newest data because before not committed
how to get newest/updated data on other service?

Technically no you cannot commit manually while using #Transactional, for this, you can check TransactionTemplate to do it programmatically.
If you are trying to commit transactionally inside your other transaction, then use #Transactional (propagation = Propagation.REQUIRES_NEW)

Related

JPA transactional proxy within a thread issue

In my Controller I have injected (#Autowired) this Service, which implements Runnable (I need multi-threading) and I call it like so:
Thread t = new Thread(service);
t.start();
t.join();
Then, in my Service's run() I call this Repository (simple JPARepository), which is injected in Service also with #Autowired:
repository.save(someEntity);
The problem is that it doesn't persist the entity with id=1. The transactional proxy (and Hibernate connection pool) is initialized after the unsuccessful saving of the first entity. After that, it works fine.
Can anyone point me to the right direction with my issue: how to force the Thread to initialize the Hibernate transactional proxy before persisting the first entity?
You should consider to start the thread after Spring context is refreshed. This is safer because all your beans may be in an inconsistent state.
#EventListener(ContextRefreshedEvent.class)
public void handleContextStart() {
// ...
}

Include resources in transactions

I am trying to find a way to make sure custom resources like files that are created within a transaction (using #Transactional) are cleaned up in case that transaction rolls back. I tried implementing a custom TransactionManager but could not find a way to register it but I do know for example spring-rabbitmq has its own transaction manager that taps into the existing transactions. Any ideas how to solve this?
Not sure that I got you correctly, but according to tag name you are using spring.
You can handle it via Spring AOP.
You should just create your own annotation(e.g. YourOwnTransactional) , and check it.
If annotation exists, you can just call like :
#Around(#anyPublicMethod() && #annotation(YourOwnTransactional))
public void aroundAddAdvice(ProceedingJoinPoint pjp){
try{
pjp.proceed();
}catch(YourException e){
//rollback
}
}
edited.

Commiting transaction within test with Spring test

I am testing my repository for update operation
#Test
public void updateStatusByEmailWithEmailCustomer()
{
customerQuickRegisterRepository.save(standardEmailCustomer());
assertEquals(CUST_STATUS_EMAIL,customerQuickRegisterRepository.findByEmail(CUST_EMAIL).getStatus());
customerQuickRegisterRepository.updateStatusByEmail(CUST_EMAIL,STATUS_EMAIL_VERFIED );
assertEquals(STATUS_EMAIL_VERFIED,customerQuickRegisterRepository.findByEmail(CUST_EMAIL).getStatus());
}
In the test case i saving my entity with default status and after that i am changing it to other using updateStatusByEmail(CUST_EMAIL,STATUS_EMAIL_VERFIED ) but still next assert statement is failing, this is due to fact that the updates during the test execution are commited after completion of test....Is there any way that I can commit my changes within the test?
You can likely get by with flushing the underlying Hibernate Session, as this will push your changes to the underlying tables in the database (within the current test-managed transaction).
Search for "false positives" in the testing chapter of the Spring reference manual for details.
Basically, you will want to call flush() on the current Hibernate Session after your update call and before the corresponding assertion.
If that does not solve your problem, with Spring Framework 4.1, you can use the new TestTransaction API for programmatic transaction management within tests.
Regards,
Sam (lead of the spring-test module)

XA transactions and message bus

In our new project we would like to achieve transactions that involve jpa (mysql) and a message bus (rabbitmq)
We started building our infrastructure with spring data using mysql and rabbitmq (via spring amqp module). Since rabbitMq is not XA-transactional we configured the neo4j chainedTransactionManager as our main transactionManager. This manager takes as argument the jpa txManager and the rabbitTransactionManager.
Now, I do get the ability to annotate a service with #Transacitonal and use both the jpa and rabbit inside it. If I throw an exception within the service then none of the actions actually occur.
Here are my questions:
Is this configuration really gives me an atomic transaction?
I've heard that the chained tx manager is not using a 2 phase commit but a "best effort", is this best effort less reliable? if so how?
What the ChainedTransactionManager does is basically start and commit transactions in reverse order. So if you have a JpaTransactionManager and a RabbitTransactionManager and configured it like so.
#Bean
public PlatformTransactionManager transactionManager() {
return new ChainedTransactionManager(rabbitTransactionManager(), jpaTransactionManager());
}
Now if tha JPA commit succeeds but your commit to rabbitMQ fails your database changes will still be persisted as those are already committed.
To answer your first question it doesn't give you a real atomic transaction, everything that has been committed prior to the occurence of the Exception (on committing) will remain committed.
See http://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/transaction/ChainedTransactionManager.html

Globally disable EntityManager cache in jboss

Is it possible to disable caching with EntityManager in some jboss config?
I'll explain. I have some final "ear" of our product that is using EntityManager through hibernate (something like this, i an newbie to this) and I need to test some behaviour. The easy way for me is to change(remove, create) state of entities direct in the database. But after i did this, the application remain to find old values for some time. I've read about some jboss cache, that is used for entity-manager.
So, for testing, i want to disable EntityManager cache, but it can not be disabled on application-level, only on jboss-level.
In brief: i need application always to reload actual entity state, because it can be edited in database with come other application. And its impossible to disable caching on application-level(hibernate.xml and other)
PS: jboss 4.2.3, ejb3, hibernate3
The cache you are referring to is probably the PersistenceContext. It cannot be disabled. You can only tweak it's scope. In a Java EE environment, the scope of the persistence context is the transaction per default. So if you need for some changes to take effect immediately, you can extract these changes (including fetching the entities in question) into a separate method and annotate it to require a new transaction:
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
Once the method returns, all changes are committed.
You could also use bean managed transactions, so you can control the commit yourself. For this, annotate your bean with #TransactionManagement( TransactionManagementType.BEAN ) and use UserTransaction:
#Resource
private UserTransaction tx;
...
tx.begin();
//do stuff
tx.commit();

Resources