method(){
try{
some code..
}
catch(Exception e)
{
throw new userDefineException();
}
}
// while calling the above method from the java client I am gettine remote exception but i am expecting to get UserdefineException.
EJB container will wrap undeclared (system) exceptions in RemoteException (or EJBException for local views). To avoid this, you should either:
Change UserDefineException to extend Exception rather than RuntimeException, and add UserDefineException to the throws clause of the remote interface.
Annotation UserDefineException with #ApplicationException, or specify it as <application-exception>com.example.UserDefineException</application-exception> in ejb-jar.xml.
Related
I use spring boot 2.2.
In a method with transactional anocation, when I save via repository if there is no error, I want to send a message with rabbit mq.
How to be sure there is no error with repository?
#Transactional
public void save(CreditEvent creditEvent) {
repository.save(creditEvent);
//no error send message
}
if there is an error when sending message, I don't want to rollback saving operation.
Although it's Transactional and JPA, still it's a java method which if save failed then unchecked DataAccessException exception will be thrown and flow won't continue to send message.
class is a runtime exception, there is no need for user code to catch it or subclasses if any error is to be considered fatal (the usual case).
#Transactional
public void save(CreditEvent creditEvent) {
try {
repository.save(creditEvent);
//no error send message}
catch {
// send message
// rethrow error
}
}
I couldn't find a good solution: In my Spring Boot app, as an #ExceptionHandler method, I need to define a handler not for a specific exception, but for any exception caused by a specific exception (i.e. a wrapped exception).
Example: Sometimes I get this:
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:541) ~[spring-orm-5.1.4.RELEASE.jar:5.1.4.RELEASE]
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746) ~[spring-tx-5.1.4.RELEASE.jar:5.1.4.RELEASE]
... 121 common frames omitted
Caused by: custom.TechRoleException: My custom TechRoleException
at myapp.method1[..]
at myapp.methodOuter[..]
My custom TechRoleException is an exception I throw inside some Hibernate EventListener's pre-update method, and the direct exception is that Persistence couldn't occur.
However, the following method that tries to use my custom exception is never reached:
#ControllerAdvice
public class GlobalExceptionHandler {
#ExceptionHandler(TechRoleException.class)
public String techRoleException(HttpServletRequest request, Exception ex) {
System.out.println("Got here");
return "home";
}
}
Here's a similar thread where the answer is wrong and didn't answer this question:
#ExceptionHandler for Wrapped Exception / getCause() in Spring
Maybe something like that?
#ExceptionHandler(Exception.class)
public String techRoleException(HttpServletRequest request, Exception ex) {
if(ex instanceof TechRoleException) {
System.out.println("Got here");
return "home";
} else {
throw ex; //or something else
}
}
My final working answer is to handle a General Exception, and then use Apache ExceptionUtils.getRootCause() to detect the specific Caused-By I'm looking for within this general handler.
(Other specific Exceptions won't come to this method if they have their dedicated Handlers. But if there's no dedicated Handler, the exception will come here.) This is the only way to detect some target Caused-By.
#ExceptionHandler(Exception.class)
public String handleGeneralException(HttpServletRequest request, Exception ex) {
Throwable rootCause = ExceptionUtils.getRootCause(ex);
if (rootCause != null && "com.myapp.TechRoleException".equals(rootCause.getClass().getName())
{
//... handle this Caused-By Exception here
// ...
}
// All other exceptions that don't have dedicated handlers can also be handled below...
// ...
}
My Grails Service calls a plugin which throws a runtime exception. In my case, I don't care about the exception, so it is swallowed.
MyGrailsService {
def myMethod {
...
try {
//callPlugin
} catch (Exception ex) {
...
}
}
}
All fine, exception is caught and processing continues. However, in my Controller, I have a catch (Throwable t) block, which I am not expecting to get executed because the exception is swallowed. It turns out the catch (Throwable t) block is executed because Grails throws a a org.springframework.transaction.UnexpectedRollbackException
which of course I do not want it to do. I guess I am getting this because the exception the plugin throws is runtime, so Grails rolls back the Transaction.
I don't want this UnexpectedRollbackException being thrown.
Any tips?
What i would have done is
class MyService{
static transactional = false
def myMethod {
...
try {
//callPlugin
} catch (Exception ex) {
...
}
}
#Transactional(readOnly = true)
def someMethod {
// Some code here
}
}
The above code will make all the methods in the service non transactional and we will explicitly make the methods transactional which we want.
However once more thing can be a point to be taken care of, the method of the plugin you are calling, that method can itself be a transactional method, which on error may get rolled back and throw a UnexpectedRollbackException. So you have to check it once if the plugin method is transactional.
We have a Spring Transaction rollback issues, where rollback doesn't seems to be working.
Within my service layer method which is annotated with #Transactional I call three different DAOImpl classes to insert 3 records. The middle insert do a get from a 4th table to populate a description field but this get failed. I expect the first insert to rollback but it doesn't seems to be happening.
Few Points:
The 'Get' method throws a Runtime Exception
We are using org.springframework.jdbc.datasource.DataSourceTransactionManager and MySQL datasource defined in applicationContext.xml. Beans are created in Beans.xml which is imported into ApplicationContext.xml
No #Transactional annotation in DAO layer
We have used <tx:annotation-driven transaction-manager="transactionManager"/> again in applicationContext.xml
We are using Spring 3.1
UPDATE:
Code snippets....
Service Class- This is somthing similar to what I have .... I tested with and without #Autowired. The transaction enable method is called within the service class.
public class CustomerService {
//#Autowired
CustomerOrderDAO customerOrderDAOImpl;
//#Autowired
CustomerItemDAO customerItemDAOImpl;
//#Autowired
CustomerPromotionDAO customerPromotionDAOImpl;
//#Autowired
PromotionDAO promotionDAOImpl;
//other variables
public CustomerOrder handleIncomingOrders(CustomerOrder customerOrder) {
try {
saveOrderDetails(customerOrder);
.....
return customerOrder;
} catch (Exception e) //TO-DO catch proper exception
{
//Send error response
.......
return customerOrder;
}
}
#Transactional
public void saveOrderDetails(CustomerOrder customerOrder) throws Exception {
customerOrderDAOImpl.create(customerOrder);
....
while (promotionsIterator.hasNext()) {
customerPromotion.setPromotionName(promotionDAOImpl.getName(customerOrder.getPromotionId));
customerPromotionDAOImpl.create(customerPromotion);
}
......
while (customerItemIterator.hasNext()) {
customerItemDAOImpl.create(customerItem);
}
}
}
Any idea?
Thanks.
The default behaviour of #Transactional is that transactional behaviour is added with a proxy around the object (the CustomerService in your example). From the reference docs (scroll down):
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.
In your example, an external call to the handlingIncomingOrders() passes through the proxy and hits the target object (an instance of the CustomerService). However, the subsequent call to saveOrderDetails() is a normal method call inside the target object, thus the transactional behaviour in the proxy is never invoked. However, if the saveOrderDetails() was called from another class, you will find that the transactional behaviour will work as expected.
The solution in your case would be calling saveOrderDetails(customerOrder); as proxyBean.saveOrderDetails(customerOrder); Where proxybean is the Object on whichhandleIncomingOrders` is being called.
If CustomerService is singleton (Defualt scope) it can be as simple as adding below code to the Service class. (adding a self reference as autowired)
//#Autowired
CustomerService customerService; // As this is injected its a proxy
and in the Method use it as
public CustomerOrder handleIncomingOrders(CustomerOrder customerOrder) {
try {
customerService.saveOrderDetails(customerOrder);
.....
return customerOrder;
} catch (Exception e) //TO-DO catch proper exception
{
//Send error response
.......
return customerOrder;
}
}
If its scope is Prototype the one of possible simple solution will be as follows.
public CustomerOrder handleIncomingOrders(CustomerOrder customerOrder, CustomerService customerService) {
try {
customerService.saveOrderDetails(customerOrder);
.....
return customerOrder;
} catch (Exception e) //TO-DO catch proper exception
{
//Send error response
.......
return customerOrder;
}
}
And where you are calling handleIncomingOrders use changes suggested in below code.
bean.handleIncomingOrders(customerOrder); //Suppose this is old code
Change it to
bean.handleIncomingOrders(customerOrder, bean);// THough it appears as we are sending reference to `THIS` as parameter whcihc can be unnecessary, in case of `Proxy`while inside your method `this` and `Passed reference` will point to different Obejects.
I have a WebSphere Portal server that houses portlets. The portlets make remote calls to ejbs running on WAS. Both the portal server and the WAS are running on the local machine. The WAS starts up properly, but on trying to start up the portal server, it throws the following error:
nested exception is: java.lang.NullPointerException at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:286)
On looking up the source in spring, I find the method definition:
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
InjectionMetadata metadata = findAutowiringMetadata(bean.getClass());
try {
metadata.injectMethods(bean, beanName, pvs);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Autowiring of methods failed", ex);
}
return pvs;
}
Since the error is in spring source code and not my code, how should I start debugging it?