How private fields accessible on jsp page in struts 2.x? - java

Hello every one I am working with struts 2.x and very new for this framework . I follow list of tutorials and steps and my application working properly but there is one thing which is not clear to me Like when I declare one private field in my action class and using struts tag that private field is accessible to the jsp page . So how it happen that is not understandable for me:
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="default" namespace="/home" extends="struts-default">
<action name="message" class="com.csc.action.MessageAction">
<result name="hello">/hello.jsp</result>
<result name="bye">/bye.jsp</result>
</action>
<action name="add" class="com.csc.action.Mathaction">
<result name="success">/hello.jsp</result>
<result name="fail">/bye.jsp</result>
</action>
</package>
</struts>
MessageAction.java
package com.csc.action;
import com.csc.service.BussniessServ;
public class MessageAction {
private String result;
private String value;
private String fstvalue;
private String scndvalue;
public String getFstvalue() {
return fstvalue;
}
public void setFstvalue(String fstvalue) {
this.fstvalue = fstvalue;
}
public String getScndvalue() {
return scndvalue;
}
public void setScndvalue(String scndvalue) {
this.scndvalue = scndvalue;
}
// method which get value from input parameter
public String getValue() {
return value;
}
// method which show the value of input parameter
public void setValue(String value) {
this.value = value;
}
// method which run as default and execute
public String execute() {
BussniessServ serv = new BussniessServ();
setMessag(serv.Addition(fstvalue, scndvalue));
return "hello";
}
// method to show message on jsp page
public String getResult() {
return result;
}
// method for save message
public void setResult(String result) {
this.result = result;
}
}
Result.jsp
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# 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=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<s:property value="result"/>
</body>
</html>

Struts uses reflection to find a method that returns that variable. For example, if you have a variable called result then Struts looks for a method called getResult() and calls it to obtain a value.
Also, if you want properties to be accessible in the JSP you have to make sure that you name these methods correctly. A property called "abc" would match the method getAbc() (unless it is a boolean, in which case would match the method isAbc() instead).

OGNL does not actually require accessors to be present, although this varies by version–earlier versions (~S2.0) required accessor methods. Later versions (~S2.1+) "helpfully" removed this restriction.
Public properties with private getters also works, although it's obviously pathological.
IMO it was a step backwards for data encapsulation.
It may be configurable in later/current versions of OGNL, I'm not sure.

Related

SessionMap is null after implementing SessionAware interface in Struts 2

