I have a JSP which has below tags the data in resultsList fed in some action and forwarded to below jsp here I would like to get the data back into the other action based on the checkbox selection. Please help, can do using Struts1 but don't like to turn back to Struts1 since started using Struts2.
<display:table class="displaytag" id="row" style="font-size:1.4em;" name="resultsList" requestURI="/SomePath.action">
<display:column property="businessType" title="Business Type"></display:column>
<display:column property="structure" title="Structure"></display:column>
<display:column property="tradeSubType" title="Trade Sub Type"></display:column>
<display:column property="businessGroup" title="Business Group"></display:column>
<display:column title="Select To Copy" align="center">
<s:checkbox name="selectToCopy" fieldValue="false" value="false" label="Check Me To Download"></s:checkbox>
</display:column>
</display:table>
The data will be fetched in one action and forwarded to the jsp where jsp contains above display tag and now I need to submit the form and action should receive the checked information to process further. Any help here is really appreciated, I can do it using Struts1 no doubt but would like to continue in Struts2.
I'm guessing your action class sends some domain objects from this type:
public class MyData {
private Integer id;
private String businessType;
//other params
//getter/setters
}
And your action class, that ist invoked before accessing the displaytag jsp page has a list of objects form type MyData:
public class MyDisplayTagAction extends ActionSupport {
private List<MyData> myDataList;
//other params
//getter/setter
public String execute() {
myDataList = getMyDataListFromSomewhere();
return SUCCESS;
}
}
The JSP should contain a form and a submit button. Moreover you have to define every data you want to send back as a field in that form. If the user is not allowed to change them, use hidden fields. The #attr.row.id access printing that id to the value. #attr is from ognl to access the variable row defined from displaytag. (For more info: Struts OGNL)
<s:form action="myStrutsPostAction" method="post">
<display:table name="myDataList" uid="row">
<display:column>
<s:checkbox name="resultsList[%{#attr.row_rowNum - 1}].selectToCopy" id="check%{#attr.row_rowNum - 1}" value="%{#attr.row.selectToCopy}"/>
</display:column>
<display:column>
<input type="hidden" name="resultsList[<s:property value='%{#attr.row_rowNum - 1}'/>]" value="<s:property value='%{#attr.row.businessType}' />"/>
<s:property value="%{#attr.row.businessType}"/>
</display:column
</display:table>
<s:submit>
</s:form>
The post action class (the one that takes the form request) should contain a list, that was defined in the <s:form> and struts will set only the the data into this list.
public class MyPostAction extends ActionSupport {
private List<MyData> resultsList = new ArrayList<>();
//getter/setter
}
Related
I am migrating from struts 1 to struts 2 framework. Based on struts 1 framework parameter=method attribute, I am able to execute different methods using the same jsp page by adding a hidden field "method".
How do I achieve the same in struts 2?
My Action class:
public class MyAction extends ActionSupport {
public String methodA() {
return "a";
}
public String methodB() {
return "b";
}
}
My JSP page
<s:form action="MyAction">
<s:select label="Method Name"
name="method"
headerKey="-1" headerValue="Select Method"
list="#{'01':'A', '02':'B', [...]}"
value="selectedMethod"
required="true"
/>
<s:submit type="button" name="submit" />
</s:form>
You could achieve that by changing the "action" url before submitting.
Check out Wildcard Method and Dynamic Method Invocation here
Though, the dynamic Method Invocation can be considered a Security Vulnerability
This might be simple problem, but I am not able to figure it out.
Here is my xhtml page:
*update p tag here, I am using primefaces*
<h:outputLabel for="Number" value="Number(100-800):" />
<h:inputText id="number" name="number_Name" value="#{validationView.number}" label="Number">
<f:validateDoubleRange minimum="100" maximum="800" />
</h:inputText>
<p:commandButton value="S-ubmit" name="submit" actionListener="#{userBean1.method1}" ajax="false" icon="ui-icon-check" validateClient="true"/>
This is my managed bean
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import org.primefaces.context.RequestContext;
#ManagedBean(name="userBean1")
#SessionScoped
public class UserBean1
{
public void method(){
String value = FacesContext.getCurrentInstance().
getExternalContext().getRequestParameterMap().get("number_Name");
System.out.println("Value: "+value);
}
public void method1(ActionEvent event) {
String param = (String) event.getComponent().getAttributes().get("number_Name");
System.out.println("Param: "+param);
}
}
I tried both methods and in both cases it is printing null output. I imported el-impl-2,2.jar into my build path. I am using primefaces 5.1 and Tomcat7
First, there is no attribute called name in h:inputText, if you really need to use that attribute, please refer to that question for more details: How to specify name attribute in h:inputText?
So I will assume your h:inputText looks something like this:
<h:inputText id="number" value="#{validationView.number}" label="Number">
<f:validateDoubleRange minimum="100" maximum="800" />
</h:inputText>
Second, in the externalContext().getRequestParameterMap().get(key) the key refers to the request parameters names included in the current request, which corresponds to the client ID (because name is autogenerated by JSF based on the client ID), so if for example your h:inputText is inside a form whose id= "form" then your client ID will be "form:number", More about When and how is clientID generated in JSF?
You can use your first method like this:
public void method(){
String value = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("form:number");
System.out.println("Value: "+value);
}
In case you only know the component id of your h:inputText and not it's client ID please refer to: Find component by ID in JSF
Finnaly, I think that the best way is to use the following method which make you benefit from the ActionEvent:
public void method(ActionEvent event) {
String param = (String) ((UIInput) event.getComponent().findComponent("form:number")).getValue();
System.out.println("Param: "+param);
}
NB: please note that event.getComponent() gets the component that triggered the event which is p:commandButton (in your case) and not the h:inputText
I have written a piece of code to put two pairs of radio button in a *.xhtml page of a JSF project built in JSF2.0, Jboss As 7.1.1 final and JDK 6.0, PrimeFaces 3.4.2.
<h:panelGrid columns="2">
<h:selectOneRadio value="#{calendarBean.radioFirst}">
<f:selectItem id="morning" itemValue="morning" itemLabel="Morning"/>
<f:selectItem id="afternoon" itemValue="afternoon" itemLabel="Afternoon"/>
</h:selectOneRadio>
<h:selectOneRadio style="padding-left: 170px" value="#{calendarBean.radioSecond}">
<f:selectItem id="noon" itemValue="noon" itemLabel="Noon"/>
<f:selectItem id="endofday" itemValue="endofday" itemLabel="End Of Day"/>
</h:selectOneRadio>
</h:panelGrid>
The Bean is:
private String radioFirst="morning";
private String radioSecond="endofday";
public String getRadioFirst() {
return radioFirst;
}
public void setRadioFirst(String radioFirst) {
this.radioFirst = radioFirst;
}
public String getRadioSecond() {
return radioSecond;
}
public void setRadioSecond(String radioSecond) {
this.radioSecond = radioSecond;
}
I have written a method to invoke on a Action Event where I want to have the values of the radio button selected. when the method invokes I get the value of the radio buttons as "morning" and "endofday" as these two are the initial values of the bean variables.
private String radioFirst="morning";
private String radioSecond="endofday";
But if I change the radio button options, I don't get the updated values, its the same old initial values. How can I get the changed values? Please help!
Three things
Don't use the session scope for this usage scenario. This will go completely wrong when your users open the same page in more than one tab. Use request scope or view scope.
Use a regular action instead of an action listener, and don't provide the radio button values as attributes. This makes no sense. The selectOneRadio components will set the updated values on your backing bean. When your action method is invoked, you will have access to those values via the instance fields of your bean.
Leave out the window.reload. If you need a full page refresh after the action, set ajax to false on the p:commandButton or use an h:commandButton.
You should modify your action button like this :
<p:commandButton actionListener="#{userLeaveBean.addAppliedLeave}" styleClass="apply_button" value="Create Leave">
<f:attribute name="userId" value="#{employee.name}"/>
</p:commandButton>
As #MikeBraun suggested, remove the window.reload(). If you want to refresh something, you could do it by using the update attribute from the p:commandButton.
And modify your bean according to this :
#ManagedBean
#SessionScoped // Could probably be moved to #RequestScoped or #ViewScoped
public class UserLeaveBean
{
#ManagedProperty(value="#{calendarBean}")
CalendarBean calendarBean;
public void setCalendarBean(CalendarBean calendarBean)
{
this.calendarBean = calendarBean;
}
public void addAppliedLeave(ActionEvent event)
{
System.out.println("Radio 1 : " + calendarBean.getRadioFirst());
System.out.println("Radio 2 : " + calendarBean.getRadioSecond());
}
}
The ManagedProperty will get the other bean accessible for you by injecting it inside the current one. Use the proper scope, probably you are using SessionScoped because you are using window.reload().
Important : the ManagedProperty bean must be at least scoped the same length as the other bean.
Read more :
Injecting Managed Beans in JSF 2.0
PrimeFaces Showcase - commandButton
I´m newbie to Struts FW and JSP at all. I have a couple of list rows generated through <s: iterator>. I wanted to get this list sorted according to each column (name, address, etc.)
so I added <s:sort> tag and created to comparator classes (name, address).
Now, I wonder how can I pass through the URL parameter which type of comparator I want to use?
The code looks like this:
<s:bean name="ois.AlphabetComparator" var="alphabetComparator" />
<s:bean name="ois.AddressComparator" var="addressComparator" />
<s:url id="place" action="getAllPlaces">
<s:param name="sortStyle">#addressComparator
</s:param>
</s:url>
<s:a href="%{place}">
<s:sort comparator="?how to pass url parameter here?" source="places">
<s:iterator status="status">
...
</s:iterator>
</s:sort>
EXAMPLE 1
Use #parameters['sortStyle'] to obtain the value of the parameter. First create URLs with distinct values for the parameter sortStyle :
<s:url id="place_sortByAddress" action="getAllPlaces">
<s:param name="sortStyle">ois.AddressComparator
</s:param>
</s:url>
<s:url id="place_sortByAlphabet" action="getAllPlaces">
<s:param name="sortStyle">ois.AlphabetComparator
</s:param>
</s:url>
Then add links (assuming the goal is to sort the list in various ways depending on the selected link) :
<s:a href="%{place_sortByAddress}">Sort by Adress</s:a></br>
<s:a href="%{place_sortByAlphabet}">Sort by Alphabet</s:a></br>
The next step is a little more tricky. If there is actually a parameter called sortStyle, then a new bean is created from the value of the parameter sortStyle. This bean will be the comparator class to sort items in the list.
<table>
<tbody>
<s:if test='%{#parameters["sortStyle"] != null}'>
<s:bean name='%{#parameters["sortStyle"]}' var="comparatorClass" />
<s:sort comparator="#comparatorClass" source="places">
<s:iterator>
<tr>
<td><s:property value="name"/></td>
<td><s:property value="adress"/></td>
</tr>
</s:iterator>
</s:sort>
</s:if>
</tbody>
</table>
For example, if you clicked on the first link, your comparator class would be ois.AddressComparator.
This solution should work fine, but it relies on the use of the parameter, that the user can see and modify, and that we must also check directly in the jsp with a "if" tag.
Checks and changes could be handled on server-side by the Action class. It may be improved thanks to struts.
EXAMPLE 2
in the JSP, use struts s:form tag. Create submit buttons for this form with s:submit tags. Each submit button calls a different method of the Action class, one for each way to sort the list.
<s:form action="getAllPlaces">
<!-- Submit buttons -->
<s:submit key="messages.submit" action="getAllPlaces" method="sortByAdress"/>
<s:submit key="messages.submit" action="getAllPlaces" method="sortByAlphabet"/>
Then create a table for displaying items of the list. As in the first example, a bean is created from a parametric value. Instead of a parameter sent in the URL, an attribute is set by the Action class and is used in the JSP. Let the Action class handle controls and changes on this attribute.
<!-- Table for list -->
<table>
<tbody>
<!-- Create a new bean with parametric class name -->
<s:bean name="%{#attr['comparatorClassName']}" var="comparatorClass" />
<s:sort comparator="#comparatorClass" source="places">
<s:iterator>
<tr>
<td><s:property value="name"/></td>
<td><s:property value="adress"/></td>
</tr>
</s:iterator>
</s:sort>
</tbody>
</table>
</s:form>
There, is the code from the Action class. It has a comparatorClassName attribute with a default value. The value changes each time you call for methods sortByAlphabet() or sortByAddress.
public class GetAllPlacesAction extends ActionSupport{
/**
*
* #return
*/
private List<PlaceBean> places = new ArrayList<PlaceBean>();
// Set default comparator class name
private String comparatorClassName = "ois.AlphabetComparator";
public String execute()
{
// Populate Stub List
GetAllPlacesAction.populateStubList(this.places);
// Forward
return SUCCESS;
}
public String sortByAdress()
{
// Refresh comparator class name
this.comparatorClassName = "ois.AddressComparator";
// Populate Stub List
GetAllPlacesAction.populateStubList(this.places);
// Forward
return SUCCESS;
}
public String sortByAlphabet()
{
// Refresh comparator class name
this.comparatorClassName = "ois.AlphabetComparator";
// Populate Stub List
GetAllPlacesAction.populateStubList(this.places);
// Forward
return SUCCESS;
}
private static void populateStubList(List<PlaceBean> p_places)
{
// Populate Stub List
p_places.add(new PlaceBean("Gabriel", "USA"));
p_places.add(new PlaceBean("Kim", "South Corea"));
p_places.add(new PlaceBean("Khofi", "Ghana"));
p_places.add(new PlaceBean("Abel", "Germany"));
}
This example may be improved by more experienced users. But for the moment it's enough to display a list, and two buttons to change the way its items are sorted. Good luck ;-) #+
<s:sort comparator="?how to pass enum class here?" source="places">
<s:iterator status="status">
...
</s:iterator>
My enum class is -->
package com.vijay.util;
public enum ServiceComparator {
displayNameAndEffectiveAt{
#Override
public int compare(ServiceContract sc0, ServiceContract sc1) {
//code
}
};
}
Today I'm using a servlet to receive a POST from a HTML page and then redirecting to my JSF page.
This is my actual Servlet:
public class CommInServlet extends HttpServlet {
private String reportKey;
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getSession(true).setAttribute("reportKey", req.getParameter("reportkey"));
req.getRequestDispatcher("main.xhtml").forward(req, resp);
}
}
HTML post page:
<html>
<head />
<body>
<form action="Filtro" method="post">
<input type="text" size="120" name="reportkey" value="XXXXXXXXXXXX" />
<input type="submit" value="doPost" />
</form>
</body>
</html>
Is it possible to post directly to my JSF page (ManagedBean)? How?
I want to replace the Servlet for something... better.
Sure you can. Most JSF requests are POSTs anyway, so if you use the path to the JSF page you're intending to handle the POST request, you can then get the parameter within a managed bean that is backed by that page OR get the parameter within the page itself.
Within a managed bean:
#PostConstruct
public void initMyBean(){
/**This map contains all the params you submitted from the html form */
Map<String,String> requestParams = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
requestParams.get("reportKey");
}
OR
within the managed bean have
#ManagedProperty(value="#{param.reportKey}")
String reportKey;
//getter and setter of course!
The method you've annotated with #PostConstruct will be executed after the managed bean has been instantiated. The above will give you access within your managed bean.
If you need the value within your page first however, you can have this in your page (preferably at the top)
<f:metadata>
<f:viewParam name="reportKey" value="#{backingBean.reportKey}" required="true"/>
</f:metadata>
Notice how you can perform validations on the parameter from within your view. Pretty cool feature.
Just be sure and set your html form action attribute to the path of the JSF view.