addFieldError not working in Struts2 - struts2

i am learning struts2 and facing some problems with showing the addFieldError message..nothing shows up ..
when i run my project and leave userID field blank it does enters into the validate method and even satisfies the condition of isEmpty method but it doesnt shows up any error message..
i put a s.o.p. statment in the isEmpty method to see ,it is entering or not..
the statment gets printed on console , the url changes to ../MyStruts/validation.action with no errors anywhere and nothing happens further..
can someone tell me where i am doing it wrong..
here is my code..
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="validate" extends="struts-default">
<action name="validation" class="com.staction.DataAction">
<result name="success">/success.jsp</result>
<result name="input">/form1.jsp</result>
<result name="error">/error.jsp</result>
</action> </package>
</struts>
form1.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%# taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
</head>
<s:form action="validation">
<h1>
<s:textfield label="UserName" name="userID" />
<s:password label="password" name="password" />
</h1>
<s:submit />
</s:form>
<s:a href="forget">forget password </s:a>
</html>
Action class...
package com.staction;
import org.apache.commons.lang3.StringUtils;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class DataAction extends ActionSupport implements ModelDriven<User> {
private static final long serialVersionUID = 1L;
User user;
DataCheck dc;
public DataAction() {
user=new User();
dc=new DataCheck();
}
#Override
public void validate() {
if(StringUtils.isEmpty(user.getUserID()))
{
System.out.println("hellp");
addFieldError("user.userID", "wtf!!!!");
}
}
public String execute()
{
System.out.println("user.userID");
/* if(dc.isValid(user))
{
return SUCCESS;
}*/
return ERROR;
}
#Override
public User getModel() {
// TODO Auto-generated method stub
return user;
}
}
and finally the User class..
package com.staction;
import org.apache.commons.lang3.StringUtils;
import com.opensymphony.xwork2.ActionSupport;
public class User{
String userID;
String password;
public String getUserID() {
return userID;
}
public void setUserID(String userID) {
this.userID = userID;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}

Your form:
<s:textfield label="UserName" name="userID" />
Your field error:
addFieldError("user.userID", "wtf!!!!");
See the difference?
Also:
I hope your code isn't actually formatted randomly like that; it's very difficult to read.
Why does your User class extend ActionSupport? If it's not an action, don't extend the base default action: it's pointless, and misleading.
Consider naming actions something meaningful: most actions are "data actions".
When posting examples, kindly trim out commented-out code and stuff that isn't directly related to the specific question.

In addition to response of Dave Newton, you must delete "user." in addFieldError so that Struts2 takes automatically the right object using getModel, or you must add set/get methods for object user in Action so that object is accessed using getter.

Jst use the name of your field that to be validated... Change ur code to
addFieldError("UserName", "wtf!!!!");

Related

JSF ViewScope beans incorrect hashcode implementation?

I am developing a simple application on JSF having the following dependences
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-impl</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.myfaces.core</groupId>
<artifactId>myfaces-api</artifactId>
<version>2.0.2</version>
</dependency>
and being a simple page with it backing bean.
xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<head>
<title></title>
</head>
<body >
<h:form>
<f:view >
<h:commandButton id="otxMainPanelTextBt" value="click"
action="#{otherController.doSome}"/>
</f:view>
</h:form>
</body>
</html>
Java code
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "otherController")
#ViewScoped
public class Other implements Serializable {
private static final long serialVersionUID = -6493758917750576706L;
public String doSome() {
System.out.println(this);
return "";
}
}
If I click on the commandButton many times according to toString source code it should write
class name+hashCode
but it writes something like the following
de.controller.Other#118ea91
de.controller.Other#1e8f930
de.controller.Other#1a38f3c
So, everytime we click there is a different hashcode for the viewscoped bean. Is this incorrect? I have tryed with session beans and this doesn't happen.
EDIT
I modified the class following #BalusC suggestion in the following way.
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "otherController")
#ViewScoped
public class Other implements Serializable {
private static final long serialVersionUID = -6493758917750576706L;
#PostConstruct
public void init()
{
System.out.println("Post Construction");
}
public Other()
{
System.out.println("Constructor");
}
public void doSome() {
System.out.println(this);
}
}
And I found this output after clicking many times.
Constructor
Post Construction
de.controller.Other#b748dd
de.controller.Other#1620dca
de.controller.Other#116358
de.controller.Other#73cb2d
de.controller.Other#1cc3ba0
So, the constructor and PostConstructor Methods are invoked only once, and in spite of this the object still has a different hashcode in every call. This is weird because the constructor with no parameter is supposed to be called on a managed bean instantiation, but it is not, so i still don't understand how can be the object created several times?
When you return non-null from an action method, a new view is created.
If you want to keep the current view alive, just return null or void from the action method.
E.g.
public void doSome() {
System.out.println(this);
}
See also:
How to choose the right bean scope?
That said, your conclusion that this is a problem is correct, but the grounds on which you based off your conclusion, "incorrect hashcode implementation", makes no utter sense. It were just physically different bean instances everytime. Add a default constructor to the class, put a breakpoint on it and you'll see that it's invoked everytime after you returned from the action method, creating a brand new instance.

