I have an NPE being thrown in controller method:
#ManagedBean
#RequestScoped
public class Controller {
...
#PostConstruct
#Override
protected void init() {
throw new NullPointerException();
}
...
}
and jboss log contains the following entry:
19:34:53,045 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (http-/127.0.0.1:8080-1) java.lang.IllegalStateException: JBAS011048: Failed to construct component instance
The problem is that there is no stack trace. I've done a lot of googling and ran into several posts about the same problem, but those people were interested in solving the root cause of the exception, they managed to do that more or less, but I'm interested in the stack trace itself. I've tried custom exception handler (http://wmarkito.wordpress.com/2012/04/05/adding-global-exception-handling-using-jsf-2-x-exceptionhandler/) and primefaces exception handler (http://www.primefaces.org/showcase-ext/views/ajaxErrorHandler.jsf;jsessionid=1gvidy1bnjzr8jggq89l59gcs) with no success.
I would appreciate any ideas concerning why there is no stack trace in case of exception in controller method and how to deal with that.
Exceptions thrown in #PostConstruct methods of controllers are not logged properly due the following reasons:
in org.jboss.as.ee.component.BasicComponent class every exceptions are catched and wrapped with IllegalStateException:
try {
componentInstancePostConstructInterceptor.processInvocation(interceptorContext);
} catch (Exception e) {
throw MESSAGES.componentConstructionFailure(e);
}
and deep inside jboss internals, there is a class com.sun.faces.context.PartialViewContextImpl that takes controll during components construction, with the following code:
try {
// do the default behavior...
comp.encodeAll(ctx);
}
catch (Exception ce) {
if (LOGGER.isLoggable(Level.SEVERE)) {
LOGGER.severe(ce.toString());
}
Not all of the components are affected
Related
I maintain a web application that have a page with the JSF tag <f:event. I have rewrote a method in a service class for it to throw a business exception. However, when the business exception is thrown, it isn't caught in managed bean and the exception is showed on the page. Seems that my code try/catch doesn't work.
In XHTML:
<f:event listener="#{resourceBean.init(enrollment)}" type="preRenderView" />
Listener method in Managed Bean:
private boolean canCreateResource;
public void init(Enrollment enrollment) {
(...)
try {
canCreateResource = resourceService.canCreateResource(enrollment);
} catch (BusinessException e) {
canCreateResource = false;
}
}
Method in service class:
public boolean canCreateResource(Enrollment enrollment) {
if (...) {
if (mandateService.isCoordinator(user, course)) {
return true;
} else {
throw new BusinessException("Undefined business rule.");
}
}
return false;
}
From what I read on other sites, I suppose I have to implement some JSF's handler class. But which and how?
EDITED
OBS 1: The BusinessException class extends RuntimeException class.
OBS 2: The attribute canCreateResource was created to control the render of a button.
It's because you threw a RuntimeException from an EJB.
When such RuntimeException is not annotated with #ApplicationException, then the EJB container will wrap it in an javax.ejb.EJBException and rethrow it. This is done so because runtime exceptions are usually only used to indicate bugs in code logic, i.e. programmer's mistakes and not enduser's mistakes. You know, NullPointerException, IllegalArgumentException, IndexOutOfBoundsException, NumberFormatException and friends. This allows the EJB client to have one catch-all point for such runtime exceptions, like catch (EJBException e) { There's a bug in the service layer or in the way how we are using it! }
If you had tried catch (Exception e) and inspected the actual exception, then you'd have noticed that.
Fix your BusinessException class accordingly to add that annotation, it will then be recognized as a real application exception and not be wrapped in an EJBException:
#ApplicationException(rollback=true)
public class BusinessException extends RuntimeException {
// ...
}
Do note that in case you throw an non-RuntimeException, then you still need to keep the annotation on that, explicitly with rollback=true, because by default it wouldn't perform a rollback, on the contrary to a RuntimeException without the annotation.
#ApplicationException(rollback=true)
public class BusinessException extends Exception {
// ...
}
Summarized:
RuntimeException thrown from transactional EJB method will perform full rollback, but exception will be wrapped in EJBException.
RuntimeException with #ApplicationException from transactional EJB method will only perform full rollback when rollback=true is explicitly set.
Exception from transactional EJB method will not perform full rollback.
Exception with #ApplicationException from transactional EJB method will only perform full rollback when rollback=true is explicitly set.
Note that #ApplicationException is inherited over all subclasses of the custom exception, so you don't need to repeat it over all of them. Best would be to have it as an abstract class. See also the examples in the related question linked below.
See also:
Letting the presentation layer (JSF) handle business exceptions from service layer (EJB)
If isCoordinator method can eventually throw an exception you should add a try catch block inside canCreateResource method. You can throw your own exception or propagate the original one. In both cases you have to declare it in the method signature. If you throw BusinessException:
public void canCreateResource(Enrollment enrollment) throws BusinessException
Do not return any value. Or return a boolean value but do not throw any exception.
In the catch block inside the init method add the Facelet message exception:
...
} catch (BusinessException e) {
this.canCreateResource = false;
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), ""));
}
}
Also in your page you have to add <h:messages> tag.
In case you want to catch an exception that you did not create yourself (and you are not able to annotate with #ApplicationException), you can catch all exceptions and see if one of the causes is of the type you want to catch.
You can check the causes of the exception recursively:
public static <T extends Throwable> T getCauseOfType(final Throwable throwable,
final Class<T> type) {
if (throwable == null) {
return null;
}
return type.isInstance(throwable) ? (T) throwable : getCauseOfType(throwable.getCause(), type);
}
public static <T extends Throwable> boolean hasCauseOfType(final Throwable throwable,
final Class<T> type) {
return getCauseOfType(throwable, type) != null;
}
You can use this like:
try {
...
}
catch (Exception e) {
if (hasCauseOfType(e, SomeException.class)) {
// Special handling
}
else {
throw e;
}
}
I have a JAX-RS resource method.
#GET
#Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public List<Some> list() {
final List<Some> list = get();
// list and each elements are ok.
return list;
}
The problem is that application/xml generates an 500 without any specific server(tomcat) log.
application/json works fine.
I check JAXB-marshaller for every element in list.
How can I debug this? How can I test any MessageBodyWriter for List<Some>?
UPDATE
The root cause of this problem (500 without a error log) is a wrongly JAXB-annotated class.
I created an ExceptionMapper<Exception> as #peeskillet suggested.
#Provider
public class MyExceptionMapper implements ExceptionMapper<Exception> {
#Override
public Response toResponse(final Exception exception) {
exception.printStackTrace(System.err);
return Response.serverError().build();
}
}
Then I could see what error JAXB made. I still don't understand why any JAXB-error is not reported.
"How can I debug this?"
Sometimes when errors/exceptions aren't being logged, I'll create an
ExceptionMapper<Throwable or Exception>
and just print the stack trace. If the exception is being thrown in the JAX-RS context, it should go through the mapper.
See more about exception mapping
I have used the solution described in this discussion to implement BackgroundJobManager as an inner class inside my JSF bean class. I have also created an ABCTask (also an inner class) as a thread that will run at the scheduled time for the BackgroundJobManager. I have a requirement to push a message onto the JSF page but doing so from the task class ABCTask results in an NPE. The same thing works for the outer bean so i'm convinced it's something to do with the context of this inner class and the bean. Would appreciate if anyone knows a solution for this.
My inner class code is as below :
public class ABCTask implements Runnable {
public ABCTask() {
}
#Override
public void run() {
setTimeoutOccuredFlag(true);
try {
if (getActiveControlledAgent().isEventLogRunning()) {
getActiveControlledAgent().setEventLogRunning(false);
}
printTimeoutMessage();
logger_o.fine("Now leaving the ABCTask ...");
} catch (Exception e) {
logger_o.error("An error while idling "+e.getMessage());
}
}
}
The $printTimeoutMessage() is as follows :
void printTimeoutMessage() {
FacesUtils.addErrorMessage(MESSAGES.getString("common.timeoutOccured"));
}
You're basically manually spawning a thread. The FacesContext is only available in the thread serving the HTTP request which matches the URL pattern of the FacesServlet, not in other threads. The FacesContext#getCurrentInstance() would return null in all other threads.
Think once again, how would you ever send a message to the HTTP response without that the client has sent a HTTP request? By default, you can't send anything to the client without that it has requested for it.
Look for poll/push techniques. This concrete problem is completely unrelated to the class hierarchy/scope. In the future, it'd be more helpful for you and us if you've identified what exactly is null. You seem to not have done that at all.
What can be cause of not working redirection in this case?
#HandlesExceptions
public class ExceptionHandler {
public void handleException(#Handles CaughtException<Throwable> e,
Messages messages
FacesContext facesContext){
messages.error("something went wrong");
facesContext.getApplication().getNavigationHandler()
.handleNavigation(facesContext, null, "foopage");
}
}
I'm sure that exception handler method is processed. How can I redirect to some error page in exception handler method?
after calling "handleNavigation", you should call :
facescontext.renderResponse();
I am looking to develop an error handling strategy for a SharePoint solution that makes use of sandboxed webparts. I was initially looking at a general exception handling approach based on this article, but this doesn't work for sandboxed webparts. Once an unhandled exception has been thrown in the sandbox, the user code service appears to take control, so that the exception handling in the base web part isn't reached. Are there any established error handling approaches for sandboxed solutions?
Is anyone aware of a method of determining when an unhandled exception has been thrown in a sandboxed webpart, if only to change the displayed error message to a more user friendly message? I would like to replace the standard "Web Part Error: Unhandled exception was thrown by the sandboxed code wrapper's Execute method in the partial trust app domain: An unexpected error has occurred." message at very least.
Thanks, MagicAndi.
Actually, you can follow the approach suggested by the article you mentioned. You just have to provide safe overridables for all virtual properties and methods your descendant web parts are going to override. The patter can be described:
Override and seal every virtual property and method supposed to be overriden with code that can throw an exception.
Create a virtual counterpart of the overridable with the same prototype and call the base class from it if necessary. This is supposed to be overriden by your descendants.
Call the new overridable from the sealed member in a try&catch and remember the exception if caught there.
Rendering method either renders the usual content or the remembered error message.
This is a torso of the base class I use:
public class ErrorSafeWebPart : WebPart {
#region Error remembering and rendering
public Exception Error { get; private set; }
// Can be used to skip some code later that needs not
// be performed if the web part renders just the error.
public bool HasFailed { get { return Error != null; } }
// Remembers just the first error; following errors are
// usually a consequence of the first one.
public void RememberError(Exception error) {
if (Error != null)
Error = error;
}
// You can do much better error rendering than this code...
protected virtual void RenderError(HtmlTextWriter writer) {
writer.WriteEncodedText(Error.ToString());
}
#endregion
#region Overriddables guarded against unhandled exceptions
// Descendant classes are supposed to override the new DoXxx
// methods instead of the original overridables They should
// not catch exceptions and leave it on this class.
protected override sealed void CreateChildControls() {
if (!HasFailed)
try {
DoCreateChildControls();
} catch (Exception exception) {
RememberError(exception);
}
}
protected virtual void DoCreateChildControls()
{}
protected override sealed void OnInit(EventArgs e) {
if (!HasFailed)
try {
DoOnInit(e);
} catch (Exception exception) {
RememberError(exception);
}
}
protected virtual void DoOnInit(EventArgs e) {
base.OnInit(e);
}
// Continue similarly with OnInit, OnLoad, OnPreRender, OnUnload
// and/or others that are usually overridden and should be guarded.
protected override sealed void RenderContents(HtmlTextWriter writer) {
// Try to render the normal contents if there was no error.
if (!HasFailed)
try {
DoRenderContents(writer);
} catch (Exception exception) {
RememberError(exception);
}
// If an error occurred in any phase render it now.
if (HasFailed)
RenderError(writer);
}
protected virtual void DoRenderContents(HtmlTextWriter writer) {
base.RenderContents(writer);
}
#endregion
}
--- Ferda