Prevent af:fileDownloadActionListener action event - jsf-2

Background
Using JDeveloper 11.1.2.3 to create a report download button using fileDownloadActionListener as follows:
<af:commandButton text="Run Report" id="submitReport">
<af:fileDownloadActionListener method="#{reportBean.run}"/>
</af:commandButton>
At the top of this JSF page is the following:
<f:view afterPhase="#{validationBean.afterPhase}" ...>
...
<af:form id="f1">
<f:event listener="#{validationBean.postValidate}" type="postValidate"/>
The idea is that the Validation Bean can capture any validation problems as follows:
public void afterPhase(javax.faces.event.PhaseEvent phaseEvent) {
if (phaseEvent.getPhaseId() == PhaseId.RENDER_RESPONSE) {
FacesContext context = phaseEvent.getFacesContext();
FacesMessage.Severity severity = context.getMaximumSeverity();
if (isSevereError(severity)) {
context.getExternalContext().getSessionMap().put(ERROR_FLAG_NAME, true);
}
}
}
This works as expected. When the user presses the button, but the form has an error, the validationError session variable is set to true. This should allow the framework to prevent the report from being generated if the form parameters have errors.
Problem
The validationError session variable is used by the report bean's run method as follows:
public void run(FacesContext facesContext, OutputStream outputStream) {
Object error = facesContext.getExternalContext().getSessionMap().get( ERROR_FLAG_NAME );
if( error != null && error != Boolean.TRUE ) {
Report report = null;
try {
report = getReport();
report.setOutputStream(outputStream);
configure(report.getParameters());
report.run();
} catch (Exception e) {
if (report != null && facesContext != null) {
report.publish(e);
}
}
}
else {
facesContext.getExternalContext().getSessionMap().remove( ERROR_FLAG_NAME );
facesContext.renderResponse();
}
}
When there is a validation error in the page, the facesContext.renderResponse(); code is executed, but the resulting web page is blank. No exceptions are logged. No errors are generated.
Question
One way to avoid this situation uses a hidden button, custom Java, and some JavaScript, as described on the following pages:
http://jobinesh.blogspot.ca/2010/01/customizing-execution-of-to-validate.html
http://tompeez.wordpress.com/2011/07/14/validate-data-before-export-via-afexportcollectionactionlistener-or-affiledownloadactionlistener/
However, that mechanism is complicated. The solution I have in mind will work if the page can be rendered as usual.
How do you force the page to be rendered after the af:fileDownloadActionListener event has fired?

