I use Struts 2.3.32 and this is the code.
methodPrefix.jsp
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<s:form action="methodPrefix" theme="simple">
name: <br/>
<s:textfield name="name"/>
<br><br>
<s:submit value="Create Person"/>
<s:submit name="method:cancel" value="Cancel"/>
</s:form>
</body>
</html>
MethodPrefixAction.java
public class MethodPrefixAction
{
private String name;
private String message;
public String execute() throws Exception
{
message = name + " create";
return "success";
}
public String cancel() throws Exception
{
message = "cancel";
return "success";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
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.mapper.action.prefix.enabled" value="true" />
<package name="default" extends="struts-default" namespace="">
<action name="goMethodPrefixPage">
<result>/chapter4/methodPrefix.jsp</result>
</action>
<action name="methodPrefix" class="example.chapter4.MethodPrefixAction">
<result>/chapter4/methodPrefixResult.jsp</result>
</action>
</package>
</struts>
when I push Cancel button, It do not call cancel() method, just call execute() method.
I don't know why method: prefix not work.
I searched a lot, and I know method: prefix configuration is false by default in Struts 2.3.32, so I used a constant..... but it did not work
This constant
<constant name="struts.mapper.action.prefix.enabled" value="true" />
works only for action: prefix, not a method: prefix. So you should use the action attribute to submit tag.
<s:submit action="cancel" value="Cancel"/>
Note: If you have DMI turned off the action: prefix is still available.
This tutorial explains it and this tutorial shows how to do validation
Method MethodPrefixAction.execute should return success or cancel string.
In struts.xml you can redirect user to different pages based on return string:
<action name="methodPrefix" class="example.chapter4.MethodPrefixAction">
<result name="success">/chapter4/methodPrefixResult.jsp</result>
<result name="cancel">/chapter4/methodPrefix.jsp</result>
</action>
Related
below is the code snippet, I want to retrieve the selected value, the autocomplete works perfectly fine,
<%# taglib prefix="s" uri="/struts-tags" %>
<%# taglib prefix="sx" uri="/struts-dojo-tags" %>
<html>
<head>
<script type="text/javascript">
function sayPramod()
{
alert("hiii");
}
</script>
<sx:head />
</head>
<body>
<h1>Struts 2 autocompleter + JSON example</h1>
<s:form >
<s:url id="databaseList" action="databaseJSON"
/>
<sx:autocompleter label="What's your favorite Database Server?"
href="%{databaseList}" name="yourFavDatabase"
/>
<s:submit value="submit" name="submit" onclick="sayPramod();" />
</s:form>
</body>
</html>
The java code is:
package com.krcl.rap.common.menu.action;
import java.util.HashMap;
import java.util.Map;
import com.opensymphony.xwork2.Action;
public class DatabaseJSON {
private Map<String, String> databases = new HashMap<String, String>();
public DatabaseJSON(){
databases.put("Google", "www.google.com");
databases.put("Oracle", "Oracle");
databases.put("PostgreSQL", "PostgreSQL");
databases.put("Microsoft SQL Server", "Microsoft SQL Server");
databases.put("DB2", "DB2");
}
public String execute() {
return Action.SUCCESS;
}
public Map<String, String> getDatabases() {
return databases;
}
public void setDatabases(Map<String, String> databases) {
this.databases = databases;
}
}
struts.xml
<package name="json" namespace="/" extends="json-default">
<action name="databaseJSON" class="com.krcl.rap.common.menu.action.DatabaseJSON">
<result type="json" >
<param name="root">databases</param>
</result>
</action>
</package>
<package name="default" namespace="/" extends="struts-default">
<action name="autoCompleterAction"
class="com.krcl.rap.common.menu.action.AutoCompleterAction"
method="display">
<result name="none">pages/autocompleter-json.jsp</result>
</action>
<action name="resultAction"
class="com.krcl.rap.common.menu.action.AutoCompleterAction" >
<result name="success">pages/result.jsp</result>
</action>
</package>
Use
<sx:autocompleter label="What's your favorite Database Server?"
href="%{databaseList}" name="yourFavDatabase"
id="yourFavDatabase"/>
in your jsp and
var yourFavDb=dojo.widget.byId('yourFavDatabase').getValue();
in your script to get the value. If you want to get the selected value in your Action class it will come on its own, once you submit the form.
I am testing the PrimeFaces example avaible at http://www.primefaces.org/showcase/ui/dialogLogin.jsf . I correctly imported PrimeFaces and JSF 2.1 in Eclipse Dyamic web project, but after filling the form when I try to do the login I get the following error:
HTTP Status 500 -
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: javax.el.MethodNotFoundException: Method not found: classi.LoginBean#ee03ec.login()
javax.faces.webapp.FacesServlet.service(FacesServlet.java:229)
root cause
org.apache.myfaces.view.facelets.el.ContextAwareMethodNotFoundException: javax.el.MethodNotFoundException: Method not found: classi.LoginBean#ee03ec.login()
org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:104)
javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:88)
javax.faces.event.ActionEvent.processListener(ActionEvent.java:51)
javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:418)
javax.faces.component.UICommand.broadcast(UICommand.java:103)
javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:1028)
javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:286)
javax.faces.component.UIViewRoot._process(UIViewRoot.java:1375)
javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:752)
org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:38)
org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:170)
org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:197)
root cause
javax.el.MethodNotFoundException: Method not found: classi.LoginBean#ee03ec.login()
org.apache.el.util.ReflectionUtil.getMethod(ReflectionUtil.java:225)
org.apache.el.parser.AstValue.invoke(AstValue.java:253)
org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:96)
javax.faces.event.MethodExpressionActionListener.processAction(MethodExpressionActionListener.java:88)
javax.faces.event.ActionEvent.processListener(ActionEvent.java:51)
javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:418)
javax.faces.component.UICommand.broadcast(UICommand.java:103)
javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:1028)
javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:286)
javax.faces.component.UIViewRoot._process(UIViewRoot.java:1375)
javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:752)
org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:38)
org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:170)
org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:117)
javax.faces.webapp.FacesServlet.service(FacesServlet.java:197)
note The full stack trace of the root cause is available in the Apache Tomcat/7.0.21 logs.
Apache Tomcat/7.0.21
LoginBean.java is:
package classi;
import java.awt.event.ActionEvent;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import org.primefaces.context.RequestContext;
#ManagedBean(name="loginBean")
#SessionScoped
public class LoginBean
{
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 void login(ActionEvent actionEvent) {
RequestContext context = RequestContext.getCurrentInstance();
FacesMessage msg = null;
boolean loggedIn = false;
if(username != null &&&& username.equals("admin") && password != null && password.equals("admin")) {
loggedIn = true;
msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Welcome", username);
} else {
loggedIn = false;
msg = new FacesMessage(FacesMessage.SEVERITY_WARN, "Login Error", "Invalid credentials");
}
FacesContext.getCurrentInstance().addMessage(null, msg);
context.addCallbackParam("loggedIn", loggedIn);
}
}
login.xhtml is:
<?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"
xmlns:p="http://primefaces.org/ui">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Insert title here</title>
</head>
<body>
<h:outputLink id="loginLink" value="javascript:void(0)" onclick="dlg.show()" title="login">
<p:graphicImage value="/images/login.png" />
</h:outputLink>
<p:growl id="growl" showDetail="true" life="3000" />
<p:dialog id="dialog" header="Login" widgetVar="dlg">
<h:form>
<h:panelGrid columns="2" cellpadding="5">
<h:outputLabel for="username" value="Username:" />
<p:inputText value="#{loginBean.username}"
id="username" required="true" label="username" />
<h:outputLabel for="password" value="Password:" />
<h:inputSecret value="#{loginBean.password}"
id="password" required="true" label="password" />
<f:facet name="footer">
<p:commandButton id="loginButton" value="Login" update=":growl"
actionListener="#{loginBean.login}"
oncomplete="handleLoginRequest(xhr, status, args)"/>
</f:facet>
</h:panelGrid>
</h:form>
</p:dialog>
<script type="text/javascript">
function handleLoginRequest(xhr, status, args) {
if(args.validationFailed || !args.loggedIn) {
jQuery('#dialog').effect("shake", { times:3 }, 100);
} else {
dlg.hide();
jQuery('#loginLink').fadeOut();
}
}
</script>
</body>
</html>
You have a bad import, replace :
import java.awt.event.ActionEvent;
with
import javax.faces.event.ActionEvent;
Also, is that &&&& working?! Maybe you have a special compiler if it doesn't give you error :)
if(username != null &&&& username.equals("admin") && password != null && password.equals("admin"))
I have a jsp as my view, which displays a form for adding a new user/ updating the user, if one is selected. I can't figure out how to prepopulate my form if a user is selected. I read about the solution using 2 actions, with the same form, one of which is just used to populate the fields, and on for submitting the data.
However, this doesn't work for me, as my action (the one defined in action attribute for the form) isn't called when loading the jsp (can't really explain this either, the menu and pages are defined in an xml file). I don't understand how to specify the second action in my jsp, and how to make sure that the action is called when first loading the jsp. I would prefer a solution not involving AJAX, if possible. Thanks.
Why do you want to go for AJAX, when you have the power of Struts. I have a simple example (it is tested) for you.
MyForm.java
package com.tusar.action;
import java.io.Serializable;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import javax.servlet.http.HttpServletRequest;
public class MyForm extends ActionForm implements Serializable{
private static final long serialVersionUID = 1043346271910809710L;
private String fullName = null;
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
/*This method will be called when you press the reset button
or load the form. You may want to populate the form here also*/
public void reset(ActionMapping mapping, HttpServletRequest request){
String reset = (String)request.getAttribute("myForm.reset");
if ((null != reset)|| ("true".equals(reset))) {
fullName = null;
}
}
}
MyFormSetupAction.java
package com.tusar.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public class MyFormSetupAction extends Action{
/*Set your form-bean properties here*/
#Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
MyForm hwForm = (MyForm) form;
hwForm.setFullName("tusar");
return mapping.findForward("success");
}
}
MyFormSuccessAction.java
package com.tusar.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
public class MyFormSuccessAction extends Action{
#Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
return mapping.findForward("success");
}
}
struts-config.xml
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.3//EN"
"http://struts.apache.org/dtds/struts-config_1_3.dtd">
<struts-config>
<!-- ==================== Form Bean Definitions -->
<form-beans>
<form-bean name="myForm" type="com.tusar.action.MyForm">
<form-property name="fullName" type="java.lang.String"/>
</form-bean>
<!-- ============= Global Forward Definitions -->
<global-forwards>
<!-- Default forward to "Welcome" action -->
<!-- Demonstrates using index.jsp to forward -->
<forward name="home" path="/home.do"/>
</global-forwards>
<!-- ===================== Action Mapping Definitions -->
<action-mappings>
<!-- This action will load the form-->
<action path="/home"
type="com.tusar.action.MyFormSetupAction"
name="myForm"
validate="false"
input="/WEB-INF/jsp/home.jsp">
<forward name="success" path="/WEB-INF/jsp/home.jsp" />
</action>
<!-- This action will evalutae the form and pass form data to
success page-->
<action path="/successAction"
type="com.tusar.action.MyFormSuccessAction"
name="myForm"
validate="true"
input="/WEB-INF/jsp/home.jsp">
<forward name="success" path="/WEB-INF/jsp/success.jsp" />
</action>
</action-mappings>
<!-- ============= Message Resources Definitions -->
<message-resources parameter="MessageResources" />
</struts-config>
home.jsp
<%# taglib uri="http://struts.apache.org/tags-bean" prefix="bean" %>
<%# taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<%# taglib uri="http://struts.apache.org/tags-logic" prefix="logic" %>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# page isELIgnored="false"%>
<html>
<head>
<title>Struts 1</title>
</head>
<body>
<html:form action="/successAction.do">
Name:
<html:text property="fullName"></html:text>
<html:submit value="Next"></html:submit>
<html:reset value="Cancel"></html:reset>
</html:form>
</body>
</html>
success.jsp
<%# taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<%# taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%# taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# page isELIgnored="false"%>
<html>
<head>
<title>Successful !</title>
</head>
<body>
<h3>Your details:</h3>
Name:
<bean:write name="myForm" property="fullName" />
</body>
</html>
Everytime you call the home.do action, the fullName property is populated with "tusar". Just comment if you need any further association, I'll be happy to help you. Thanks!
There should be an action called when selecting the user. The properties of that user should be copied into the action form before returning the action forward.
Without any configuration information it's difficult to help beyond that.
I'm trying to output a list of strings to a jsp page using struts 2. The template file is something like this:
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%# taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<s:iterator value="vars">
<p><s:property /></p>
</s:iterator>
</body>
</html>
The corresponding java action file is:
public class TestAction extends ActionSupport {
private static final long serialVersionUID = 1L;
List<String> vars = null;
public List<String> getVars() { return vars; }
public void setVars(List<String> vars) { this.vars = vars; }
#Override
public String doExecute() throws Exception {
vars = new ArrayList<String>();
vars.add("Users");
vars.add("Organizações");
vars.add("Eventos");
vars.add("Locais");
return SUCCESS;
}
}
The problem is that, the result is:
Users
Organizações
Eventos
Locais
(source code)
<p>Users</p>
<p>Organizações</p>
<p>Eventos</p>
<p>Locais</p>
which I believe it means that I'm receiving the strings encoded with something that's not UTF-8. Any ideas on how to solve this?
This is very late reply, but I want to update this to help, somebody who stuck with this bug. Add following lines to your jsp to resolve the issue.
<%# page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<s:property escapeHtml="false"/>
Depending on your version of struts 2
Older: (this is deprecated in newer versions)
<s:property escape="false"/>
Newer: (not sure which version this was introduced)
<s:property escapeHtml="false"/>
I have a problem with the propagation of a long running conversation when I redirect the view by the handleNavigation() method. Here is my test code:
I have a conversationscoped bean and two views:
conversationStart.xhtml is called in Browser with URL
http://localhost/tests/conversationStart.jsf?paramTestId=ParameterInUrl
<!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">
<f:metadata>
<f:viewParam name="paramTestId" value="#{conversationTest.fieldTestId}" />
<f:event type="preRenderView" listener="#{conversationTest.preRenderView}" />
</f:metadata>
<h:head>
<title>Conversation Test</title>
</h:head>
<h:body>
<h:form>
<h2>Startpage Test Conversation with Redirect</h2>
<h:messages />
<h:outputText value="Testparameter: #{conversationTest.fieldTestId}"/><br />
<h:outputText value="Logged In: #{conversationTest.loggedIn}"/><br />
<h:outputText value="Conversation ID: #{conversationTest.convID}"/><br />
<h:outputText value="Conversation Transient: #{conversationTest.convTransient}"/><br />
<h:commandButton action="#{conversationTest.startLogin}" value="Login ->" rendered="#{conversationTest.loggedIn==false}" /><br />
<h:commandLink action="/tests/conversationLogin.xhtml?faces-redirect=true" value="Login ->" rendered="#{conversationTest.loggedIn==false}" /><br />
</h:form>
<h:link outcome="/tests/conversationLogin.xhtml" value="Login Link" rendered="#{conversationTest.loggedIn==false}">
<f:param name="cid" value="#{conversationTest.convID}"></f:param>
</h:link>
</h:body>
</html>
The Parameter is written to the beanfield and displayed in the view correctly. There are 3 different possibilities to navigate to the next View. All 3 work fine. The beanfield shows up the next view (conversationLogin.xhtml) too:
<!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">
<h:head>
<title>Conversation Test</title>
</h:head>
<h:body>
<h:form>
<h2>Loginpage Test Conversation with Redirect</h2>
<h:messages />
<h:outputText value="Testparameter: #{conversationTest.fieldTestId}"/><br />
<h:outputText value="Logged In: #{conversationTest.loggedIn}"/><br />
<h:outputText value="Conversation ID: #{conversationTest.convID}"/><br />
<h:outputText value="Conversation Transient: #{conversationTest.convTransient}"/><br />
<h:commandButton action="#{conversationTest.login}" value="Login And Return" /><br />
</h:form>
</h:body>
</html>
When I return to the Startpage by clicking the button the conversation bean still contains all values. So everything is fine. Here is the bean:
package test;
import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.faces.event.ComponentSystemEvent;
import javax.inject.Inject;
import javax.inject.Named;
#Named
#ConversationScoped
public class ConversationTest implements Serializable{
private static final long serialVersionUID = 1L;
final String CONVERSATION_NAME="longRun";
#Inject Conversation conversation;
private boolean loggedIn;
private String fieldTestId;
#PostConstruct
public void init(){
if(conversation.isTransient()){
conversation.begin(CONVERSATION_NAME);
System.out.println("New Conversation started");
}
loggedIn=false;
}
public String getConvID(){
return conversation.getId();
}
public boolean isConvTransient(){
return conversation.isTransient();
}
public boolean getLoggedIn(){
return loggedIn;
}
public String startLogin(){
return "/tests/conversationLogin.xhtml?faces-redirect=true";
}
public String login(){
loggedIn=true;
return "/tests/conversationStart.xhtml?faces-redirect=true";
}
public void preRenderView(ComponentSystemEvent ev) {
// if(!loggedIn){
// System.out.println("Will redirect to Login");
// FacesContext ctx = FacesContext.getCurrentInstance();
// ctx.getApplication().getNavigationHandler().handleNavigation(ctx, null, "/tests/conversationLogin.xhtml?faces-redirect=true");
// ctx.renderResponse();
// }
}
public void setFieldTestId(String fieldTestId) {
System.out.println("fieldTestID was set to: "+fieldTestId);
this.fieldTestId = fieldTestId;
}
public String getFieldTestId() {
return fieldTestId;
}
}
Now comes the problem
As soon as I try to redirect the page in the preRenderView method of the bean (just uncomment the code in the method), using handleNavigation() the bean is created again in the next view instead of using the already created instance. Although the cid parameter is propagated to the next view !
Has anybody an idea what's wrong ?
best regards
Thomas