Unable to access GET parameters in JSF backing bean

I am unable to access GET parameters in a backing bean. The example.xhtml file:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<f:metadata>
<f:viewParam name="id" value="#{myBackingBean.unitId}" />
<f:viewAction action="#{myBackingBean.findUnits}" />
</f:metadata>
<head>
<title>Example Title</title>
</head>
<body>
I found #{myBackingBean.units.size()} units.
</body>
</html>
My understanding is that when I GET example.jsf?id=3 then JSF calls myBackingBean.setUnitId(3). Correct?
Here is MyBackingBean:
#Model
public class MyBackingBean {
private static Logger logger = Logger.getLogger(MyBackingBean.class
.getName());
//#ManagedProperty("#{param.id}")
private Long unitId;
#Inject
private IExampleEJB myExampleEjb;
private List<Unit> units;
#PostConstruct
public void postConstruct() {
Map<String, String> mymap = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
for (String k:mymap.keySet()) {
logger.info(String.format("%s %s", k,mymap.get(k)));
}
}
public void findUnits() {
logger.info(String.format("MyBackingBean findUnits %d", unitId));
units = myExampleEjb.findUnits();
}
public List<Unit> getUnits() {
return units;
}
public void setUnits(List<Unit> units) {
this.units = units;
}
public Long getUnitId() {
return unitId;
}
public void setUnitId(Long unitId) {
this.unitId = unitId;
}
}
The id parameter is in the parameter request map in postConstruct().
In my case, setUnitId() is never called, nor is findUnits().
In a different but related question, the #ManagedProperty (currently commented out) does not work either.
Given the xmlns.jcp.org namespace, you're using JSF 2.2. The early Mojarra 2.2.0 and 2.2.1 versions have a known bug which causes the <f:viewParam> to not work.
As per the comments you're using GlassFish 4.0. If you didn't upgrade its bundled JSF implementation and thus are using the early Mojarra version 2.2.0, then you're definitely facing this bug and you need to upgrade.
You can get the JAR from http://javaserverfaces.java.net. All you need to do is to replace javax.faces.jar file in GlassFish's /modules folder with the newer version.
See also
f:viewParam doesn't pass required parameter when new xmlns.jcp.org namespace is used

JSF Navigation outcome constants

