I have following UI part on JSF - it's simple search form with input field and submit:
<h:form>
<h:commandButton action="#{operation.found}" value="#{msg.search}" />
<h:inputText name="searchParam"/>
</h:form>
And correspondingly, on backend, i attempt to get value of input field next way:
public List<Store> getFound() {
String name = (String) FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap().get(
"searchParam");
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();
HibernateTemplate hbt = new HibernateTemplate();
hbt.setSessionFactory(sessionFactory);
foundStores = hbt.find(BEAN_PATH + " WHERE name = ?",
new Object[] { name });
return foundStores;
}
And null name is passed to backend.
It seems that problem in .jsf part, but from first glance looks ok...
You must point the <h:inputText> to a managed-bean property:
<h:inputText name="searchParam" value="#{searchBean.searchParam}" />
and define in your bean:
private String searchParam;
public String getSearchParam() {..}
public void setSearchParam(String searchParam) {..}
and then use the searchParam in your getFound() method;
Of course, you need to have the bean defined as managed bean, but I assume you have done it:
<managed-bean>
<managed-bean-name>searchBean</managed-bean-name>
<managed-bean-class>mypackage.SearchBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
You can check a JSF tutorial (like this, for example)
Related
Including libs/foundation/global.jsp at the top of my jsp winds up calling <cq:defineObjects />, which winds up instantiating the slingRequest or currentNode variables that I can use within my scriptlets. However, I am creating beans and including them like so
<jsp:useBean id="myBean" class="com.foo.bar.MyBean" />
<jsp:setProperty name="myBean" property="request" value="<%= slingRequest %>" />
and in my bean I have a getter/setter
public SlingHttpServletRequest getRequest() {
return resource;
}
public void setRequest(SlingHttpServletRequest request) {
this.resource = resource;
}
Here I'm instantiating the bean and passing in a reference to the current request.
My quesion is, how can I avoid having to pass in this parameter? Is there a way to get a reference to the current request via some sort of static context so that I can set the bean property in the constructor?
There is no way to statically pass the request to newly created bean (and there can't be, as there might be many requests at the same time, so we can't have a shared static variable to store it). You may create a scriptlet:
<% pageContext.setAttribute("myBean", new MyBean(slingRequest)); %>
MyBean property: ${myBean.property}
or get rid of the beans and use one of the frameworks mentioned by Thomas:
Sling Models,
Slice,
NEBA.
You should never pass your request object to Bean classes. I agree with Thomas and Tomek's answer.
But starting to use a framework all of a sudden in the middle of a project to solve this issue is an overkill.
The basic idea here is that the request object should not be passed around. Rather, you should get the resource URI from the request and pass that to your Bean classes.
Additionally you can pass ResourceResolver object to get any resource in your Bean class.
My sample code would look something like this :
<jsp:useBean id="myBean" class="com.foo.bar.MyBean" />
<jsp:setProperty name="myBean" property="resourcePath" value="<%= slingRequest.getResourceURI() %>" />
<jsp:setProperty name="myBean" property="resourceResolver" value="<%= slingRequest.getResourceResolver() %>" />
and my Bean class method would be like this :
public SlingHttpServletRequest getResourcePath() {
return resourcePath;
}
public void setResourceResolver(String resourcePath) {
this.resourcePath = resourcePath;
}
public SlingHttpServletRequest getResourceResolver() {
return resolver;
}
public void setResourceResolver(ResourceResolver resovler) {
this.resolver = resolver;
}
Now in your bean class, you can form the resource object using the resourcePath and ResourceResolver like this :
Resource resource = resourceResolver.resolve(resourcePath);
I will like to edit a list of items in the same page. Each item should be edited using a separate form. I am creating a h:form within ui:repeat. Only when the last form is submitted, the user input is applied to the managed bean. For all other forms, user input is not applied to the model.
#ManagedBean
public class Controller {
Logger logger = Logger.getLogger("TestWeb");
private List<Customer> customerList;
public List<Customer> getCustomerList() {
if (customerList == null) {
customerList = new ArrayList<Customer>();
customerList.add(new Customer("Daffy Duck", "daffy#example.com"));
customerList.add(new Customer("Bugs Bunny", "bugs#example.com"));
customerList.add(new Customer("Samity Sam", "sam#example.com"));
}
return customerList;
}
public String updateCustomer(Customer c) {
logger.info("Updating: " + c.getName());
return null;
}
}
In the view, I have
<ui:repeat var="c" value="#{controller.customerList}">
<h:form>
<h3>Edit Customer</h3>
Name: <h:inputText value="#{c.name}"/><br/>
E-mail: <h:inputText value="#{c.email}"/><br/>
<h:commandButton value="Update"
action="#{controller.updateCustomer(c)}"/>
</h:form>
</ui:repeat>
I search for hours without any solution. What will be the correct way to do this? I can hack it by using a single form and using a ui:repeat within it. But there are many issues with that and I will rather not take that route. Thanks.
This is a bug in state saving of <ui:repeat> in Mojarra. There are several similar issue reports at http://java.net/jira/browse/JAVASERVERFACES, among others issue 2243.
You have basically 2 options: use another iterating component (e.g. <c:forEach>, <h:dataTable>, <t:dataList>, <p:dataList>, etc), or replace Mojarra by MyFaces (the <ui:repeat> in this construct works properly in there).
I have researched enough on this topic sans any luck :-(
My requirement is to load a HashMap that is declared in the action class from the jsp form that has a s:select tag.
Here is my action class
public class AttributeAction extends ActionSupport {
private HashMap<String, String> lstAttrTypesHashMap;
public void setLstAttrTypesHashMap(HashMap<String, String> lstAttrTypesHashMap) {
this.lstAttrTypesHashMap = lstAttrTypesHashMap;
}
public HashMap<String, String> getLstAttrTypesHashMap() {
return lstAttrTypesHashMap;
}
public String renderPageAction() {
lstAttrTypesHashMap.put("ENTRY1", "VALUE1");
lstAttrTypesHashMap.put("ENTRY2", "VALUE2");
lstAttrTypesHashMap.put("ENTRY3", "VALUE3");
return SUCCESS;
}
public String searchAction() {
logger.info("***************************************");
logger.info("searchAction Started ...");
logger.info("a.getType() = [" + a.getType() + "]");
logger.info("getLstAttrTypesHashMap() = [" + getLstAttrTypesHashMap() + "]");
return SUCCESS;
}
}
here is how I show the drop down in the jsp
<s:select
key="a.type"
label="Select Object Type"
name="a.type"
list="lstAttrTypesHashMap" />
Here is the struts.xml
<action name="attributeSearch" method="searchAction" class="com.frk.gid.action.AttributeAction">
<result name="success">/AttributeResult.jsp</result>
<result name="input">/AttributeInput.jsp</result>
</action>
<action name="attributeRender" method="renderPageAction" class="com.frk.gid.action.AttributeAction">
<result name="success">/AttributeInput.jsp</result>
</action>
When the above jsp loads, I can see that the drop down is populated fine. However when I submit it back to the action, i can only see the selected value (a.type) . The hashmap happens to be null. Is there anything else I need to do to get this HashMap loaded? My understanding was Struts2 would automatically load the HashMap from the dropdown on submit - apparently not ... appreciate any input !!!!
Thanks very much for your responses !
Finally I decided to go with passing Hidden variables and it worked like a charm.
Also, I had complex types like Map>, I had to write my own Type Converter to convert from and to String.
I'm dynamically adding textboxes to a form on my jsp page using Javascript. When that form is submitted to an action, how does my action get the values of those textboxes? (I'm using Struts 2, btw.) In ASP.NET, I was able to find them in Form.Request/FormCollection. Is there a Struts 2 equivalent? Thanks a million.
In Struts2, you create beans in the form to do submit values. In order to create the input text-box, use the <s> tag. For example :
<s:textfield name="loginBean.userName" label="UserName" required="true" />
Here loginBean is the bean passed to the jsp page when.
Bean consists of variable declarations and getters-setters for the variable.
Then in the back-end Java where the form is submitted to, you can access the same bean.
Declare getter-setter in Java and then you can access the properties of the bean.
public LoginBean getLoginBean() {
return loginBean;
}
public void setLoginBean(LoginBean loginBean) {
this.loginBean = loginBean;
}
public String authenticate() {
String username = loginBean.getUserName();
I would recommend looking at source codes of open-source Struts projects.
It sounds like you're trying to populate a dynamic list. To do that, you just have to use the [n] index syntax at the end of your Action class property name:
HTML:
<input type="text" name="yourCollection[0]" value="first value" />
<input type="text" name="yourCollection[1]" value="second value" />
<input type="text" name="yourCollection[2]" value="third value" />
Action Class:
public class YourAction extends Action {
public List<String> yourCollection;
public List<String> getYourCollection(){
return yourCollection;
}
public void setYourCollection(List<String> aCollection){
this.yourCollection = aCollection;
}
}
I've got this h:dataTable and form:
<h:form>
<h:dataTable value='#{bean.allData.dataItems}' var='item'>
<h:column>
<h:outputText value='#{item.id}' />
</h:column>
<h:column>
<h:inputText value='#{item.name}' />
</h:column>
</h:dataTable>
<h:commandButton value="Save" action="#{bean.saveEntries}"/>
</h:form>
So the table shows the id and a textbox with the name in. That works. When a user clicks the button, I'd like it to save any changes to the name field.
DataBean has:
private Vector<ItemBean> dataItems;
// constructor here
public void setDataItems(Vector v) {
dataItems = v;
}
public Vector getDataItems() {
return dataItems;
}
and ItemBean has...
private String id;
private String name;
// setter for both
// getter for both
Bean has a variable 'allData' of type 'DataBean'.
Bean also has a method saveEntries() which is currently blank (as I'm not sure how it works). How do I reference the inputs to set these values?
JSF has already done it during UPDATE MODEL VALUES phase. Print/debug the local variables and you'll see. All you need to do in the save method is just persisting the data in some datastore.
Also see the following articles for more background information and examples:
Using datatables.
Debug JSF lifecycle.