Handling application exceptions and bean validations in JSF2 managed bean - jsf-2

I am building a JSF2 application with multi-lingual content.
1) Bean validation will be used for validating the form fields. I use ValidationMessages properties files to define locale specific error messages and use the <h:message> tag for displaying the correct error message on screen.
2) For application specific exceptions, I currently have a generic ApplicationException which is handled in managed bean methods. Inside the exception catch block, I set a "msg" field in the bean with a custom error message (For e.g: "The inventory cannot be updated as no matching product code found").
In the xhtml pages, I check if the "msg" string is not empty and display it on top of the page.
Is there a better way to handle display of success and error messages in JSF?
Can I simply throw the ApplicationException in managed beans and have a generic handler to handle the exceptions and display messages in the relevant view?
I read https://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception-jsf2, but I am not able to map it to my requirement

You're doing it almost properly. The way for the component validations is the one to go. However, for your managed bean logic, it's not necessary to implement a custom String property in your bean. Just add the message you want in your action method and it will be displayed by the h:messages tag:
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
"The inventory cannot be updated as no matching product code found","");
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, message);
Using an ExceptionHandler for just displaying a message seems overcomplicated. It also won't work for asynchronous (Ajax) requests, unless you use a third party solution like Omnifaces.
See also:
JSF 2 Global exception handling, navigation to error page not happening

Related

Can Fluent Validation .NET determine error messages sequence

I use Fluent Validation .NET for validating.
Is it possible to determine error messages sequence from "RuleFor" in validation summary.
Example:
RuleFor(x=>x.A).NotEmpty().WithMessage("A is required.");
RuleFor(x=>x.B).NotEmpty().WithMessage("B is required.");
For example, How can I determine message sequence to specificly show "B is required." before "A is required".
There is no explicit ordering of rules inside FluentValidationModelValidationFactory validator queries, that means that order of error messages on server-side depends on order of rules declaration, e.g. if rule for A property goes before rule for B, then you will see in ValidationResult error message for A before B. But it works only for manually getting of validation result (create validator object and call Validate method).
After errors get into ModelState object - they loss their order. Thats because of ModelStateDictionary type, which stores objects as Dictionary, not as List.
And if we look at NDoc description of ValidationSummary method, we see:
Returns an unordered list (ul element) of validation messages that are in the ModelStateDictionary object.
But if client-side validation enabled - then validation summary element appears without server call, and it's error messages order the same as order of inputs in html.
Conclusion
The only way to save error message order in ViewResult is to 'manually' use validator, call validate and manually iterate ValidationResult in partial view or template to create markup you need. But if you rely on client-side validation — you can just reoder inputs on form.

How can I use a shared error message Dialog in PrimeFaces

In PrimeFaces, when you want to show an error Message you can:
create in View a command Component that calls an action
in 'update' attribute, you set the id of the p:message or p:growl component that will display the message
in The backing Bean, in the action function you throw a message
As a result, the error message will be displayed in the redirect page, in the message component with the matching id
But what if :
You want to display the message in another page, that doesn't contain the command component that called the action.
The action can redirect to lots of different pages, depending on some Backing bean Logic.
The action is not called from a command Component, at least not directly
I've thought of putting a p:message component with a specific id, and include it in every xhtml page. But this would not necessarily cover the 3rd scenario.
For example, there could be a function that checks the connection to another Web Service. A Connection error could be thrown from lots of different Actions.
Or a session expiration
Or a denial of permission
How would you manage this kind of generic error messages ?
You could put the common <p:dialog> or <h:message> in a template file which is being used for all pages and give it a unique id. That way, it will be rendered for all the pages using that template.
This, is assuming that you're using templates that is.
UPDATE: If you wish to programmatically update the component, you can do so using RequestContext#update()
For e.g.
if (someErrorCondition) {
RequestContext.getCurrentInstance().update("errorDialogId");
}
where errorDialogId is the ID of the common error dialog.
If you intend to use this approach, you need to remove the update atribute from your command component.
See Also
Calling Primefaces dialog box from Managed Bean function
Why not use the RequestContext#showMessageInDialog(FacesMessage)?
As per their User Guide:
Displaying FacesMessages in a Dialog is a common case where a
facesmessage needs to be added to the context first, dialog content
containing a message component needs to be updated and finally dialog
gets shown with client side api. DF (Dialog Framework) has a simple utility to bypass
this process by providing a shortcut;
Using this you don't need to have additional codes to put in every page you have. Just add it in your beans.

JSF ui:debug causing NullPointerException

