Struts validations problems [duplicate] - validation

I have following defined in
struts-config.xml:
<struts-config>
<form-beans>
<form-bean name="LoginForm" type="com.actionform.LoginForm"/>
</form-beans>
<action-mappings>
<!-- action for login -->
<action input="/views/login.jsp" name="LoginForm" path="/Login" scope="session" type="com.actions.LoginAction"
parameter="method" validate="true">
<forward name="success" path="/views/Frameset.html" />
</action>
</action-mappings>
<message-resources parameter="/WEB-INF/ApplicationResources"/>
<!-- ========================= Validator plugin ================================= -->
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property
property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>
</struts-config>
The login form:
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
if (userName == null || userName.length() < 1) {
System.out.println("in validate ---");
errors.add("userName", new ActionMessage("error.userName.required"));
// TODO: add 'error.name.required' key to your resources
}
if (password == null || password.length() < 1) {
errors.add("password", new ActionMessage("error.password.required"));
// TODO: add 'error.name.required' key to your resources
}
return errors;
}
login.jsp:
<html:form action="/Login?method=loginUser">
<html:errors/>
<html:text name="LoginForm" property="userName" />
<html:messages id="err_userName" property="userName">
<bean:write name="err_userName" />
</html:messages>
</html:form>
Property file:
error.userName.required = User Name is required.
error.password.required = Password is required.
Where am I doing wrong? I am getting the following error
javax.servlet.jsp.JspException: Cannot find bean error in any scope
I just want to display the error in the same JSP.

After you obtain the ActionMessages/ActionErrors object which contains the messages or errors you want to display in your input page (using <html:messages> tags or <html:errors> tags), you must call one of the following methods from your Action object to place the result of your validation in scope:
addMessages(HttpServletRequest request, ActionMessages messages)
or
addErrors(HttpServletRequest request, ActionMessages errors)
Are you doing that?