Frank Nimphius said:
using a hidden button is the only option you have available today. I
will file an ER that raises an event for the fileDownload listener
(sort of a pre-download) that should allow you to cancel it by calling
Render Response. As said, this doesn't exist yet and the hidden button
is the option you have available (note that the file download tag is a
client behavior tag and not a full UI component, which is why there is
no way yet to interrupt execution.

Related

not able to handle JSF render exception

Using mojarra 2.1.27 and richfaces 4.3.6 on tomcat7, I was trying to implement my own exception handler for the ajax requests (Following all your advices) but I never get access to the render exception.
I have normal postback exceptions handled through web.xml <error-page> directives, which works fine, and ajax request should go through my custom handler. This seems to work when updating values and invoking the actions, but not with exceptions during rendering phase.
Having this simple ajax command button
<a4j:commandButton execute="#this" action="#{testController.actionButton4}"
render="#form" value="Ajax Post + Render Error"/>
which (amongst others) renders a div with a result
<div id="result">
#{testController.result}
</div>
Is backed by a simple action in my TestController
public String actionButton4() {
result = "action4";
inError = true;
return null;
}
And a simple getter which is used during the render.
public String getResult() {
if (inError) {
inError = false;
throw new RuntimeException("Render error in " + result);
}
return result;
}
My handler does more or less the default behaviour
public void handle() throws FacesException {
dohandle();
getWrapped().handle();
}
public void dohandle() throws FacesException {
FacesContext fc = FacesContext.getCurrentInstance();
PhaseId phaseId = fc.getCurrentPhaseId();
boolean partialRequest = fc.getPartialViewContext().isPartialRequest();
boolean ajaxRequest = fc.getPartialViewContext().isAjaxRequest();
Iterator<ExceptionQueuedEvent> iterator = getUnhandledExceptionQueuedEvents().iterator();
log.trace("Phase id ({})", phaseId);
while (iterator.hasNext()) {
log.trace("Request is partial ({}). Request is ajax ({})", partialRequest, ajaxRequest);
if (!ajaxRequest) {
return;
}
...
}
}
What I see during rendering is a logging exception in the ExtendedPartialViewcontextImpl of richfaces
Jun 25, 2014 10:18:44 AM org.richfaces.context.ExtendedPartialViewContextImpl$RenderVisitCallback logException
SEVERE: /test2.xhtml: Error reading 'result' on type c.n.g.w.controller.TestController
...
Then I see the phase ends and the exception handler is consulted
10:18:44.336 {http-bio-8080-exec-2} TRACE c.n.g.w.generic.LifeCycleListener - END PHASE RENDER_RESPONSE 6
10:18:44.336 {http-bio-8080-exec-2} TRACE c.n.g.w.generic.ExceptionHandler - Phase id (RENDER_RESPONSE 6)
But for some reason there is no unhandled exception in the queue.
I couldn't find anything stating that the RF rendering should react any different that others, but I suspect it could be. Does anyone know more than me here?
UPDATE:
I notice from the client side log that the rendered output is clipped right at the EL tag, so the rendering breaks and commits the partial result for some reason.

How to handle an error in a "Model" class in MVC ASP.NET, to do with null session vars

I am using MVC3, C#, Razor, .NET4
I use a session variable in my Model constructor. Sometimes it can be null, mainly due to recycling of the AppPool. I need to catch the "null" error of the session and ideally redirect to another action ie Error/Index. However I am in model, and I am not sure whether one can redirect out of a model class.
my Code:
try
{
intOrderId = (Int32) System.Web.HttpContext.Current.Session["OrderId"];
intSupplierId = (Int32) System.Web.HttpContext.Current.Session["SupplierId"];
}
catch (Exception e)
{
// Redirect to Error/Index ?????
}
I have a feeling that I may have to set a property in the model to highlight the error, and then have the controller's action inspect this and act accordingly, howowever I have loads of actions that call this model, so I am not wanting to do this. I would rather react to this error in one place.
Many thanks in advance for any help on this.
Rather than using try/catch to handle empty values, why not check before you read?
if(System.Web.HttpContext.Current.Session["OrderId"] != null)
&& System.Web.HttpContext.Current.Session["SupplierId"] != null)
{
intOrderId = (Int32) System.Web.HttpContext.Current.Session["OrderId"];
intSupplierId = (Int32) System.Web.HttpContext.Current.Session["SupplierId"];
}
else
{
//Throw an exception that the controller can catch: NullReferenceException or InvalidCastException.
//Or return a specific value to indicate that an error occured
}

How to handle errors in my CustomAutorize attribute in asp.net 3.0 Application