My JSF application has a <ui:debug> tag in the top level template. I have a data item creation page that saves the item to the DB. The DB then returns the saved item which I store in the JSF flash. I then redirect to a new page and display the item that I retrieved from the flash. When I view the page, the Debug page is shown with a NullPointerException and sometimes there is no stack trace and other times there is a stacktrace similar to (don't pay attention to the specific line numbers.
NullPointerException
at com.sun.facelets.util.DevTools.writeVariables(DevTools.java:158)
at com.sun.facelets.util.DevTools.writeVariables(DevTools.java:144)
at com.sun.facelets.util.DevTools.debugHtml(DevTools.java:135)
at com.sun.facelets.tag.ui.UIDebug.writeDebugOutput(UIDebug.java:92)
at com.sun.facelets.tag.ui.UIDebug.encodeBegin(UIDebug.java:81)
...
If I remove the <ui:debug> tag, then my page is successfully displayed. What is causing the NullPointerException?
Part of the job of the <ui:debug> tag is to display the contents of all the various JSF scopes including the "flash scope". DevTools.writeVariables is a helper function that is used to turn the objects in the scopes into something readable to display in the debug page. It uses methods like toString() to display the objects. The object that was stored in the flash, overrode the toString() method with the following boilerplate code
#Override
public String toString() {
//TODO: Supply implementation
return null
}
Since the toString() was returning null, it later caused a NullPointerException. If you properly implement toString(), this error will not occur.

CDI bean List in datatable is null on submit from JSF

Please note: This question is about CDI scopes as we are using CDI scopes in the app and not JSF scopes.
1) Controller Bean (TestController.java) which is in RequestScoped (enterprise context) is called index_cut.xhtml, when we come for first time on this page.
2) On button “Load”, we load the following method to populate the sapFinancialPeriodList which works fine and displays the data
3) After changing the content on the page and submitting, the sapFinancialPeriodList appears as NULL in the following method –
Any suggestions?
Your bean is request scoped and you're loading the data model on action only instead of on (post)construction. When the HTTP response after the action which loaded the data is finished, then the bean is garbaged. The subsequent request would get a brand new instance of the bean with all properties set to default. However, as the same data model isn't been preserved during (post)construct, it remains empty.
In JSF2 you'd solve this with using #ViewScoped. This way the bean will live as long as you're interacting with the same view by postbacks (which return null or void).
In CDI you'd need to solve this using #ConversationScoped, which in turn requires some additional #Inject Conversation boilerplate, complete with begin() and end() calls at the right moments. For a concrete example, see also What scope to use in JSF 2.0 for Wizard pattern?.
An alternative is to pass the parameters responsible for creating the data model to the subsequent request via <f:param> in the command link/button as follows
<h:commandButton value="save" ...>
<f:param name="period" value="#{bean.period}" />
</h:commandButton>
and then recreate exactly the same data model in (post)constructor of the request scoped bean as follows
String period = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("period");
List<SapFinancialPeriod> sapFinancialPeriodList = someservice.list(period);
(the above is by the way nicer to solve with #ManagedProperty if you were using standard JSF; as far as I know CDI doesn't have an annotation which enables you to set a HTTP request parameter as a bean property)
See also:
How to choose the right bean scope?
Unrelated to the concrete problem, the upcoming JSF 2.2 solves this functional requirement in a nicer way using the new "Faces Flow" feature with the new #FlowScoped annotation and the new xmlns:j="http://java.sun.com/jsf/flow" tags.

ErrorAttribute vs OnException vs Application_Error

I want to handle application wide error and show a ErrorView page in asp.net mvc.
There are 3 ways to do it (or i know).
1) ErrorAttribute in BaseController:Controller class.
Can be used on individual Action/Controller/BaseController.
2) Override OnException() in the BaseController:Controller class.
Will work on Controllers derived from BaseController
3) Application_Error in Global_aspx.
What is the best practice.
Which one of these methods should be used for application wide error handling or should we use multiple or only one.
If we handle error on ErrorAttribute Or/And OnException() on BaseController should we still handle it in Application_Error().
When should we use Application_Error()?
HandleErrorAttribute is an MVC filter applied via the attribute. You can supply a view name to display if an exception occurs and you can also specify the base (or specific) type of exception this filter applies to. If no view name is supplied it will look for a view named "Error". As you've already noticed you can apply it to various scopes. It allows you to specify a different "error page" view based on the exception.
Controller.OnException is a method that will get called if any of your actions ends up throwing an error.
Both of the above two are MVC concepts and part of the MVC pipeline, which sits on top of the ASP.NET pipeline, and if you handle the exception using the above it won't propagate to Application_Error, but things like http errors 404, 500 and will if I remember correctly.
What to use?
Definitely look into ELMAH for application wide error logging and my blog post about ELMAH and ASP.NET MVC
Regarding displaying error pages you should be fine with just using [HandleError] and the HandleErrorAttribute, since it already handles everything for you (optional filtering and optional custom error page per exception type).
if you want to handle the error on application level then don't apply the HandleError or OnException Override for the controller.
Try to Get the Last Error from the Server Object in Application_Error Handler check the Exception Type and based on the exception type define the action you would like to perform.
For 404 you might want to set a different action on the controller to handle.
For 500 you might want to set a different action on the controller to handle.
For NON HTTPException (SQLException) you might even want to send out email.
Please make sure you set the correct Response Status Code for SEO purpose.

Resources