I'm really do not care how about struts handles an exception. Using old raw code from 1.2 generally when overriding a RequestProcesor, I should probably replace the two methods - process and processException. First thing is happy about catching exception from the request after processValidation has been made. The fragment of code could look like
Exception exception = null;
if (needValidation)
try {
if (! processValidate(request, response, form, mapping)) {
return;
}
exception = (Exception)request.getAttribute(Globals.EXCEPTION_KEY);
} catch (InvalidCancelException ex) {
exception = ex;
}
ActionForward forward;
// Check out if exception occurred
if (exception != null){
forward = processException(request, response, exception, form, mapping);
The second is pretty easy if you have configured the errors forward. The errors forward is usually one of the global forwards that easily found from the mapping. Once it found, it likes to display your error message on the page. I think those would probably enough for processing an exception
exception.printStackTrace();
log.error(exception);
request.setAttribute("error", exception.getMessage());
return mapping.findForward("error");
It has been done because validate method from ActionForm or ValidatorForm doesn't throw any exceptions and I couldn't properly override this method without throwing some. Once thrown, who will care about it?!

Related

Spring Web Flow validator not found

I am trying to do form validation in Spring Web Flow. For this I am using a validator class, which is named after the model. Just like it is stated in the documentation.
The validator gets instantiated as a bean but is never called during validation. Any pointers on that issue?
flow config
<?xml version="1.0" encoding="UTF-8"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/webflow http://www.springframework.org/schema/webflow/spring-webflow-2.4.xsd">
<view-state id="createTotpKeyView" view="/templates/totp/create/create" model="key">
<on-entry>
<evaluate expression="createTotpKeyAction"/>
</on-entry>
<transition on="submit" to="successfullyCreated" bind="true" validate="true"/>
</view-state>
<end-state id="successfullyCreated" view="/templates/totp/create/success"/>
</flow>
This is the action that is called in the view-state.
createTotpKeyAction
#Component
public class CreateTotpKeyAction implements Action
{
String uid = "random";
#Override
public Event execute(RequestContext context) throws Exception
{
try
{
// Create a TOTP key and put it in the view scope
TOTPKey totpKey = client.createTotpKeyForUid(uid, null);
context.getViewScope().put("key", totpKey);
return new Event(this, "success");
}
catch (Exception e)
{
log.error("Error while creating TOTP key for user: " + uid + ".\n" + e.getMessage());
// Put response message in flash scope to show it once
context.getFlashScope().put("fetchingError", true);
return new Event(this, "error");
}
}
}
This is the validator I am trying to use. EDIT renamed to match documentation.
KeyValidator
#Component
public class KeyValidator
{
[...]
public void validateCreateTotpKeyView(TOTPKey key, ValidationContext context)
{
System.out.println("VALIDATE VIEW STATE");
}
public void validate(TOTPKey key, ValidationContext context)
{
System.out.println("DEFAULT VALIDATE");
}
}
I also tried different naming schemes such as TOTPKeyValidator or TotpKeyValidator. None of them worked.
The only thing that is working, is creating a validation method in the TOTPKey class, but I don't want to use that approach.
In addition this is the log file produced during the attempted validation
Log
Mapping request with URI '/totp/create' to flow with id 'totp/create'
Resuming flow execution with key 'e5s1
Locking conversation 5
Getting flow execution with key 'e5s1'
Getting FlowDefinition with id 'totp/create'
Resuming in org.springframework.webflow.mvc.servlet.MvcExternalContext#2b551393
Restoring [FlowVariable#3b66a2de name = 'key', valueFactory = [BeanFactoryVariableValueFactory#2fbc89 type = TOTPKey]]
Processing user event 'submit'
Resolved model twofa.core.domain.TOTPKey#505439d0
Binding to model
Adding default mapping for parameter 'execution'
Adding default mapping for parameter 'totpKeyId'
Adding default mapping for parameter 'token'
Adding empty value mapping for parameter 'eventId_submit'
Validating model
Event 'submit' returned from view [ServletMvcView#19f8532f view = org.springframework.web.servlet.view.velocity.VelocityLayoutView: name '/templates/totp/create/create'; URL [/templates/totp/create/create.vm]]
Executing [Transition#2feb5361 on = submit, to = successfullyCreated]
Exiting state 'createTotpKeyView'
Entering state 'successfullyCreated' of flow 'totp/create'
Executing org.springframework.webflow.action.ViewFactoryActionAdapter#423fa131
Rendering MVC [org.springframework.web.servlet.view.velocity.VelocityLayoutView: name '/templates/totp/create/success'; URL [/templates/totp/create/success.vm]] with model map [{currentUser=null, flashScope=map[[empty]], flowRequestContext=[RequestControlContextImpl#70144045 externalContext = org.springframework.webflow.mvc.servlet.MvcExternalContext#2b551393, currentEvent = submit, requestScope = map[[empty]], attributes = map[[empty]], messageContext = [DefaultMessageContext#149807b4 sourceMessages = map[[null] -> list[[empty]]]], flowExecution = [FlowExecutionImpl#1c4b2c3e flow = 'totp/create', flowSessions = list[[FlowSessionImpl#6eea5d26 flow = 'totp/create', state = 'successfullyCreated', scope = map['key' -> twofa.core.domain.TOTPKey#73f32d0a]]]]], flowExecutionKey=e5s1, flowExecutionUrl=/totp/create?execution=e5s1, key=twofa.core.domain.TOTPKey#73f32d0a}]
Finished executing org.springframework.webflow.action.ViewFactoryActionAdapter#423fa131; result = success
Completed transition execution. As a result, the flow execution has ended
Removing flow execution '[Ended execution of 'totp/create']' from repository
Ending conversation 5
Unlocking conversation 5
It says Validating Model but nothing happens...
It came down to a wrong import statement in my validator class.
Using org.relaxng.datatype.ValidationContext instead of org.springframework.binding.validation.ValidationContext will not work.

struts2 validation using message store interceptor

consider this:
user clicks on a link
request goes to DisplayLoginAction
Login.jsp is displayed
user enters his credentials
form is mapped to ValidateLoginAction
validation fails in ValidateLoginAction
ValidateLoginAction stores the errors and returns "input"
redirecting to DisplayLoginAction..
DisplayLoginAction retrieves the errors from the interceptor and shows them to the user above the login form
user refreshes the page
The errors are gone
How should I save the errors on page refresh?
<action name="displayLoginPage" class="DisplayLoginAction">
<interceptor-ref name="store">
<param name="operationMode">RETRIEVE</param>
</interceptor-ref>
<interceptor-ref name="customStack"/>
<result name="success">Login.jsp</result>
<result name="input">Login.jsp</result>
</action>
<action name="validateloginForm" class="ValidateLoginAction">
<interceptor-ref name="store">
<param name="operationMode">STORE</param>
</interceptor-ref>
<interceptor-ref name="customStack"/>
<result name="input" type="redirectAction">displayLoginPage</result>
<result name="success">LoginConfirmation.jsp</result>
</action>
user refreshes the page
The errors are gone
How should I save the errors on page refresh?
That is the way MessageStoreInterceptor works. It is actually a feature, not a bug.
Page refresh is an action triggered by the user, that means it can be assumed he has already read the result of the previous operation (the login attempt), unless he is pressing F5 with the eyes closed.
You should WANT a message to expire after the first read.
Consider a page with a lot of non-ajax operations, like combobox depending on others, etc... If the error message is persistent, it would popup after each submit operation that does not involve going to another page.
You don't want that. You should want to get the message saying that one operation has gone wrong (or right) just after that operation. If the user then proceed with other operations, like a refresh, if those operations aren't going in error (or in a specific success state), no message should be shown.
After that, there's also the problem of when deleting from session a persistent message, because otherwise you would get that message in the next action with a RETRIEVE or AUTOMATIC operationMode. Then you could (but shouldn't) customize the MessageStore Interceptor, or writing / reading / deleting messages from and to the session on your own, basically reinventing the wheel. Or even put two MessageStore Interceptors, one RETRIEVE and one STORE for displayLoginPage Action, getting the pitfalls just mentioned.
You are also using the PRG pattern (Post/Redirect/Get), to avoid re-sending the data when refreshing the page. At the same way, you should avoid re-reading the same messages twice.
To see how this specifically works, you can take a look at the MessageStore Interceptor source code, that is quite simple:
Before Invocation, if Action is ValidationAware and operationMode is RETRIEVE or AUTOMATIC:
read actionMessages, actionErrors, fieldErrors from session;
merge them with current action's actionMessages, actionErrors, fieldErrors;
remove actionMessages, actionErrors, fieldErrors from session.
/**
* Handle the retrieving of field errors / action messages / field errors, which is
* done before action invocation, and the <code>operationMode</code> is 'RETRIEVE'.
*
* #param invocation
* #throws Exception
*/
protected void before(ActionInvocation invocation) throws Exception {
String reqOperationMode = getRequestOperationMode(invocation);
if (RETRIEVE_MODE.equalsIgnoreCase(reqOperationMode) ||
RETRIEVE_MODE.equalsIgnoreCase(operationMode) ||
AUTOMATIC_MODE.equalsIgnoreCase(operationMode)) {
Object action = invocation.getAction();
if (action instanceof ValidationAware) {
// retrieve error / message from session
Map session = (Map) invocation.getInvocationContext().get(ActionContext.SESSION);
if (session == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Session is not open, no errors / messages could be retrieve for action ["+action+"]");
}
return;
}
ValidationAware validationAwareAction = (ValidationAware) action;
if (LOG.isDebugEnabled()) {
LOG.debug("retrieve error / message from session to populate into action ["+action+"]");
}
Collection actionErrors = (Collection) session.get(actionErrorsSessionKey);
Collection actionMessages = (Collection) session.get(actionMessagesSessionKey);
Map fieldErrors = (Map) session.get(fieldErrorsSessionKey);
if (actionErrors != null && actionErrors.size() > 0) {
Collection mergedActionErrors = mergeCollection(validationAwareAction.getActionErrors(), actionErrors);
validationAwareAction.setActionErrors(mergedActionErrors);
}
if (actionMessages != null && actionMessages.size() > 0) {
Collection mergedActionMessages = mergeCollection(validationAwareAction.getActionMessages(), actionMessages);
validationAwareAction.setActionMessages(mergedActionMessages);
}
if (fieldErrors != null && fieldErrors.size() > 0) {
Map mergedFieldErrors = mergeMap(validationAwareAction.getFieldErrors(), fieldErrors);
validationAwareAction.setFieldErrors(mergedFieldErrors);
}
session.remove(actionErrorsSessionKey);
session.remove(actionMessagesSessionKey);
session.remove(fieldErrorsSessionKey);
}
}
}
After Invocation, if Action is ValidationAware and operationMode is STORE or (operationMode is AUTOMATIC and Result is of type redirectAction):
read actionMessages, actionErrors, fieldErrors from action;
store actionMessages, actionErrors, fieldErrors in the session.
/**
* Handle the storing of field errors / action messages / field errors, which is
* done after action invocation, and the <code>operationMode</code> is in 'STORE'.
*
* #param invocation
* #param result
* #throws Exception
*/
protected void after(ActionInvocation invocation, String result) throws Exception {
String reqOperationMode = getRequestOperationMode(invocation);
boolean isRedirect = invocation.getResult() instanceof ServletRedirectResult;
if (STORE_MODE.equalsIgnoreCase(reqOperationMode) ||
STORE_MODE.equalsIgnoreCase(operationMode) ||
(AUTOMATIC_MODE.equalsIgnoreCase(operationMode) && isRedirect)) {
Object action = invocation.getAction();
if (action instanceof ValidationAware) {
// store error / messages into session
Map session = (Map) invocation.getInvocationContext().get(ActionContext.SESSION);
if (session == null) {
if (LOG.isDebugEnabled()) {
LOG.debug("Could not store action ["+action+"] error/messages into session, because session hasn't been opened yet.");
}
return;
}
if (LOG.isDebugEnabled()) {
LOG.debug("store action ["+action+"] error/messages into session ");
}
ValidationAware validationAwareAction = (ValidationAware) action;
session.put(actionErrorsSessionKey, validationAwareAction.getActionErrors());
session.put(actionMessagesSessionKey, validationAwareAction.getActionMessages());
session.put(fieldErrorsSessionKey, validationAwareAction.getFieldErrors());
}
else if(LOG.isDebugEnabled()) {
LOG.debug("Action ["+action+"] is not ValidationAware, no message / error that are storeable");
}
}
}
Note 1: The login operation is also self-explanatory: if after logging in you land on the login page again, it can only mean that the login failed... BTW the above explanation applies to every page/functionality
Note 2: There are sites producing messages that expire automatically after X seconds, not caring about the user having read them or not... and that is against the usability, IMHO.

struts 1 validation

Hi all I have a problem when working with struts validation as the following :
an edit profile page loaded , when user click save a validation should be executed if an error exist a redirect to the same page must happen with validation error showed, and data loaded, else execute method called. what happen that a errors list has values but no errors showed up in the screen, a snap of my code is :
I am using struts 1
<action path="/selectUserAction" validate="true" input="/selectUserAction.do" type="com.bg.sharjah.usermanagement.manageusersgroups.web.actions.SelectUserAction"
name="editUserProfileFormBean" scope="request">
#Override
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
//Logger.getAnonymousLogger().log(Level.WARNING,"");
ActionErrors errors = new ActionErrors();
try{
errors = super.validate(mapping, request);
System.out.println("validate <<<<<<<<<<< "+errors.size());
}catch(Exception e)
{
e.printStackTrace();
}
return errors;
// Validation.match(errors, password, confirmPassword);
//Validation.match(errors, email, confirmEmail);
}
Note:
my form bean is used with different actions, also I need to know how to redirect to the same page using input attribute ?
Thanx all I find out the problem it's a resource bundle issue.

ASP.NET MVC properly handling invalid URLs

I'm trying to properly handle and return a 404 for this URL: http://localhost:2867/dd./xml (notice the dot before the slash)
In my current implementation I get 4 exceptions/errors in Application_Error. The first exception returned by Server.GetLastError() is System.Web.HttpException while the next three are null.
I made a bare minimum implementation to reproduce this issue. Here's the code in global.asax.cs:
protected void Application_Error(object sender, EventArgs e)
{
Exception exception = Server.GetLastError();
Server.ClearError();
var routeData = new RouteData();
routeData.Values.Add("controller", "Error");
routeData.Values.Add("action", "Generic");
routeData.Values.Add("area", "");
IController errorController = new ErrorController();
// this line throws System.Web.HttpException is a view is returned from ErrorController
errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
}
The error controller looks like this:
public class ErrorController : Controller
{
public ActionResult Generic()
{
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View();
// returning content rather than a View doesn't fire 'System.Web.HttpException' in Application_Error
//return Content("Some error!");
}
}
There are two issues. One is that for the given URL instead of one error in Application_Error I get 3 or 4, and the other is that when returning a view from the ErrorController an exception is thrown on the Execute call line in Application_Start. If a Content("something") is returned instead this internal (to MVC I assume) exception is not triggered.
In order to see the problem you have to be in debug mode and use the development server. When using IIS or IIS Express the error is not caught for some reason. Also, every now and then these errors go away. To get it back to the beginning you have to clean the solution.
If you'd like to play with it here's the bare minimum solution: http://dl.dropbox.com/u/16605600/InvalidUrl.zip
Thank you for your help!
If you're using IIS7+ putting this in the web.config works:
<system.webServer>
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" />
<error statusCode="404" responseMode="ExecuteURL" path="/Error/PageNotFound" />
</httpErrors>
</system.webServer>
(Answer from How can I properly handle 404 in ASP.NET MVC?)
Would still be nice to know what is going on in the Application_Error.
You can handle a 404 by changing the customeErrors section in the web.config
There is also a redirectMode attribute which you can use to control the nature of the error page redirection (and avoid the 302) (Read here)
<configuration>
...
<system.web>
<customErrors mode="RemoteOnly"
redirectMode="ResponseRewrite"
defaultRedirect="/ErrorPages/Oops.aspx">
<error statusCode="404" redirect="/ErrorPages/404.aspx" />
</customErrors>
...
http://www.asp.net/hosting/tutorials/displaying-a-custom-error-page-cs
In ASP.net MVC, there is a method you can override to catch all exceptions thrown in a controller. Just override Controller.OnException(...) and you can do custom error handling in there as well. If all of your controllers inherit from a common base controller class, you can put the error handling there.
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.onexception.aspx

struts jqgrid server validation error messages

I have a project using Struts2 on the server side and I am trying to make it work with jqGrid (using JSON format). I have several tables made with jqGrid and I am using the add/edit/delete buttons from navGrid.
The main problem I have is with server validation error messages. I have created custom validators and they work with jsp pages, using s:fielderror, but I don't know how to make them work for add/edit popups from jqGrid. I am aware that jqGrid provides the users with custom validation on client, but this has its limitations(think about testing whether the email of a user is unique, you definitely must use the database for that, or if some fields depend on each other and must be tested together, like if isManager is true, then the managerCode must be not empty and vice versa...).
When I use the client validation, there is a message in the add/edit window whenever an error occurs. Can I somehow display my server validation error messages in the window in the same way?
I managed to solve the issue. I will explain how using a simple custom validator for age field, which must be > 18 for an Employee. It is supposed next that the validator was already declared in validators.xml and mapped on the action and that the message in case of ValidationException is "An employee should be older than 18.".
Using Firebug, I figured out that the id of the error area in the form is FormError. It is possible to configure a callback function errorTextFormat in jqgrid, in order to get a response from the server and process it. In the jqgrid configuration, one could write
errorTextFormat : errorFormat,
with
var errorFormat = function(response) {
var text = response.responseText;
$('#FormError').text(text); //sets the text in the error area to the validation //message from the server
return text;
};
The problem is now that the server will send implicitly a response containing the whole exception stack trace. To deal with it, I decided to create a new result type.
public class MyResult implements Result {
/**
*
*/
private static final long serialVersionUID = -6814596446076941639L;
private int errorCode = 500;
public void execute(ActionInvocation invocation) throws Exception {
ActionContext actionContext = invocation.getInvocationContext();
HttpServletResponse response = (HttpServletResponse) actionContext
.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse");
Exception exception = (Exception) actionContext
.getValueStack().findValue("exception");
response.setStatus(getErrorCode());
try {
PrintWriter out = response.getWriter();
out.print(exception.getMessage());
} catch (IOException e) {
throw e;
}
}
/**
* #return the errorCode
*/
public int getErrorCode() {
return errorCode;
}
/**
* #param errorCode the errorCode to set
*/
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
}
It must also be configured in struts.xml as follows:
<package name="default" abstract="true" extends="struts-default">
...
<result-types>
<result-type name="validationError"
class="exercises.ex5.result.MyResult">
</result-type>
</result-types>
...
<action name="myaction">
...
<result name="validationException" type="validationError"></result>
<exception-mapping result="validationException"
exception="java.lang.Exception"></exception-mapping>
</action>
...
</package>
These are the steps I followed to get a validation error message in the add/edit window and now it works.

Resources