I'm new to Struts framework. So seeking some online tutorials and tried to develop a very basic application. Before using interceptors am able to access username and password values in action class but after involving interceptors am getting username and password as null in action class execute method. How can i get the values of username and password inside action class?
login.jsp
<s:form action="login.action">
<s:actionerror cssStyle="color:red"/>
<s:textfield name="username" label="Username"/>
<s:password name="password" label="Password"/>
<s:submit value="Go"/>
</s:form>
Interceptor class
public class MyInterceptors extends AbstractInterceptor {
/**
*
*/
private static final long serialVersionUID = 1L;
public String intercept(ActionInvocation invocation)throws Exception{
/* let us do some pre-processing */
String output = "Pre-Processing";
System.out.println(output);
/* let us call action or next interceptor */
String result = invocation.invoke();
/* let us do some post-processing */
output = "Post-Processing";
System.out.println(output);
return result;
}
}
Action class
public class LoginAction extends ActionSupport {
/**
*
*/
private static final long serialVersionUID = 1L;
private String username;
private String password;
public String execute() {
System.out.println("Action Result.."+getUsername());
return "success";
}
//getters and setters
}
struts.xml
.....
<interceptors>
<interceptor name="myinterceptor"
class="com.techm.interceptors.MyInterceptors" />
</interceptors>
<action name="login" class="com.techm.actions.LoginAction">
<interceptor-ref name="myinterceptor"></interceptor-ref>
<result name="success">Success.jsp</result>
<result name="error">Login.jsp</result>
</action>
.....
Result on execution in console is :
Pre-Processing
Action Result..null
Post-Processing
In the action config you have overridden the interceptors configuration. Struts by default is configured to use a default stack of interceptors even if you don't use any interceptors in the action config. By overriding interceptors you made a mistake. You should add a defaultStack in your specific action config.
<action name="login" class="com.techm.actions.LoginAction">
<interceptor-ref name="myinterceptor">
<interceptor-ref name="defaultStack"/>
<result name="success">Success.jsp</result>
<result name="error">Login.jsp</result>
</action>
Related
I've created a Struts2 project in which I used XML based validation. Model class RegistrationForm is shown below
package com.projects;
import com.opensymphony.xwork2.ActionSupport;
public class RegistrationForm implements Serializable{
private static final long serialVersionUID = 1L;
private String fname;
private String lname;
private int numbr;
public int getNumbr() {
return numbr;
}
public void setNumbr(int numbr) {
this.numbr = numbr;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
}
RegistrationFormAction.Java
package com.projects;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
public class RegistrationFormAction extends ActionSupport implements ModelDriven<RegistrationForm> {
private RegistrationForm registrationForm;
public RegistrationForm getRegistrationForm() {
return registrationForm;
}
public void setRegistrationForm(RegistrationForm registrationForm) {
this.registrationForm = registrationForm;
}
public RegistrationForm getModel(){
registrationForm=new RegistrationForm();
return registrationForm;
}
public String execute(){
return "success";
}
}
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>
<constant name="struts.devMode" value="true" />
<package name="dd" extends="struts-default">
<interceptors>
<interceptor-stack name="defaultStack">
<interceptor-ref name="exception" />
<interceptor-ref name="alias" />
<interceptor-ref name="servletConfig" />
<interceptor-ref name="prepare" />
<interceptor-ref name="i18n" />
<interceptor-ref name="chain" />
<interceptor-ref name="debugging" />
<interceptor-ref name="profiling" />
<interceptor-ref name="scopedModelDriven" />
<interceptor-ref name="modelDriven" />
<interceptor-ref name="params"/>
<interceptor-ref name="validation"/>
<interceptor-ref name="fileUpload" />
<interceptor-ref name="checkbox" />
<interceptor-ref name="staticParams" />
<interceptor-ref name="conversionError" />
<interceptor-ref name="workflow"/>
</interceptor-stack>
</interceptors>
<action name="submitForm" class="com.projects.RegistrationFormAction">
<interceptor-ref name="defaultStack" />
<result name="success">/WelcomePage.jsp</result>
<result name="input">/RegistrationForm.jsp</result>
</action>
</package>
</struts>
RegistrationFormAction-validation.xml
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="registrationform">
<field-validator type="visitor">
<param name="appendPrefix">false</param>
<message/>
</field-validator>
</field>
</validators>
RegistrationForm-validation.xml
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
<validators>
<field name="fname">
<field-validator type="requiredstring">
<message>First Name can't be blank</message>
</field-validator>
</field>
<field name="lname">
<field-validator type="requiredstring">
<message>Last Name can't be blank</message>
</field-validator>
</field>
<field name="numbr">
<field-validator type="int">
<param name="min">1</param>
<param name="max">10</param>
<message>Number between 1 to 10</message>
</field-validator>
</field>
</validators>
but validation is not working.
There are a lot of things goin' on here! I'll post them in order of appearance in the question:
Never make a POJO extends ActionSupport:
public class RegistrationForm extends ActionSupport {
must become
public class RegistrationForm implements Serializable {
Better returning SUCCESS than "success" to prevent typos (but ok this is secondary);
The intercetpor stack customization has four problems:
you are overriding the existing basicStack, this risks to violate the POLA, especially if other people will work on this project; it's better to use a custom name instead, eg. myStack;
you are using only three interceptors, and this is suspicious; while many of the default interceptors can be dropped, many others instead should be always kept, especially with validation involved, eg. ConversionError Interceptor, or Workflow Interceptor, etc. Read how the whole thing works. As a rule, you should remove an Interceptor only when you know exactly what it does and you are absolutely sure you don't (and won't) need it.
When using ModelDriven (that is usually not recommended, because basically useless and source of problems when not experts with it), you need to put the ModelDriven Interceptor before the Parameters Interceptor, otherwise when the parameters interceptor runs, the model won't be pushed yet, and the setters will be searched on the action, eg. setFname(), instead that on the model (resulting in null properties in the model, and in the warning
Unexpected Exception caught setting 'fname' on 'class RegistrationFormAction: Error setting expression 'fname' with value ['Sumit', ]
because of the missing setters in the action).
Finally, if you are really using the code you posted, then you are NOT using the wrong stack you've created, because 1) The default one is the defaultStack, not the basicStack, so overriding basicStack has no effects, and 2) you've not used <default-interceptor-ref> to change the default stack reference, nor you've used the <interceptor-ref> inside the <action> tag to specify a different interceptor stack for that action only.
You are mixing 1.0.2 and 1.0.3 in DOCTYPE of XML validation files, make everything 1.0.3 (and notice that they migrated from OpenSymphony to Apache); then change:
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
to
<!DOCTYPE validators PUBLIC
"-//Apache Struts//XWork Validator 1.0.3//EN"
"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
Ensure that the RegistrationFormAction-validation.xml file is in the action folder, while the RegistrationForm-validation.xml is in the RegistrationForm.java folder.
Consider avoiding ModelDriven, because as Stephen Young says,
You Must Tame Complexity to Become a Better Programmer
As pointed out by AleksandrM's comment, there is also a typo in
<field name="registrationform">
that should be
<field name="registrationForm">
I have a drop down box via the <sj:select> tag that I can't seem to get to populate. I have a getter in the action that it is referencing via the href but it doesn't seem to trigger that action so it isn't seeing the getter. I'm using this method which should work from what I've seen from a few tutorials but I'm apparently missing something somewhere.
In its current state now it's just rendering and empty drop down box.
Quick rundown of what I think should be happening:
page should load via InputAction, which it does and populates the list variable with a list of 20 strings
the <sj:select> should fire off the action referenced in the href
that should trigger the RateClass action which populates my list box
I am going about it this way because based on the input of this box I will be switching in and out lists of strings for future select boxes in this application.
Action Class:
public class RateClass extends InputAction{
/**
*
*/
private static final long serialVersionUID = -836858635953762820L;
private String selectedUtility;
public String execute(){
return SUCCESS;
}
public String getJSON(){
System.out.println("YAY JSON!!!");
return execute();
}
public List<String> getUtilityList() {
return utilityList;
}
public String getSelectedUtility() {
return selectedUtility;
}
public void setSelectedUtility(String selectedUtility) {
this.selectedUtility = selectedUtility;
}
}
Struts.XML json package:
<package name="jsonPackage" extends="json-default" namespace="/">
<action name="rateclass" class="rateclass">
<result name="success" type="json" />
</action>
</package>
Bean Definition:
<bean id="rateclass" class="com.action.input.RateClass" scope="prototype">
</bean>
Relevant .jsp excerpt:
<label for="utility">Utility: </label>
<sj:select style="margin-left:50px;" href="%{remoteurl}" id="utility"
name="selectedUtility" list="utilityList"
headerKey="-1" headerValue="Please Select a Utility"/>
Struts URL definition:
<s:url id="remoteurl" value="rateclass"></s:url>
The issue was in the prepare() function of my InputAction class that was extended off of my JSON class. Inside of that there was a nullpointer being thrown that wasn't handled due to a DAO object I did not define in my RateClass bean.
I have an abstract class that looks like the following with appropriate getters and setters for private properties (left out to keep the post sort):
public abstract class CityDistanceAwareAction extends BaseAction implements Preparable {
private CityDistanceRepository cityDistanceRepository;
private CityRepository cityRepository;
private String cityA;
private String cityB;
private CityDistance cityDistance;
public void prepare() {
if (StringUtils.isNotBlank(cityA) && StringUtils.isNotBlank(cityB)) {
CityPair cityPair = new CityPair(getCityRepository().findByName(cityA), getCityRepository().findByName(cityB));
setCityDistance(getCityDistanceRepository().load(cityPair));
}
}
}
And then I have a very simple Class that looks like the following:
public class SearchCityDistanceAjaxAction extends CityDistanceAwareAction {
#Override
public String perform() {
if (getCityDistance() == null) {
addActionError("No city distance found for that pair");
return ERROR;
}
return SUCCESS;
}
}
The idea is that I can send in a String cityA and String cityB. Do my look-ups and simply return the cityDistance object via AJAX.
When I set my struts.xml action up as follows:
<action name="searchCityDistance" class="searchCityDistanceAjaxAction">
<result type="json">
<param name="includeProperties">
cityDistance.*
</param>
</result>
<result name="error" type="json">
<param name="ignoreHierarchy">false</param>
<param name="includeProperties">
actionErrors.*
</param>
</result>
</action>
I get the following return:
(CommonsLogger.java:68) - Adding include property expression:
cityDistance.* (CommonsLogger.java:68) - [JSON]{}
But I expected to get the cityDistance.* object back provided by the getter in the abstract CityDistanceAwareAction.
Interestingly enough if I add a special getter on the SearchCityDistanceAjaxAction object like the following:
public CityDistance getAjaxCityDistance() {
return getCityDistance();
}
and change the struts file to:
<result type="json">
<param name="includeProperties">
ajaxCityDistance.*
</param>
</result>
It gives me what I expected from my first attempt.
(CommonsLogger.java:68) - Adding include property expression:
ajaxCityDistance.* (CommonsLogger.java:68) -
[JSON]{"ajaxCityDistance":{"cityPair":{"cityA":{"cityName":"American
Falls","id":68},"cityB":{"cityName":"Ririe","id":119}},"distance":85}}
It would be ideal to remove the getter from my SearchCityDistanceAjaxAction as a getter is already provided in the parent. Is there something I am missing here or is this the way it should function?
Thanks in advance.
I was able to change my struts.xml file to the following:
<action name="searchCityDistance" class="searchCityDistanceActionAjaxAction">
<result type="json">
<param name="ignoreHierarchy">false</param>
<param name="excludeProperties">
cityDistanceRepository
</param>
<param name="includeProperties">
cityDistance.*
</param>
</result>
<result name="error" type="json">
<param name="ignoreHierarchy">false</param>
<param name="includeProperties">
actionErrors.*
</param>
</result>
</action>
But it still smells a little fishy to use the excludeProperties to leave out my cityDistanceRepository. If this is how has to be I guess that is what I will do but hopefully there is a better solution.
I am unable to find out what I am doing wrong. I am bound to use Form Bean within Form Bean as there are numerous different parts of the form. Basically, there is a response part as well as request part on the same form.
While initializing the view, I am getting a no getter method exception.
I am using Struts 1.2
javax.servlet.jsp.JspException: No getter method for property getAvailableAddres
sRequest.resellerId of bean org.apache.struts.taglib.html.BEAN
at org.apache.struts.util.RequestUtils.lookup(RequestUtils.java:968)
struts-config.xml:
<form-beans>
<form-bean name="getAvailableAddress" type="com.wisor.talktalk.model.GetAvailableAddress" />
<form-bean name="provideRequest" type="com.wisor.talktalk.common.talktalkbean.RequestActionForm" />
</form-beans>
<action-mappings>
<action path="/ttTestJsp" type="com.wisor.talktalk.controller.TestJsp"
name="getAvailableAddress"
scope="session"
validate="false"
unknown="false">
<forward name="init" path="/WEB-INF/talk/preorderView/getAvailableAddress.jsp"/>
</action>
</action-mappings>
JSP Page:
<html:form action="/ttTestJsp.do?task=getResponse" styleClass="form">
<fieldset>
<label class="inline label" for="reseller_id"><fmt:message
key="label.field.resellerId" />:</label>
<html:text
property="getAvailableAddressRequest.resellerId"
styleClass="mandatory" readonly="readonly"></html:text>
</fieldset>
<html:submit value="GetAddress"/>
</html:form>
FormBean Main:
public class GetAvailableAddress extends ActionForm{
private GetAvailableAddressRequest getAvailableAddressRequest;
public void intilize(){
getAvailableAddressRequest = new GetAvailableAddressRequest();
}
public GetAvailableAddressRequest getGetAvailableAddressRequest(){
return this.getAvailableAddressRequest;
}
public void setGetAvailableAddressRequest(GetAvailableAddressRequest getAvailableAddressRequest){
this.getAvailableAddressRequest = getAvailableAddressRequest;
}
}
child Form Bean:
public class GetAvailableAddressRequest implements Serializable{
private String resellerId;
public String getResellerID(){
return this.resellerId;
}
public void setResellerID(String resellerId){
this.resellerId = resellerId;
}
}
Action Class:
public class TestJsp extends Action {
Logger logger = Logger.getLogger(this.getClass());
#Override
public ActionForward execute( ActionMapping map, ActionForm actionForm,
HttpServletRequest request, HttpServletResponse response) throws Exception{
ActionForward forward = null;
GetAvailableAddress form = (GetAvailableAddress) actionForm;
form.intilize();
forward = map.findForward("init");
return forward;
}}
It seems your getter and setter for ressellerId field are not properly named in GetAvailableAddressRequest class. You are using ID at the end of the method name instead of Id
Corrected signatures below:
public String getResellerId(){
return this.resellerId;
}
public void setResellerId(String resellerId){
this.resellerId = resellerId;
}
Remember that the property name of the input tag must match with a getter method name in the action form
sample :
in the jsp
<html:textarea property="productDescription" rows="15" cols="50" >
</html:textarea>
in the action form
public String getProductDescription() {
return productDescription;
}
To others being redirected here: first check all your variable/method names.
The problem for me was that the Form Bean requested the values from the POJO class(the class with getters and setters) in order to display the initial jsp; since they had no value to begin with, they returned a null, making the jsp think there's no getter.
Just set a default value, even "".
public class GetAvailableAddressRequest implements Serializable{
//private String resellerId;
private String resellerId = "defaultValue";
public String getResellerID(){
return this.resellerId;
}
public void setResellerID(String resellerId){
this.resellerId = resellerId;
}
This fixed it for me!
your getter and setter for this field are not properly named in.
it should be like "private String variableName" not like "private String VariableName".
CamelCase is not recommended here.
I am pretty familiar with Struts 2... Since 3 days I've been stuck in a very strange problem.
I have many attributes in my action class; some are Integers, the others are Strings. I know I have created both of the getters/setters for all my attributes
showcase extends struts-default and json-default because i need the class to render a json table i am using the struts2-jquery gridtag....none of my attributes are being printed exept sord,sdix,page.. those defined by the tag
My Action Class
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.convention.annotation.ParentPackage;
import amz.votrerepas.dao.CategorieDao;
import amz.votrerepas.dao.CategorieDaoImplementation;
import amz.votrerepas.dao.ProduitDao;
import amz.votrerepas.dao.ProduitDaoImplementation;
import amz.votrerepas.models.Produit;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.Preparable;
#ParentPackage(value = "showcase")
public class ProduitAction extends ActionSupport implements Preparable{
private static final long serialVersionUID = 947577563329037436L;
private List<Produit> produits;
private String searchOper = "asc"; // Search operator
private String sord; // sorting order - asc or desc
private String sidx; // get index row - i.e. user click to sort.
private String searchField; // Search Field
private String searchString; // The Search String
private String oper;
private Integer rows = 0;
private Integer page = 0;
private Integer total = 0;
private Integer records;
private String myeditOptions;
#Override
public void prepare() throws Exception {
CategorieDao catdao = new CategorieDaoImplementation();
Map<Long, String> listEditOptions = catdao.getAllCategories();
List<String> arraywithresulttupels = new ArrayList<String>();
for (Long key : listEditOptions.keySet()) {
arraywithresulttupels.add(""+key+":"+listEditOptions.get(key));
}
Collections.sort(arraywithresulttupels);
myeditOptions = "{value:'" + StringUtils.join(arraywithresulttupels, ";")
+ "'}";
}
#Override
public String execute() throws Exception {
ProduitDao dao = new ProduitDaoImplementation();
produits = dao.getallProducts();
return SUCCESS;
}
public String getJSON() throws Exception {
return execute();
}
public List<Produit> getProduits() {
return produits;
}
public void setProduits(List<Produit> produits) {
this.produits = produits;
}
public String getSearchOper() {
return searchOper;
}
public void setSearchOper(String searchOper) {
this.searchOper = searchOper;
}
public String getSord() {
return sord;
}
public void setSord(String sord) {
this.sord = sord;
}
public String getSidx() {
return sidx;
}
public void setSidx(String sidx) {
this.sidx = sidx;
}
public String getSearchField() {
return searchField;
}
public void setSearchField(String searchField) {
this.searchField = searchField;
}
public String getSearchString() {
return searchString;
}
public void setSearchString(String searchString) {
this.searchString = searchString;
}
public String getOper() {
return oper;
}
public void setOper(String oper) {
this.oper = oper;
}
public Integer getRows() {
return rows;
}
public void setRows(Integer rows) {
this.rows = rows;
}
public Integer getPage() {
return page;
}
public void setPage(Integer page) {
this.page = page;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public Integer getRecords() {
return records;
}
public void setRecords(Integer records) {
this.records = records;
}
public String getMyeditOptions() {
return myeditOptions;
}
public void setMyeditOptions(String myeditOptions) {
this.myeditOptions = myeditOptions;
}
}
SomeWhere in My JSP page
<s:property value="%{myeditOptions}"/>
<s:property value="%{page}"/>
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>
<constant name="struts.devMode" value="false" />
<!-- ******************************** Comptes Actions ******************************** -->
<package name="default" extends="struts-default" namespace="/auth">
<action name="authenticate" class="amz.votrerepas.actions.Authenticate" method="execute">
<result name="success" type="redirectAction">
<param name="actionName">indexProduits</param>
<param name="namespace">/products</param>
</result>
<result name="error">/pages/welcome.jsp</result>
</action>
</package>
<!-- ******************************** Produits Actions ******************************** -->
<package name="categories" extends="struts-default" namespace="/products">
<action name="indexProduits" class="amz.votrerepas.actions.CategorieAction" method="execute">
<result name="success">/pages/admin/products.jsp</result>
</action>
<action name="edit-categorie-grid-entry" class="amz.votrerepas.actions.CategorieEditAction" method="execute">
<result name="success"> /pages/admin/products.jsp </result>
<result name="input"> /pages/admin/products.jsp </result>
</action>
<action name="edit-produit-grid-entry" class="amz.votrerepas.actions.ProduitEditAction" method="execute">
<result name="success"> /pages/admin/products.jsp </result>
<result name="input"> /pages/admin/products.jsp </result>
</action>
</package>
<!-- ******************************** Json Actions ******************************** -->
<package name="showcase" extends="struts-default,json-default" namespace="/jquery">
<action name="jsontableCats" class="amz.votrerepas.actions.CategorieAction" method="getJSON">
<result name="success" type="json" />
</action>
<action name="jsontableProds" class="amz.votrerepas.actions.ProduitAction" method="getJSON">
<result name="success" type="json" />
</action>
</package>
</struts>
My Lib Folder
antlr-2.7.6
antlr-2.7.7
asm-3.3.1
asm-3.3
asm-commons-3.3
asm-tree-3.3
cglib-2.2.2
codegen-0.5.9
commonj.sdo-2.1.1.v201112051852
commons-collections-3.1
commons-fileupload-1.2.2
commons-io-2.0.1
commons-lang-2.6
commons-lang3-3.1
dom4j-1.6.1
ecj-3.7.2
eclipselink-2.4.0
freemarker-2.3.19
guava-13.0.1
hibernate3
hibernate-commons-annotations-4.0.1.Final
hibernate-core-4.1.7.Final
hibernate-entitymanager-4.1.7.Final
hibernate-jpa-2.0-api-1.0.0.Final
hibernate-validator-4.3.0.Final
javassist-3.11.0.GA
javassist-3.12.0.GA
javassist-3.15.0-GA
javax.inject-1
javax.persistence-2.0.4.v201112161009
jboss-logging-3.1.0.GA
jboss-transaction-api_1.1_spec-1.0.0.Final
joda-time-1.6
json-lib-2.3-jdk15
jsr305-1.3.9
jta-1.1
log4j-1.2.16
mysema-commons-lang-0.2.4
mysql-connector-java-5.1.25-bin
ognl-3.0.6
querydsl-apt-3.1.1
querydsl-codegen-3.1.1
querydsl-core-3.1.1
querydsl-jpa-3.1.1
querydsl-jpa-3.1.1-apt
querydsl-jpa-3.1.1-javadoc
querydsl-sql-3.1.1
slf4j-api-1.6.1
slf4j-log4j12-1.6.1
struts2-convention-plugin-2.3.14
struts2-core-2.3.14
struts2-jquery-grid-plugin-3.5.1
struts2-jquery-plugin-3.5.1
struts2-json-plugin-2.3.14
validation-api-1.0.0.GA
xwork-core-2.3.14
The Value of page is shown but the value of myeditOptions is not.....
Pleeeease help
#Lord-zed I see that you populate myEditOptions only on prepare() method. It is not populated again when the "execute" action is hit. So either you must populate it again in execute() or put a hidden field in the jsp of the prepare action to post it back to the "execute" action. I would propose to repopulate it in the execute().
There is no need to typecast the getters and setters,
You should create different file of getters and setters and DAO too.