I wonder if i can replace "success" with a Constants value from a JSF library.
Backing Bean Method:
#Override
public String save() {
LOG.info("Called");
return "success";
}
For your issue, you'll find Omnifaces' <o:importConstants /> so useful (that's what I use in my own projects). That way you can import your constants file in your JSF page (I use my master page template for that).
<o:importConstants
type="com.mycompany.NavigationResults" />
This way you can access your NavigationResults values both from Java code and JSF tags (EL scope).
public abstract class NavigationResults {
public static final String SUCCESS = "success";
public static final String HOME = "home";
}
Use it in your managed beans:
public String save() {
LOG.info("Called");
return NavigationResults.SUCCESS;
}
In your buttons or links:
<h:button value="Go home" outcome="#{NavigationResults.HOME}" />

Struts2: How to pass a values from one action to another action. Or from one JSP to another JSP. Without using session

Hi I am building a project using Struts2. However during the development I am facing many issues. The biggest issue is Session management in Struts2. There is very limited information related to this.
I have hunt for the solution to my problem but got only limited information that does not satisfy my needs.
I do not wish to use container's session (Apache Tomcat 7) as it will become an overhead when multiple user would try to use the application.
I have created 2 Action classes and 2 JSPs.
The values entered in JSP1 (Login.jsp and LoginAction.java POJO) should be used in another action (HomeAction.java POJO) and later they should display in subsequent JSPs (Home.jsp).
I am using tiles as well.
I have tried using tag but I cannot able to set a value to it.
In Struts2,
How could I pass an object on a JSP1/Action to another Action/JSP2 ?
A small Login page example would be appreciated.
e.g. A username entered in a text field should display to another JSP page using 2 different Action classes.
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.custom.i18n.resources" value="ApplicationResources" />
<package name="default" extends="struts-default">
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" />
</result-types>
<action name="login" class="org.myaction.LoginAction" method="validateLoginCredentials">
<result name="autheticatedUser" type="redirect" >homePage</result>
<result name="fail" >/jsp/Login.jsp</result>
</action>
<action name="homePage" class="org.myaction.HomeAction" method="execute">
<result name="responseOK" type="tiles" >/tile.NextPage</result>
<result name="error" type="tiles" >/tile.HomePage</result>
</action>
</package>
</struts>
LoginAction.java
public class LoginAction extends ActionSupport {
//private static final String SUCCESS = "success";
private static final String FAIL = "fail";
private String userName;
private String password;
public String getUserName() { return userName; }
public void setUserName(String userName) { this.userName = userName; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public String validateLoginCredentials() {
if(this.userName.equals("admin")
&& this.password.equals("allow")) {
return "autheticatedUser";
}
addActionError(getText("error.login"));
return FAIL;
}
}
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>Login</display-name>
<context-param>
<param-name>org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG</param-name>
<param-value>/WEB-INF/tiles.xml</param-value>
</context-param>
<listener>
<listener-class>org.apache.struts2.tiles.StrutsTilesListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>/jsp/Login.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
My question is,
In Struts2,
How could I pass the userName from Login.jsp/LoginAction.java to Home.jsp/HomeAction.java ?
Note: Storing into session is not preferred option but could use if there is no other way to maintain the user state in Struts2.
A small Login page example would be appreciated.
e.g. A username entered in a text field should display to another JSP page using 2 different Action classes.
Edited
Hi thank you! I really appreciate your reply. I presume this would work. There is one more thing I forgot to mention.
An another class(JavaBean) property is present in LoginAction.java class.
public class LoginAction extends ActionSupport {
private UserData userData;
public void setUserData(UserData userData) {
this.userData = userData;
}
public String getUserData() {
return userData;
}
}
UserData.java
public class UserData {
private String userName;
public void setUserName(String userName) {
this.userName = userName;
}
public String getUserName() {
return userName;
}
}
how can I set the userName property of UserData object which is in
LoginAction.java ?
I've tried this
<s:hidden name="userData.userName" value="userName" />
but it's not working....
Do you know what mistake I am making here?
Use redirectAction with param
<action name="login" class="org.myaction.LoginAction" method="validateLoginCredentials">
<result name="autheticatedUser" type="redirectAction">
<param name="actionName">homePage</param>
<param name="userName">${userName}</param>
</result>
<result name="fail" >/jsp/Login.jsp</result>
</action>
Also, don't forget to add userName getter/setter in HomeAction class. Then in your Home.jsp you can directly use <s:property value="userName"/> (or whatever)
The conversation plugin is a good wrapper around session, which can be used to manage the objects life time between actions. (https://code.google.com/p/struts2-conversation/)
This solution will help a lot when you have some step base jsp pages (more than two steps). The plugin in is annotation base and has necessary jsp tags too

Question about Struts2 return type

I have the following scenario:
Struts.xml
<action name="user_initNews" method="initNews" class="it.sba.bcc.sbarima.user.web.action.UserAction">
<result type="dispatcher">
<param name="location">pages/elementicomuni/elencoNews.jsp</param>
</result>
</action>
User Action
public class UserAction extends BaseAction
{
private NewsService newsService = null;
private User utente;
private List<News> news;
public String initNews()
{
return SUCCESS;
}
public void elencoNews()
{
try
{
newsService = UserServiceFactory.getNewsService();
this.news = newsService.getNews(getAbiUserProfile(), getMatricolaUserProfile());
}
catch (ServiceException e)
{
e.printStackTrace();
}
}
public List<News> getNews()
{
return news;
}
}
elencoNews.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<?xml version="1.0" encoding="utf-8"?>
<%# taglib uri="/struts-tags" prefix="s" %>
<html>
<body>
<s:action name="user_elencoNews!elencoNews"></s:action>
<s:iterator value="news" var="n">
<label><s:property value="descrizione"/></label>
</s:iterator>
</body>
</html>
Whene the elencoNews.jsp is rendered, I would like to call from the JSP page an action thath return a set of POJO to iterate.
The elencoNews.action is correctly called, but I do not know how to treat data on the elencoNews.jap
How can I do that?
I'm afraid you are misunderstanding the whole Struts2 typical workflow. You dont (typically) want to call another action from the JSP, in the typical workflow the JSP renders after your action has processed your request, and it just displays data (typically from your Action instance, which is found in the value stack).
Eg read here
In your example, you'd should code in your JPS:
<s:iterator value="news" var="n">
<s:property value="descrizione"/>
</s:iterator>
If you have this concepts clear (and you have coded the most basic-typical struts2 cases), the disregard this and be more explicit about what are you trying to accomplish - why you have two actions involved for a single request and jsp.
If you want a dynamic jsp page, you can look into using the Struts2-jQuery plugin which will allow you to call another action in your JSP and load the results. See examples at http://www.weinfreund.de/struts2-jquery-showcase/index.action under Ajax Link or Ajax Div sections.

Resources