Commiting transaction within test with Spring test - spring

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)

Related

Why spring transactional executes code after repository save exception?

Using the annotation #Transactional spring executes the function past the repository save error to the following lines that shouldn't have been executed!!
Example: Using #Transactional on method
iEmployeeRepository.save(employee); <<-- Error occurs here
System.out.println("Hello"); <<-- This line still gets executed
I know #Transactional behaviour doesn't need a save, it automatically updates the ORM entity, according to this behaviour it looks like its running all the code and executes save repository by itself after all function code has run.
How can make sure #Transactional stop executing code when an error occurs when save repository is called?
save doesn't throw an exception. Due to JPAs write cache SQL statements are moved back as far as possible, which often mean to the end of the transaction, at which time all the collected changes will be flushed to the database. Any exceptions caused by that interaction will be raised at that time only.
This is JPA behaviour and independent of Spring.
You can avoid this by using JpaRepository.saveAndFlush(..)
This will force a flush right after the save and thereby trigger all errors early.

Spring Transaction - Do not rollback for error under specific method

I have a Spring Boot application in which a service is responsible to create a Business Entity. For simplicity, let's consider:
create(Object toCreate) {
validationService.validate(toCreate);
Object created = repository.save(toCreate);
notificationService.notify(created);
}
Business has changed and now I would like the creation to not fail if notification fails.
I therefore wrapped the notify() method in a try-catch block that only logs the error (which is a RuntimeException).
However when tested, a transaction rollback error was thrown, saying the connection was closed. I do not want any rollback, especially since the NotificationService does not modify the database.
How can I tell Spring that any exception happening in the NotificationService is fine and does not require a rollback? I tried annotating the class/method with #Transactional(propagation=NEVER) but got existing transaction found for transaction marked with propagation 'never'
Perhaps refactoring your code would help better than the introduction of more complex transaction handling.
Assuming your #Transactional is on the create() method, we can see that you have:
Pre-persistence business logic
Persistence logic
Post-persistence business logic
It depends on your use-case, but I would not expect pts. 1 & 3 to contain persistence logic. If that is the case, you could extract your persistence logic in its own service that would itself be a transaction, not the parent.
If you have the need for a transaction in those steps, you could also extract them in their own transaction.
Other leads might be:
The default rollback behavior is for runtime unchecked exceptions. You could use checked exceptions to avoid the rollback.
If your notification is separate from persistence and you do not care about the transaction, you could make it an asynchronous call (e.g. with #Async). It would be scheduled outside of the transaction in its own context.
You can use the option norollbackfor of #Transactional so you have to specify an exception class not the service and when an error occurs in notifications try to throw a specifc error which would not cause a rollback.

TransactionalEventListener won't kick in

I have a problem with #TransactionalEventListener.
Given:
Kotlin 1.3.50
Spring Webflux
Spring Data
Hibernate 5
Postgres JDBC (not RDBC!)
What happens:
Request to controller was made.
Service did some job within method marked as #Transactional an event and published event.
Response returned to client
Event listener marked as #Async, #TransactionalEventListener and #Transactional doesn't kick in.
What I did:
I have debugged into service method which publishes an event to find out whether an actual transaction is in progress with the help of some static utility method I don't remember, which told me what I suspected - it is in progress.
Then I enabled debug output to see log saying: No transaction is in progress. Discarding event.
I mean, both publishing and consuming sides do have annotation #Transactional on them. No alterations to default params of annotations were made.
I have found similar situation in this question question but no one answered that.
Also, I have read an article at dzone but there seems to be no mentioning of my case.
Workaround:
I can avoid this by either replacing #TransactionalEventListener to #EventListener (alas, remove transaction bound processing) or by changing param fallbackExecute to true which effectively is the same as first solution.
Suspected parties:
Possibly absence of reactive transaction manager in an webflux environment could be the case? And some weird bug not accounting JpaTransactionManager?

WebSphere insert/update statements with SQL-SERVER hangs with REQUIRES_NEW propagation

We are facing an issue in our spring batch application when we are deploying the application on WebSphere.
Example: One class contains parent() method and Second class contains child() method, where child method requires a new transaction. After execution of the methods when transaction is committed the commit routine hangs and nothing happens further.
#Transactional //using current transaction
public void parent(){
child();
}
#Transactional(propagation=REQUIRES_NEW) //creates new transaction
public void child(){
//Database save statements including update, insert and deletes
}
This issue only persists in WebSphere and code works fine on our local machine where we are using tomcat as web container.
WebSphere logs/stacktrace shows that the WebSphere prepared statement keeps on waiting for the response from the database. At the same time update and inserts are locked out on the affected tables i.e. if we run an insert or update query manually on the affected table the query doesn't execute.
We are using Spring JPA for data persistence and Spring’s JpaTransactionManager for transaction management and MSSQLServer database.
Is it that WebSphere does not support creating new transaction from existing transaction?
Yes, the pattern you are describing is supported by WebSphere Application Server. Given that this involved locked entries within the database, you might be running into a difference between the application servers in which transaction isolation level is used by default. In WebSphere Application Server, you get a default of java.sql.Connection.TRANSACTION_REPEATABLE_READ for SQL Server, whereas I think in most other cases you end up with a default of java.sql.Connection.TRANSACTION_READ_COMMITTED (less locking). If the default value is the problem, you can change it on the data source configuration.
If you are using WebSphere Application Server Liberty, then the default isolation level can be configured in server.xml as a property of the dataSource element, like this,
<dataSource isolationLevel="TRANSACTION_READ_COMMITTED" jndiName=...
If you are using WebSphere Application Server traditional, then the default isolation level can be configured as the webSphereDefaultIsolationLevel custom property, which can be set to the numeric value of the isolation level constant on java.sql.Connection (value for TRANSACTION_READ_COMMITTED is 2).
See this linked article for the steps of doing so via the admin console.

TransactionManagementType.CONTAINER vs TransactionManagementType.BEAN

what is the difference between TransactionManagementType.CONTAINER and TransactionManagementType.BEAN
as Im using TransactionManagementType.CONTAINER in all of my EJBs and when ever the multiple instances of database is used, It throws an error which gets resolved if i change it to TransactionManagementType.BEAN
I want to know what are the advantages and disadvantages and how it gets effected if I change it to TransactionManagementType.BEAN
ERROR:
Error updating database. Cause: java.sql.SQLException: javax.resource.ResourceException:
IJ000457: Unchecked throwable in managedConnectionReconnected() cl=org.jboss.jca.core.
connectionmanager.listener.TxConnectionListener#680f2be0[state=NORMAL managed
connection=org.jboss.jca.adapters.jdbc.local.LocalManagedConnection#7ba33a94 connection
handles=0 lastReturned=1495691675021 lastValidated=1495690817487
lastCheckedOut=1495691675018 trackByTx=false pool=org.jboss.jca.core.connectionmanager.
pool.strategy.OnePool#efd42c4 mcp=SemaphoreConcurrentLinkedQueueManagedConnectionPool
#71656eec[pool=FAQuery] xaResource=LocalXAResourceImpl#4c786e85
[connectionListener=680f2be0 connectionManager=5c3b98bc warned=false
currentXid=null productName=Oracle productVersion=Oracle Database 12c
Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options
jndiName=java:/FAQuery] txSync=null]
TransactionManagementType.CONTAINER
You let the container itself manage transactions(container will commit and rollback). You can control behavior of your transactions (more precisely transaction propagation) by annotating methods with #TransactionManagementAttribute and specifying one of the attributes from TransactionAttribute Types.
TransactionManagementType.BEAN
You have to do transaction demarcation (start, commit, rollback) explicitly yourself, by obtaining UserTransaction interface.
#Resource
UserTransaction ut;
public void method(){
ut.begin();
... // your business logic here
ut.commit(); // or ut.rollback();
}
Note that you have to either commit and rollback before you exit the same method which stated the transaction for Stateless and Message Driven Beans, but it is not required for Stateful bean.
Regarding your question, advantage of BMT is that scope of the transaction can be less than scope of the method itself, i.e explicit control of the transaction.
You would most probably use CMT, BMT is required only in some narrow corner cases to support specific business logic.
Another advantage or use case of BMT is if you need to use Extended Persistence Context Type, which can be supported in BMT with Stateful Session Beans.
Regarding your specific problem, without seeing any bean code or error messages, this is probably what is happening: if you have more databases then each database and its corresponding driver must be able to join an existing transaction, otherwise you will get a specific detailed error.
If you use TransactionManagementType.BEAN the bean is required to start a brand new transaction. Which means you are not joining an existing transaction, and each database operations begin and commit independently from each others.
You can achieve the same effect by leaving TransactionManagementType.CONTAINER and annotating your method with REQUIRES_NEW, provide of course you are calling each EJB trough the corresponding proxy/interface.
So it is not correct to put it like BEAN vs CONTAINER, but rather you have to made some design choice and annotate your methods accordingly.
As requested for a method marked with one of the following:
REQUIRES_NEW existing transactions gets suspended, and the method runs under a brand new transaction
REQUIRED is the default behavior, if a transaction exists it is reused by the method, otherwise gets created and the method runs in it

Resources