I am migrating my Seam 2 powered application to CDI and one of the things that is critical for me to retain is the error handling. In Seam 2, I simply replaced the default exception handler with my own, but in CDI, I am guessing I'll have to use an Interceptor.
How would I set this up as using an Interceptor requires me to specify where it will intercept calls? I mostly want to accomplish auditing, so when an exception occurs, it is logged, then a notification (email, xmpp, sms, phone call) is sent out to administrators.
When an exception occurs, is there simply an event that I can listen for and act on?
Walter
Are you using JSF2? If yes, instead of writing an Interceptor, you could register an ExceptionHandlerFactory in your web.xml as described here. In a CustomExceptionHandler, you can catch all Exceptions and handle them programmatically.
I'm using this approach in my JEE6-CDI-app, find it quite okay.
Related
In our project we use Activemq (jms template) - to publish many events from one webapp to another.
we use logging aspect (spring aop) as well - mainly we log errors and entering\quitting methods.
Now, sometimes we face racing conditions on the flow of the systems. i.e. an entity is being created on one web app, an event is fired to notify another webapp, but the handling of the other webapp requires a different event to be handled first, so if such scenario happens, the handling fails (for example, an id is missing ) and immediately retried (jms re-delivery), on the 2nd time of the retry its usually works (never more then 3 retries are required).
So basically, we have exceptions as part of our day to day flow, but:
our log files are huge and messy because of the exceptions thrown by such scenarios, any idea how can we not log the first few retries exceptions and only on a later exception we will log? Maybe another approach you can recommend?
Thanks.
You can use JMSXDeliveryCount property of Message to get the redelivery count. See http://activemq.apache.org/activemq-message-properties.html
I have a ServletContextListener which performs some database management functions when my Java EE application starts. This runs in my application before JPA and other pieces of the application are started/loaded. If the database maintenance fails I am logging the errors. If the database maintenance fails the application will not function properly and I would like to halt the application.
How can I gracefully and correctly stop the application from ServletContextListener.contextInitialized?
Solution given by Viven below is close but not quite. When I throw a RuntimeException Glassfish is left in an inconsistent state where its admin console is not accessible but some process is still running and keeping port 3700 (IIOP?) open which then prevents a restart.
In your listener, catch any exceptions and use servlet context attributes to store flags or other useful information about the error. You should probably also log something to indicate that the app is non-functional.
At this point, your options may be dictated by the architecture of your app. If all requests are handled by a single controller/dispatcher servlet, it might make sense to have its init method check the context attributes and throw an UnavailableException. Just be aware that the exception only applies to the specific servlet throwing it. This makes the approach less manageable if your app contains many servlets or allows direct access to other resources.
Another option would be to create a filter that intercepts every request, checks the context attributes and then throws an exception. Other variations are certainly possible.
If your ServletContextListener throws an exception, the webapp won't load correctly and the application server may block all subsequent request (and respond with a 500 error).
It isn't exactly preventing the application to start, nor stopping the application, but it prevents any further usage of the app and could be useful in your case.
After proper verification in the spec, this behaviour isn't mandatory in the specification. The server may (not must) return 500 errors. This solution has to be used carefully, therefore.
See this Answer for a quote from the Servlet spec.
I am trying exception handling in spring portlet based UI application,
I have used spring globalexception handling using #ControllerAdvice.
It works fine in servlet based application but its not working in portlet application.I have noticed that spring container has not processed #ControllerAdvice in portlet. I tried searching in internet on the same issue but no luck.
Is there any other way to handle exceptions in portlet applications?
Thanks in advance.
The Portlet support in Spring is rapidly declining, with very little code or documentation of such. You'll notice that the DispatcherPortlet auto-registers an instance of AnnotationMethodHandlerExceptionResolver, not the newer ExceptionHandlerExceptionResolver.
Even if you manually define an instance of the latter in your portlet.xml file, it won't get picked up by the DispatcherPortlet because it specifically looks for implementers of the org.springframework.web.portlet.HandlerExceptionResolver, which is a different hierarchy than the org.springframework.web.servlet.HandlerExceptionResolver (of which ExceptionHandlerExceptionResolver is a descendent).
Let's say you've got a Spring web app with a structure like this:
com/
myapp/
controller/
model/
service/
How should you handle exceptions that occur below the level of the controller?
Should you make methods in the Model and Service layers throw their exceptions up to the Controller layer?
What to do with them once they reach the Controller?
Do you always show the same error page to users but write a detailed exception to the log files?
It very much depends on the concrete case:
you can show the exception message (translated by some exception translation mechanism to a human-readable representation) together with validation message - for example "Email sending failed, please try again later"
If the exception can't be recovered from, you can redirect to a page which will display human-readable explanation
you can redirect to a generic 500 page that says "Oops, something went wrong"
Pick one option that you feel best fits your use-case in terms of usability.
I think logging and handling system exceptions should be done by the service layer. If you think about it in service-oriented terms, there may not be a UI calling a particular service. All system level cleanup needs to happen in that layer.
With that said, no exception should ever escape the controller layer. There needs to be enough communication between the service and controller layers so the controller can tell the user what's going on in friendly, easy-to-understand terms. Communicating back to users is the controller's duty.
I'm mantaining a EJB 2 CMP legacy app runing on a JBoss 4.0.4 GA application server with deployed entity/stateless session beans. All the EJB boilerplate code is generated via XDoclet from the EntityEJB/EntityEJBManager annotations.
I've noticed that when my GUI client invokes the facade create method, I have lots of cases of EJBException in my server log with the "Reentrant method call detected" message, which rollbacks the transaction.
What does this Exception means? How can I avoid having such error (which unfortunately, I wasn't able to reproduce yet)
Update: Found this link that explains what is meant by reentrancy, however, seems to me that it says my app cannot be accesed concurrently?
I've seen this before where EJB1 calls EJB2 which calls back to EJB1 within the container as part of the same transaction.
You can tell the container to allow this by marking EJB1 as reentrant which will allow it to be accessed multiple times in the same transaction.
This is done in the deployment descriptor with the following tag:
<reentrant>True</reentrant>
There should be a corresponding EntityEJB annotation that XDoclet can use to generate this for you.
we just came across the same problem and our solution was two-fold. Firstly we ensure that none of ejb's had transaction attributes of NotSupported within our ejb-jar.xml. We then used "instance per transaction" as our optimistic locking strategy. It's a bit of a belt-and-braces approach, but it works
It does mean that the Entity bean in question cannot be accessed concurrently, which makes sense since it would likely corrupt the data.