I am implementing SessionAware in my action class. But, the sessionMap is always null. The setSession method doesn't seem to be called.
Here is the code. In the execute method, the sessionMap is always null.
What am I doing wrong?
Action class:
public class HelloWorldAction extends ActionSupport implements SessionAware
{
private static final long serialVersionUID = 544659976107736338L;
private Map<String, Object> sessionMap;
private String name;
public String execute() throws Exception {
if(sessionMap != null) {
sessionMap.put("TestID", "Test");
}
return "success";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public void setSession(Map<String, Object> arg0) {
this.sessionMap = arg0;
}
}
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>
<include file="struts-default.xml"/>
<package name="my-projects" namespace="/" extends="struts-default">
<action name="hello"
class="com.my.projects.actions.HelloWorldAction"
method="execute">
<result name="success">/jsp/HelloWorld.jsp</result>
</action>
You can try this to get Session Map
Map session = ActionContext.getContext().getSession();
and remove below line
<include file="struts-default.xml"/>
The struts-default.xml is the name of the default configuration file used by the Struts in it's core library. You should not use this name to your custom configurations.
A base configuration file named struts-default.xml is included in the struts2-core.jar file. This file is automatically included into struts.xml file to provide the standard configuration settings without having to copy them.
To exclude the struts-default.xml or to provide your own version, see the struts.configuration.files setting in struts.properties.
Remove this line from the configuration:
<include file="struts-default.xml"/>
This file can override the default settings such as the interceptor stack and your application won't work in the default mode.
By default it's configured to populate the session to the actions that implement SessionAware.

How to maintain a list of objects in Java Server Faces 2

I have a JSF2 application that should show a page where a number os items must be added in a list. The user wants to add those items, set some properties of them and finally persist them all together, in a single save operation.
The domain object that should be handled by this page looks like this:
public class Item {
private long id;
private String name;
private Item previous;
public Item() { }
public Item(Item previousItem) {
this.previous = previousItem;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Item getPrevious() {
return previous;
}
}
The ItemBean class looks like this:
#ManagedBean
public class ItemBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<Item> items = new ArrayList<Item>();
public List<Item> getItems() {
if(items.size()==0) {
items.add(new Item()); // adding the first item
}
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
public void addItem(Item previousItem) {
Item newItem = new Item(previousItem);
items.add(newItem);
}
public void save() {
...
}
}
The view is a xhtml file that looks like this:
<?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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets">
<body>
<ui:composition template="/templates/layout.xhtml">
<ui:define name="content">
<h2>Items</h2>
<fieldset>
<legend>Items being added</legend>
<ui:repeat value="#{itemBean.items}" var="item">
<div>
<h:outputLabel value="Item" for="name" />
<h:inputHidden value="#{item.id}" />
<h:inputText id="name" value="#{item.name}" />
<h:commandLink action="#{itemBean.addItem(item)}">Add</h:commandLink>
</div>
</ui:repeat>
</fieldset>
<div class="options">
<h:commandButton action="#{itemBean.save}" value="Save"/>
<div class="clear border-bottom"></div>
</div>
</ui:define>
</ui:composition>
</body>
</html>
Notice that in order to add a new item, the current one must be sent to satisfy business rules.
The problem is that I can add a second item with no problema, but when I click in the Add link next to the second item, the page is rerendered with one single item, just like it was in the beggining.
Unfortunatelly, I can't see what's missing to make it work, even after reading a lot of posts, pages and some book chapters.
Update 1
I was asked about the kind of scope used with this bean. It´s de default scope (#RequestScoped). I was trying to avoid using #SessionScoped for the sake of scalability, but in this particular case, I´m not sure I have a choice. Anyone with more experience could give me tip?
What is the scope of your ManagedBean ?
Since you didn't post any persistence code, I suppose the items List only exists througout your Bean's life. This means that if your Bean is #ViewScoped or #RequestScoped, your items cease to exist after you submit your form.
You need use an ajax component, something like:
<fieldset id="list">
<legend>Items being added</legend>
<ui:repeat value="#{itemBean.items}" var="item">
<div>
<h:outputLabel value="Item" for="name" />
<h:inputHidden value="#{item.id}" />
<h:inputText id="name" value="#{item.name}" />
<h:commandLink action="#{cargoBean.addItem(item)}">
<f:ajax render="list" />
Add
</h:commandLink>
</div>
</ui:repeat>
</fieldset>
I see no form in your xhtml page like :
<h:form>
<ui:repeat>
<h:inputBlabla/>
</ui:repeat>
</h:form>
A form is needed while using h:input fields.

Primefaces - methods not listed in 'actionListener'

I'm using Primefaces 4.0. I have a method in the Bean class, and I want to call it in a commandButton. When using Primeface's commandButton, Eclipse (Kepler) code completes the bean's name, as expected, but does not list the methods. The method is called, but there's no code completion for it. If I use the default commandButton, all the methods are listed (including 'equals' and 'hashCode').
In short, I'm getting code completion for some parts of the Primefaces tags, but not everything.
EDIT:
XHTML
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form>
<p:inputText value="#{testBean.name}" id="name" />
<p:commandButton value="Print name" actionListener="#{testBean.printName}" />
</h:form>
</h:body>
</html>
Bean
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean
#RequestScoped
public class TestBean implements Serializable {
private static final long serialVersionUID = -4705029823018566258L;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void printName(){
System.out.println(name);
}
}
printName() isn't a Listener object. You need to have a Listener object handle the call and have the action done from there.
Here is some documentation to help you understand.
EDIT
This should work:
<p:commandButton>
<f:actionListener/>
</p:commandButton>
If you have included the tag library and have downloaded the JAR and placed it in your /WEB-INF/lib :
<%# taglib prefix="f" uri="http://java.sun.com/jsf/core"%>

Spring MVC navigation

I want to create simple navigation with Spring MVC, so far I got this:
#Controller
#RequestMapping("/secure")
public class NavigationController {
#ModelAttribute("myPath/operation")
public OperationForm getOperationForm() {
return new OperationForm();
}
#RequestMapping("/myPath/operation")
public String processOperationPage() {
//Some logic goes here
return "myPath/operation";
}
#ModelAttribute("myPath/configuration")
public ConfigurationForm getConfigurationForm() {
return new ConfigurationForm();
}
#RequestMapping("/myPath/configuration")
public String processConfigurationPage(Map model) {
return "myPath/configuration";
}
}
And in my JSP page:
Configuration
Operation
Is this solution for navigating through pages efficient? Could you suggest me some other ways to make the navigation? I am sure there is but I can't find anything on the internet.
For the jsp's this is a bit neater imho :
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
...
<c:url var="config" value="/secure/myPath/configuration.htm"/>
Configuration

Using jsp:setProperty to set one bean in other bean

I would like to know how to use jsp:setProperty in the following scenario. Here is a simple example of two java classes.
public class MyExample {
private MyName myNameExample = new MyName();
public MyExample() {}
public MyName getMyNameExample() {
return myNameExample;
}
public void setMyNameExample(MyName setTo) {
myNameExample = setTo;
}
}
public class MyName {
private String firstName;
public MyName() {}
public String getFirstName() {
return firstName;
}
public String setFirstName(String setTo) {
firstName = setTo;
}
}
I was trying to use something like:
<jsp:useBean id="example" class="MyExample" scope="page"/>
<jsp:setProperty name="example" property="????" value="aFirstName"/>
The important part here is that I want to reference the MyName object from within MyExample. Therefore, creating a bean to directly access MyName will not help me. So I am not looking for this answer:
<jsp:useBean id="name" class="MyName" scope="page"/>
<jsp:setProperty name="name" property="firstName" value="aFirstName"/>
You could just create both beans and set one in other by ${}.
<jsp:useBean id="myName" class="MyName" scope="page" />
<jsp:setProperty name="myName" property="firstName" value="aFirstName" />
<jsp:useBean id="myExample" class="MyExample" scope="page" />
<jsp:setProperty name="myExample" property="myExampleName" value="${myName}" />
Unrelated to the concrete problem, I'd suggest to invest time in learning servlets and MVC. The above is a pretty old fashioned and tight-coupled way of controlling the models in the view.
Note that using packageless classes may not work in all circumstances (since they are invisible for normal classes inside a package). Only in certain Apache Tomcat configurations it will work. Rather put your classes inside a package in order to be not dependent of that.

Categories