I have an spring advice method which logs the exception after a method (in DAO layer) throws an exception. The DB query are handled at DAO classes.
while running the code my service method (S1), which interns call DAO layer method (D1) to execute query.
test case: DB is up and code execute normally. in second run, meanwhile DB is down, and calls doesn't reach to DAO layer and exception throws (Connect excpetion) at service layer (S1) itself; hence advise not able to log the excpetion because calls is not reached to DAO.
how the jdbc connections are managed by server (tomcat)?
Related
Problem:
Spring boot service using MVCS architecture. I am using Spring AOP advice (around advice) for all functions present in any class in repository directory. So for example when jpa save method is called, the around advice is triggered.
Now, Here is how things get called when no exception occurs.
CONTROLLER -> SERVICE LAYER -> call to repository layer function triggers advice function which allows join point to proceed -> REPOSITORY LAYER -> around advice -> and everything executes fine.
Now, Here is the flow when exception is thrown by the controller advice function.
CONTROLLER -> SERVICE LAYER -> call to repository layer function triggers advice function which allows join point to proceed -> REPOSITORY LAYER -> some DB exception occurs (for example trying to set a database attribute with NON NULL constraint to NULL) -> back to controller advice, it catches the exception then throws a custom checked exception to service layer and than going through service layer and then controller where the exception is handled.
The problem is that service layer doesn't know about controller advice (it acts like a proxy) and thinks that repository layer won't throw any exception since it doesn't declare throws in its methods signature (for example the default save method).
So the exception that reaches the controller is not the one which is thrown by the controller advice functions. In fact Java wraps that exception inside UndeclaredThrowableException.
One way to deal with this situation is to check ex.getCause() and get the exception which java wrapped in UndeclaredThrowableException.
Another is to declare throws in the repository methods signature so that the service layers can know about the repository function throwing exception. (But this is not possible for default implementation provided by jpa - like the save function - atleast not without overriding the save function) and this I don't want to do because there are a lot of jpa inbuilt functions to override.
Any elegant solution/suggestion to the problem ?
You cannot magically violate JVM restrictions about throwing undeclared checked exceptions. Therefore, you will have to
throw a checked exception which has actually been declared in the intercepted target method, or
throw a runtime exception instead, optionally wrapping it around the checked exception you want to throw.
Sorry, I cannot change the JVM for you. You need to play by its rules.
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.
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
I want to test the integration of Spring and Activiti, then I stuck with confusing problem. I have a workflow with 2 service task (using jpa repository saveAndFlush method to update database) A and B
In the service A, I actively throw a new Exception , then the transaction rollbacks, and the flow stops. Well, it's okay.
However, how can I rollback the service A only and the flow continue to service B?
Because if service A throws Exception, the flow will be stopped, and if Exception is caught ( then the flow continues), service A will not rollback.
I use JPA Repository to automatically handle transaction, so change to manual mode will take a lot of efforts now.
Probably you need a new transaction for every service in the flow and catch all exception.
Put a layer between your service tasks A,B and your process, let's make its name TransactionService. This service should trigger your service methods. Also those service methods should use new transactions for their operations(you can use #Transactional annotation). In TransactionService don't do anything, just trigger them and wrap them in try catch blocks.
As a result of them you can catch the exception and make it flow to the next task and doesn't care about rollback because after an exception it will be rolled back automatically.
I am using Spring Hibernate integration in my application and DAO classes are extending HibernateDaoSupport.
Suppose I save some object using the code
getHibernateTemplate().save(object);
As Spring Hibernate integration doesn't mandate to write try-catch block, but suppose if any exception is thwron while saving that object.
Then what is the best way to handle it? I means should I catch it in the service layer and wrap it in some user defined excpetions.
Do I need to write try-catch in DAO layer method itself in case I want to log which method in DAO throws exception?
I have never used HibernateDaoSupport or Hibernate Template before so ignorant about exception handling. Please provide me your valuable inputs
The idea behind Spring using RuntimeException is that generally there are different types of exception:
Exceptions that you want to recover from (such as a DuplicateKeyException if a record that you're trying to insert already exists or the more general DataIntegrityViolationException if there was a DB constraint that was violated as a result of user input)
Exceptions that you can't recover from (the database is down)
For the first case, you may well handle the exception (either through a custom business exception, so that the view layer can redirect to the input page and provide a meaningful message)
For the second case, it would be easier to let the exception bubble up and have it handled by a generic exception handler that then displays a generic error page to the user. For this scenario it doesn't make sense to wrap the exception in a custom exception as you won't be able to recover. A blown up DB tends to be fatal.
So what I would do:
try {
getHibernateTemplate().save(object);
} catch (DataIntegrityViolationException dive) {
throw new BusinessValidationException(dive, "You've got the data wrong");
}
Spring exception hierarchy is well documented.
Usually you can't do much if you have a data access exception, because in the working system this may be caused by the shortage of diskspace on the DB server, or network connection problems etc.
Such exceptions are usually need to be logged and investigated as soon as possible.
There some recoverable errors, they can be handled with spring exception hierarchy, but imho most of them should be avoided during the developing phase, so your web server should validate as many things as possible, before it goes to the db.
If you want to set the exception logging see the similar questions:
Exception handler in Spring MVC
Spring MVC Best Practice Handling Unrecoverable Exceptions In Controller