I am working on an asp.net MVC 3.0 Application. I am using using my own CustomRoleProvider
and CustomErrorHandler by overriding default attributes.
Every thing is working fine. But ,the problem is with the exception handling.
While testing the application , tester has given invalid DB connection to test.
The result is , Custom Error Handler is not rendering Error View , instead it is routing the original path
For ex:
I am running my application as
Home/Index
It is first hitting Custom Role Provider to fetch the roles for the application
Since , the Db Connection is not correct , it is raising exception that "Not able to Connect"
Now , Instead of routing to Error View along with this error message. It is routing to Home Controller and Index action.
**The code for my Custom Error Handler is as Follows**
public class CustomHandleErrorAttribute : HandleErrorAttribute // Error handler
{
public override void OnException(ExceptionContext filterContext)
{
if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
{
return;
}
if (new HttpException(null, filterContext.Exception).GetHttpCode() != 500)
{
return;
}
if (!ExceptionType.IsInstanceOfType(filterContext.Exception))
{
return;
}
// if the request is AJAX return JSON else view.
if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
{
filterContext.Result = AjaxError(filterContext.Exception.Message, filterContext);
}
else
{
filterContext.ExceptionHandled = true;
var controllerName = (string)filterContext.RouteData.Values["controller"];
var actionName = (string)filterContext.RouteData.Values["action"];
var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
filterContext.Result = new ViewResult
{
ViewName = View,
MasterName = Master,
ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
TempData = filterContext.Controller.TempData
};
}
}
protected JsonResult AjaxError(string message, ExceptionContext filterContext)
{
if (String.IsNullOrEmpty(message))
message = "Something went wrong while processing your request. Please refresh the page and try again.";
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
return new JsonResult { Data = new { ErrorMessage = message }, ContentEncoding = System.Text.Encoding.UTF8, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
In the above code , after setting up filterContext.Result . It is not rendering Error View as Expected.
Please correct/suggest me, where i am going wrong..
Updated:
public class CustomRoleProvider : RoleProvider // Custom role provider
{
public override string[] GetRolesForUser(string username)
{
// Fetching roles for user from database
}
// Some other Methods
}
This is method is generating exception , since it is trying to connect to wrong connection
Updated2:
1) I am using Custom Error Handler for the entire controller.
2) I need to catch all the exceptions including Ajax Errors
3) I have included my code for Custom Error Handler Above
4) I am also using CustomRole Provider for entire controller
5) Here, I am trying to generate exception , by giving wrong database connection
6) I am running the URL : Home/Index
7) Before going to thatr URL, it is hitting the methods in Role Provider class since i am using it as a attribute
8) Since, i have gave wrong DB Connection , It is generating exception
9) Then, it fires on exception method of Custom error handler
10) Building the Error Model for the error view
11) But, here is the problem. Instead of rendering Error View , it is going to index method of the Home Controller.
12) But, i need Error View to be rendered here, because it has failed to connect to database and getting roles . I want furthuer execution of URL Home/Index to be stopped here.
Hope this clarifies the problem..i am running in to. please feel free to ask me for furthuer details/Clarification
HandleError is designed to be able to register multiple filters (for example for different exceptions). One filter can handle only some specific exceptions or error cases and another unhandle cases can be handled by another HandleError. I suppose that currently both standard and your [CustomHandleError] filter are applied. You can set the Order property to an integer value that specifies a priority from -1 (highest priority) to any positive integer value. The greater the integer value is, the lower the priority of the filter is. You can use Order parameter for example (see here) to make your filter working before. More full description of the order you can find in the MSDN documentation.
The answer, this one and the article for example provide small examples of usage Order property of HandleError.

Handle ViewExireException/ajax and display a Primefaces dialog

