I am new to JBoss. As part of My Application I am using JBoss.We are also using EJB's as a part of the project also. A exception like StaleObjectStateException is raised . So , the EJB uses this exception to rollback a transaction. So, Please tell me how to stop StaleObjectStateException from being logged.Log4j is used here.
StaleObjectStateException being a runtime exception, shouldn't be caught in normal cases
But the only way for you to stop it from coming to logs, is to catch the exception in your code and eat up.
However, IMHO it should be of prime importance to figure out why you are getting this exception.
org.hibernate.StaleObjectStateException is a Hibernate exception that usually indicates that some other thread of control has updated the state of your entity bean in the database.
You must catch it before it is thrown from an EJB and deal with it somehow.
Any RuntimeException that is thrown from an EJB call automatically results in transaction rollback.
You should also read the javadoc for org.hibernate.StaleStateException to ensure that some of the other scenarios it describes do not apply to you.
Related
I am involved in a new project and I was assigned to investigate an error that is happening when apparently a transaction(or more than one) to the database in being performed. We are using Java for the backend(Spring framework), MyBatis for mapping objects and Websphere Liberty as server, the problem comes in some methods that are marked as #Transactional, this is the declaration:
#Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED,isolation=Isolation.READ_UNCOMMITTED)
Inside the method there are some executions to the database and apparently in some cases throws a TimeoutException and makes Rollback of operation, I guess concurrent calls make this(I am not sure) this is the error image we got:
I am new in transactions and I donĀ“t know if the parameters declared could affect in the performance, what can cause a TimeoutException as this?
I am lost, I would be grateful with any help.
Thank you.
Just a bit of background on EJB3.1 exceptions before bringing up my question -
Application exceptions comprise of
User defined checked or unchecked exceptions which have
#ApplicationException annotation
All checked exceptions
java.lang.Exception & it's subclass exceptions
except java.rmi.RemoteException & it's subclass exceptions
System exceptions comprise of
java.rmi.RemoteException and it's subclass exceptions
All unchecked exceptions
java.lang.RuntimeException and it's subclass exceptions
java.lang.Error and it's subclass exceptions
Below is a statement I have read in this book
In EJB System exceptions are not excepted by the client, when encountered such exceptions are not passed to the client as is but are wrapaped in a javax.ejb.EJBException.
My questions -
Are all application exceptions described above supposed to be thrown directly by EJB to client?
If System Exceptions are wrapped inside javax.ejb.EJBException before throwing to the client, then is javax.ejb.EJBException considered as System Exception?
IndoKnight, what a perfect wrap up you gave of how Exception semantics within the Java EE framework.. work.
Here's the two only lines a "bean provider", that is you and me, need to know about exceptions in Java EE:
Your bean is totally free to recover from any type of exception or error as you see fit, with respect to other constraints the bean might be under. If you recovered from an exception, then congratulations - there's no problem anymore =)
A relevant constraint could for example be that "enterprise beans that use container-managed transaction demarcation must not use any transaction-management methods that interfere with the container's transaction demarcation boundaries" to quote the Java EE 7 tutorial page 48-2 (would you like to programmatically set the rollback of a container managed transaction, use EJBContext.setRollbackOnly()).
You are also discouraged, as with any type of Java application, to handle Throwable or Error thrown from a really low level. RuntimeException is theoretically counted in this category, as it so famously signals a "developer error" that's like "totally totally unexpected" - yet we all know it isn't.
Basically, an unexpected exception (runtime exceptions + other shit that we assume originate from someone else) is assumed to be unhandleable by your code and should be handled by the server instead. The server is required to handle the "unhandleable" exception (see the EJB 3.2 specification, page 204) by printing something about it in the log (I'll get into the details a bit later!).
More specifically..
You asked (and here is what I believe or hold true):
Are all application exceptions described above supposed to be thrown
directly by EJB to client?
Yes. And the transaction (if one is active) shall not be rolled back unless you explicitly state that it should by using the rollback attribute of the ApplicationException. Java code throwing exceptions is a very natural thing. Java EE has no intention of demolishing this programming model. So go ahead, throw checked exceptions however you like, forcing the clients to try-catch those or mark runtime exceptions as being application exceptions and throw those too. Happy throwing!
If System Exceptions are wrapped inside javax.ejb.EJBException before
throwing to the client, then is javax.ejb.EJBException considered as
System Exception?
Yes, but not for the reason you provide. To be clear, there is no type called SystemException. It is just fancy wording to describe those kind of exceptions that the majority of beans out there didn't figure could happen, and most likely, they originate from the EJB container. Your code should definitely not throw an EJBException. Doing so would probably only thwart the mind of the Server. Nor can you annotate the exception as being #ApplicationException since you don't own the code, it is provided by the Java EE API. You could extend EJBException, but it wouldn't make any sense to disguise your code as being part of the server's codebase. Most importantly, since EJBException extends RuntimeException, I think it is safe to categorize the EJBException as a "system-level exception".
Watch out for the Devil
Some remote clients will receive the RemoteException instead of the EJBException.
Interceptors that you might not even be aware of in a huge enterprise project, could swallow exceptions thrown from your method making an active transaction commit even though you never had plans to let him do that.
I bet you think that a suppressed exception is always retrievable using Throwable.getCause(). Do note that the EJB 3.2 specification does not say that the container has to or should spare a reference to the suppressed cause. In fact, the only thing the container has to do is log the exception. Then, if the bean is not a singleton, the bean instance must be discarded and never used again. Also, if the bean is a message-driven bean, only then is the original exception required to be "wrapped". How-to "wrap" the exception is not specified. Super portable cool code should probably have a look at both the Throwable.getCause() method and Throwable.getSuppressed() too. Don't blindly expect in your handling code to always find the original exception.
Asynchronous methods (public session bean methods annotated #Asynchronous) that return void cannot propagate an exception to his client. Thus they must not declare or throw application exceptions (see the EJB 3.2 specification page 82). Do note that when you invoke an asynchronous method, it might be the case that the server cannot provide threading resources to service your request and if so, he is required to throw an.. EJBException (page 48)!
Yes, more or less that's how they work. For further details on EJB's behaviors check out the following blog post: Link
Also from this question:
An application exception shall be thrown when there is a
business-logic error, as opposed to a system error.
There is an important difference: application exceptions do not
automatically cause a transaction to rollback. The client has an
opportunity to recover after an application exception is thrown.
Application exceptions are sent to the client without being repackaged
as an EJBException. Therefore, you can use them to report validation
errors or business logic problems, and they will reach the client.
javax.ejb.EJBException extends RuntimeException so yes, it is a System Exception.
Common scenario associated with this: if you've got an uncaught RuntimeException in your application code it will roll-back. It's pretty useful default behavior.
I have an error/exception that is thrown by a particular method. Any time this error occurs, I want to log it. Would it be good practice to log the error within the initial method, and then re-throw it? That way I would not need to log it in the catch statements of any function that calls this method.
It would look something like this:
public void doSomething() throws Exception{
try{
someFunction(); // throws Exception
} catch (Exception e){
logger.fatal(e.getMessage()); // always log this Excpetion
throw e;
}
}
My concern was the re-throwing of exact same error. I have not seen this done, and I wondered if it would be considered bad practice.
EDIT: I should add that this Exception should never ever happen. That might help understand this situation.
I would log information describing why your method is about to throw an exception rather than the exception itself. Let clients decide if they want to log the exception itself or handle it.
If you handle the exception I'm not sure it is the right thing to always log it. Depends on your application of course but in general it seems to me like it should be up to the client code to log the exception.
Thus, my recommendation, if the method throws the exception, let the client take care of the handling, even if it most often means logging it. (Unless of course you want the logging to be a documented side effect of the method.)
It really depends on your logging preferences. For example you database access layer may have a method that takes a SQL query as a String as an argument and executes it in the DB. Now you may want to log any SQLException in that layer and then wrap the SQLException by a custom exception [like a DatabaseException] and then re-throw it back to the parent layer. You may also want to encapsulate some additional behaviour like a boolean shouldRetry in your DatabaseException object so that the parent layer may retry the operation again. Logging the SQLException right away will let you debug the issue more easily later.
EDIT:
This approach makes more sense when your parent layer does an operation that might throw more than one kind of exception. For example, in the above scenario, the method that takes the SQL query might also throw a InvalidHostException if the database manager is unreachable or a ConnectionRefusedException, if the database manager refused connection due to overload. In such a case you might log the exception and then wrap it with the more general DatabaseException. Also if the method threw a ConnectionRefusedException then you might want to set the shouldRetry variable to true; while the same will be false for a InvalidHostException. This allows the caller API to try to call the method again after sometime if the value of shouldRetry was set to true.
NOTE: Except SQLException, the rest are creations of my imagination. :-)
I would log the error in the initial method only if there was pertinent information there that would not be available in the client code.
Maybe you could use aspect approach. So after each busines method you check the exception type that has been thrown and verify whether it matches criteria of exception that should be logged. If so you log it and rethrow exception otherwise you just rethrow exception without logging. This allow you to centralize your error logging and disable/enable it when necessary apart from business logic - this is typical cross-cutting concern not core concern.
public class MyLoggerInterceptor ... {
#AroundInvoke
public Object invoke(InvocationContext ic){
try{
ic.proceed();
}catch(Exception e){
if(exceptionShouldBeLogged(e)){
logger.fatal(e);
}
throw e;
}
}
}
There are already a lot of answers but I would say that you need to make the best decision with the information you have at the time, but you then need to monitor what you are logging when your application runs. (many developers don't do this, me included)
If you think your logging is to verbose change it and if you find that trying to investigate an issue you don't have enough information then you add more logging in.
Its like method naming, its difficult to get right the first time but keep changing until you get it perfect.
I receive javax.ejb.TransactionRolledbackLocalException in Websphere 7 from the container and I wonder how is it possible to catch this exception? I have a timeout set in Websphere and get this message after this time. I run session beans.
I am trying to find what SQl statement was the cause of this exception. Where can i find that?
As per Sun's docs
Here's the bottom line guideline: If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.
TransactionRolledbackLocalException is an unchecked exception and there is nothing you can do if it happens. You could catch it as Aaron Digulla suggests in his answer, but what is the point ?
If you catch it then you will be messing with the internals of the App Server. You will get an exception on the client and you can call getCause() on the exception you get on the client to properly notify the user.
You have two solutions
Look at what is causing the timeout
(Probably bad SQL)
Increase the timeout
A transaction is rolled back when one of two conditions are met:
There is an exception in your code
There is a timeout
Obviously, you can catch the exception in case #1 by wrapping the outermost code with a try{}catch(). But which code of yours is executed on timeout?
Unless your app server offers an API to attach a listener to such events, this is not possible. See the documentation which you received with the product or call the support for details.
[EDIT] If you want to see the SQL which actually causes the timeout, you have two options:
You can use java.sql.DriverManager.setLogWriter(w); to log all SQL statements to a file. While this always works, it will create a lot of output and it will be hard to match this against the exception unless you can make sure you are the only one running requests.
If you use an OR mapper (like Hibernate and such), you can enable logging for them. See here for Hibernate.
You can use also the [Log4JDBC] (https://code.google.com/p/log4jdbc/).
This allows for logging in front of the driver.
The way it works is that you specify it in the datasource like a proxy.
Of course that if you are using hibernate it is simpler to set the show sql property.
But if you use JDBC this will work because all query's go through here.
I keep getting this "suggestion" from many fellow developers over and over again. In my experience I've found that EJBExceptions are well-suited for "end of the world" from the bean instance perspective (like when something is so wrong that the bean instance cannot recover by itself). If an instance can recover, I think it's better to throw an application exception.
Here is the pattern that I meet over and over again:
private SomeResource resource;
ejbCreate:
resource = allocateResource(...);
omMessage:
try {
...
} catch (JMSException e) {
throw new EJBException(e);
}
ejbRemove:
freeResource(resource);
IMHO this is a antipattern that causes resource leaks.
EDIT: Specifically, the EJB specification says that if a bean throws a runtime exception (and EJBException is a runtime exception) from the business method, then the bean is discarded without calling ejbRemove on it.
Is this a relevant example against throwing an EJBException?
What are the relevant cases when EJBException should be thrown?
The throwing of EJBException is recommended by the EJB spec (14.2.2 in the EJB 3) in the cases where the EJB cannot recover from an exception it encounters. The spec also says that the EJB can reasonably allow (unchecked) System Exceptions to propagate to the container.
I agree with your reading of the spec that in such cases life-cycle callback methods will not be invoked by the container, and hence your concern that any resource-tidy up that would normally happen in the ejbRemove() callback will not happen and so there's a danger of resource leakage.
My experience is that very many tricky problems arise because of a lack of defensive coding. "Situation X cannot occur in a well behaved system, and if it does then the whole system is broken, so I'll not code for that eventuality." Then we get some "interesting" alignment of the stars and operator errors and the "can't happen" happens several times in quick succession and unanticipated side-effects kick in leading to really difficult to diagnose problems.
Hence I would say:
Do everything you can to leave the Bean instance in a state where the next invocation of a business method might be able to work. This might mean catching exceptions and closing resources that are in error. In this case you may then chose to tell the callers, "sorry guv, that request didn't work, but maybe if you retry later ..." I do that by throwing a TransientException checked exception.
If you have no important housekeeping in ejbRemove then you can allow SystemExceptions to propogate - but I'm not sure that this is friendly. You depend upon a library and it throws a NullPointerException. Is is actually more robust to catch and rethrow TransientException?
If you do have important housekeeping, then I think you do need to catch all exceptions and at least attempt the cleanup. You may then choose to rethrow EJBException or a system exception so that the instance is destroyed, but at least you've tried to do the housekeeping.
The container can still commit the current transaction even though the EJB method has thrown an application exception. If your EJB method can throw an application exception then you should consider using EJBContext.setRollbackOnly() like this:
public void method() throws ApplicationException {
try {
...
} catch (ApplicationException e) {
_context.setRollbackOnly();
throw e;
}
}
Throwing an EJBException or a system (unchecked) exception means that the container will automatically rollback the transaction. See: http://java.sun.com/j2ee/tutorial/1_3-fcs/doc/Transaction3.html
If your system's EJBs do not routinely trap and handle application exceptions then code that throws them can result in a partially complete operation committing its changes.
This can lead to hard-to-find bugs because the "user myth" of an EJB method with CMP is that it maps to a transaction, which is atomic. The partially complete business logic is atomically committed to the database. This is extremely confusing when it happens in practice. Joel's article on leaky abstractions: http://www.joelonsoftware.com/articles/LeakyAbstractions.html explains why.
If your system has EJBs that do not handle application exceptions correctly the logical answer is to fix them so that they do. Until the problem is fixed, your team might have a rational reason for not wanting application exceptions thrown from EJBs.
Whether or not is leaks resources depends on how those resources are administered. The discarded bean gets garbage collected giving up its reference to the resource which gets garbage collected in turn when no more references point to it. If the resource is also kept in a collection with a path to root, it will leak unless the container has a pool manager that can detect idle resources and recycle it.
I agree with you that the bean should handle any exceptions it can by itself and let the result be known to the caller. For me the anti pattern in the situation you describe is using exceptions to pass object state. Exceptions should be exceptions, not used as return values.