I don't redirect or forward my user to another page. So when the my SessionExpiredExceptionHandler (extends ExceptionHandlerWrapper) handles the ViewExireException. I want the user to stay on the same page and display a PrimeFaces Dialog. For notifying that the session has expired and that the user needs to login again (dialog based). I am use Servlet 3.1 functions to login/logout user and Basic/file for auth-method to map the users to different system roles.
What is happening now is that the View/page get refreshed after 2 min, but the session doesn't get invalidated. That only happens the second time when the page refreshes, after 4 min.
<session-config>
<session-timeout>2</session-timeout>
</session-config>
Edit:
Which is refreshed by the meta tag:
<meta http-equiv="refresh" content="#{session.maxInactiveInterval}" />
How can I make SessionExpiredExceptionHandlerinvalidate the session object (Servlet logout) when the Exceptions occur the first time, and how can I invoke a JavaScript (expireDlg.show()) on the client to display a PrimeFaces dialog ?
I have looked at some other threads but not found a viable solution.
Session time-out
SessionExpiredExceptionHandler
#Override
public void handle() throws FacesException {
for (Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents().iterator(); i.hasNext();) {
ExceptionQueuedEvent event = i.next();
ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
Throwable t = context.getException();
if (t instanceof ViewExpiredException) {
ViewExpiredException vee = (ViewExpiredException) t;
FacesContext fc = FacesContext.getCurrentInstance();
Map<String, Object> requestMap = fc.getExternalContext().getRequestMap();
NavigationHandler nav = fc.getApplication().getNavigationHandler();
try {
requestMap.put("currentViewId", vee.getViewId());
nav.handleNavigation(fc, null, "Home");
fc.renderResponse();
} finally {
i.remove();
}
}
}
// At this point, the queue will not contain any ViewExpiredEvents.
// Therefore, let the parent handle them.
getWrapped().handle();
}
web.xml
<exception-type>javax.faces.application.ViewExpiredException</exception-type>
<location>/home.xhtml</location>
</error-page>
How can I make SessionExpiredExceptionHandler invalidate the session object (Servlet logout) when the Exceptions occur the first time
The session is supposedly to be already invalidated/expired (otherwise a ViewExpiredException wouldn't be thrown at all), so I don't see how it's useful to manually invalidate/expire it yourself. But for the case that, you can invalidate it as follows:
externalContext.invalidateSession();
and how can I invoke a JavaScript (expireDlg.show()) on the client to display a PrimeFaces dialog ?
You can use the PrimeFaces RequestContext API to programmatically instruct PrimeFaces to execute some JS code on complete of ajax response.
RequestContext.getCurrentInstance().execute("expireDlg.show()");
Don't forget to remove the navigation handler block from the exception handler if you actually don't want to navigate.
This solution worked for my case. It seams that Primefaces (3.3) is swallowing the ExceptionQueuedEvent. There are no Exception to handle when my ViewExceptionHandler gets called. So instead I used the p:idleMonitor component with event listner. I also removed the meta refresh tag.
<p:idleMonitor timeout="#{(session.maxInactiveInterval-60)*1000}">
<p:ajax event="idle" process="#this" update="sessionMsg" listener="#{userController.userIdleSession()}" />
<p:ajax event="active" process="#this" update="sessionMsg" listener="#{userController.userActiveSession()}"/>
</p:idleMonitor>
One weird thing is if the timeoutis excatly the same as the web.xmlsession time-out parameter, the listener won't be invoked.
Bean functions
public void userIdleSession() {
if (!userIdleMsgVisable) {
userIdleMsgVisable = true;
JsfUtil.addWarningMessage(JsfUtil.getResourceMessage("session_expire_title"), JsfUtil.getResourceMessage("session_expire_content"));
}
}
public void userActiveSession() {
if (!userSessionDlgVisable) {
userSessionDlgVisable = true;
RequestContext.getCurrentInstance().execute("sessionExipreDlg.show()");
}
}
The dialog (sessionExipreDlg) called the redirect instead of using navigation handler to get new scope and refresh the page.
public void userInactiveRedirect() {
FacesContext fc = FacesContext.getCurrentInstance();
userIdleMsgVisable = false;
userSessionDlgVisable = false;
sessionUser = null;
HttpServletRequest request = (HttpServletRequest) fc.getExternalContext().getRequest();
JsfUtil.findBean("homeController", HomeController.class).clearCurrentValues();
try {
fc.getExternalContext().redirect(JsfUtil.getApplicationPath(request, false, null));
} catch (IOException ex) {
BeanUtil.severe(ex.getLocalizedMessage());
}
}

Visual Studio 2010 add in - events not triggered

I have written an add in that takes the active document as a parameter. So each time that the active document has changed, I need to know. To do so, I wanted to use "Events.DocumentEvents.DocumentOpened" event of the DTE2 object. But the problem is that event is never get fired even though I change the active document.
The code snippet is as follows
public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref Array custom)
{
_applicationObject = (DTE2)application;
_applicationObject.Events.DocumentEvents.DocumentOpened += new _dispDocumentEvents_DocumentOpenedEventHandler(DocumentEvents_DocumentOpened);
...
}
void DocumentEvents_DocumentOpened(Document Document)
{
MessageBox.Show("Not called");
}
I have tried with DocumentEvents as well but no success. Any ideas?
I had just realized that I focused on the wrong event and thats why it was not fired. With the code below I got what I intended to. So instead of DocumentEvents, I had to use WindowEvents.
....
_applicationObject.Events.WindowEvents.WindowActivated += new _dispWindowEvents_WindowActivatedEventHandler(WindowEvents_WindowActivated);
}
void WindowEvents_WindowActivated(Window GotFocus, Window LostFocus)
{
if (ucCAST != null && GotFocus.Document != null)
((CAST)ucCAST).refreshCode(GotFocus.Document.Name);
}

Resources