How to make spring checkboxes checked by default? - java

I'm using Spring 3.1.0.RELEASE. I have this field in my command object ...
public Set<EventFeed> getUserEventFeeds() {
return this.userEventFeeds;
}
On my Spring JSP page, I want to display a checkbox list of all possible event feeds, and then have checked checkboxes if the user has one in his set. I want to have some special HTML formatting around each checkbox, so I'm trying ...
<form:form method="Post" action="eventfeeds.jsp" commandName="user">
...
<c:forEach var="eventFeed" items="${eventFeeds}">
<tr>
<td><form:checkbox path="userEventFeeds" value="${eventFeed}"/></td>
<td>${eventFeed.title}</td>
</tr>
</c:forEach>
...
However, the items aren't getting checked by default if one is in the set. How do I do this? Here is the binder I'm using in my controller class ...
#InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(EventFeed.class, new EventFeedEditor());
}
private class EventFeedEditor extends PropertyEditorSupport {
#Override
public void setAsText(String text) throws IllegalArgumentException {
setValue(eventFeedsDao.findById(Integer.valueOf(text)));
}
#Override
public String getAsText() {
return ((EventFeed) getValue()).getId().toString();
}
}

#Dave, there is something called form:checkBoxes. You can try with that.
<form:checkboxes path="userEventFeeds" items="${eventFeeds}" itemLabel="id" itemValue="value"/>
My assumption here is you should have "id" and "value" defined in the EventFeed class.
I just tried this by having a String[] availableList and String[] selectedList. It works like charm. You can give a try as well.

Interestingly this works:
<form:checkbox path="services" value="${type}" checked="checked"/>

You can do this by placing selected default property true in your class
class User {
boolean userEventFeeds = true;
}

I've tried both form:checkboxes and form:checkbox with the same data and the first works, the second doesn't. (Same release of Spring you have)
It looks like there was a bug which, despite their claim, seems to be still there.

For my usecase (reacting on stuff in a list that has nothing to do with the object being filled), this code worked:
(Please be aware that this is a last-resort kind of code, other solutions are most likely better suited.)
<%# taglib prefix="jstl" uri="http://java.sun.com/jsp/jstl/core" %>
<jstl:forEach var="listObject" items="${someList}">
<jstl:if test="${listObject.active}">
<form:checkbox path="active" checked="checked"/>
</jstl:if>
<jstl:if test="${!listObject.active}">
<form:checkbox path="active"/>
</jstl:if>
</jstl:forEach>

Related

How do I translate text in .java source files?

I have an enum like this
public enum CheckboxFeature {
Option1(" choose this"),
Option2(" or this"),
Option3(" maybe this"),
Option4(" lastly this");
#Getter
private final String text;
public static CheckboxFeature fromName(String v) {
for (CheckboxFeature c: CheckboxFeature.values()) {
if (c.name().equalsIgnoreCase(v)) {
return c;
}
}
throw new IllegalArgumentException(v);
}
}
This shows the four options as checkboxes in the web view
<form:checkboxes items="${features}" path="enabledFeatures" itemLabel="text" delimiter="<br/>"/>
How can I translate these options? I use fmt:message for the rest of the translations in the web view.
I have tried
Option1(" <fmt:message key=\"text.test\"/>"),
and
Option1(" ${option1}"),
with
<fmt:message key="text.select" var="option1"/>
in the .jsp.
Neither of them work, so it seems it can't work this way. What is the correct way of translating the strings? Ideally using the fmt:message and i18n resources (lang.properties files) that are in place and working on the rest of the servlet?
Optimally, you get the resource key from the enum, and look that up.
public enum CheckboxFeature {
Option1("label.option1.key"),
Option2("label.option2.key"),
Option1("label.option3.key"),
Option2("label.option4.key");
private final String key;
[...]
I don't know how to nest a l10n lookup in the itemLabel attribute, so I would write something like:
<c:forEach items="Options.values()" var="current">
<form:checkbox path="selectedOptions" value="${current.name()}"/> <fmt:message key="${current.getKey()}"/>
</c:forEach>
1、CheckboxFeature add method like:
public static List<String> getAllCheckboxFeature(String v) {
return Arrays.asList(Option1.getText(),...Option4.getText());
}
2、than use the jstl like:
<c:forEach items="${options}" var="option">
<input type="checkbox" ="${option}">
</c:forEach>

Transferring collection object from one jsp to another

I get the data from the database and store it in some collection object in one jsp(say One.jsp). I want this collection object to be available in another jsp(say Two.jsp). It might contain large data. So, I have used java bean for that in the following way.
public class BeanClass implements Serializable{
private HashMap<String,List<String>> myMap;
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public HashMap<String,List<String>> getMyMap() {
return myMap;
}
public void setData(HashMap<String,List<String>> myMap) {
this.myMap = myMap;
}
}
I am setting bean in One.jsp in the following way.
<jsp:useBean id="dataObject" class="com.mypack.BeanClass" scope="session"/>
<jsp:setProperty name="dataObject" property="myMap"/>
<%
dataObject.setData(myMapObj);
%>
But I get the following error:
Can't find a method to write property 'dataMap' of type 'java.util.HashMap' in a bean of type 'com.mypack.BeanClass'
Somewhere I found stating that we can't do the set for other things unless it is a string. Is there anyway that I can workaround it to make it work even for collection objects? So that I don't need to rollback lot of things that I have done. If not can someone please suggest how to transfer the collection object from one jsp to another? Example with snippet is appreciated.
Or is it that I am missing some extra configuration to make beans work?
Note: I might have used redirect() method, but here the navigation from One.jsp to Two.jsp is done by clicking on hyperlink(href)
EDIT:
Thanks to Alfreema. His solution worked after I had changed to setMyMap, but in Two.jsp I am facing issue. I try to display only some part of map like below. But it displays everything that is there in Map as if it shows when we use out.println(myMap); and it displays table at the very end of the page after printing the content of whole map.
Two.jsp:
<jsp:include page="header.jsp"/>
<jsp:useBean id="dataObject" class="com.mypack.BeanClass" scope="session"/>
<jsp:getProperty name="dataObject" property="myMap"/>
<%! HashMap<String,List<String>> gottenMap = null; %>
<%
gottenMap = dataObject.getMyMap();
%>
<table>
<tbody>
<%
String selectedPart = request.getParameter("part");
List<String> list = gottenMap.get(selectedPart);
for(int i=0; i<list.size(); i++)
{
%>
<tr>
<td colspan='2'><strong>
<%= list.get(i) %>
</strong></td>
</tr>
<%
}
%>
</tbody>
</table>
I am confused why it does like that without coding for printing the whole collection.
Change this:
<jsp:useBean id="dataObject" class="com.mypack.BeanClass" scope="session"/>
<jsp:setProperty name="dataObject" property="myMap"/>
<%
dataObject.setData(myMapObj);
%>
To this:
<jsp:useBean id="dataObject" class="com.mypack.BeanClass" scope="session"/>
<jsp:setProperty name="dataObject" property="data" value="${myMapObj}"/>
Your setter is called "setData(...)", not "setMyMap(...)". JSP is going to see property="data" and call setData(...).
So that will fix you up, but you didn't show us where you are setting myMapObj. We have to assume that you are setting that up correctly elsewhere and have made it available to the tag via a pageContext.setAttribute("myMapObj", myMapObj); call.
Side note: I recommend you rename the setData(..) method to setMyMap(...) to make it consistent with the getter getMyMap(...). If you do that, then you will need to change the property="..." back to "myMap", just like you had it.

Tapestry: How to set HTML checkbox from java page

I am using plain HTML checkbox(not Tapestry type). I need to set the checkbox to checked in my java page. How do I do that?
Here is my tml code fragment
<input type="checkbox" name="leaf" id="leaf" value="leaf"/>
Any help would be appreciated. Thanks.
You need to set the checked property. I'd probably use the <t:any> component.
TML
<t:any element="input" type="literal:checkbox" name="literal:leaf" id="prop:clientId" value="prop:currentObject.value" checked="prop:checked" />
JAVA
#Property
private SomeType currentObject;
public String getClientId() {
return "mycheckbox_" + currentObject.getId();
}
// if this returns null, tapestry won't render the attribute
public String getChecked() {
return currentObject.isSelected() ? "checked" : null;
}

Bind Collection to Form - why is it not working?

Could someone please help me find out why my attempt to bind Collection to the form in Spring MVC is not working?
Here is how my object looks like -
public class TestObj {
private Integer testNumber;
private String home;
private String destination;
}
Here is my form object that contains list of above object -
public class TestForm {
private List<TestObj> testList;
//contains getter and setter for testList
}
In my controller, I have implemented formBackingObject method -
public class MyController extends SimpleFormController {
public MyController() {
setCommandClass(TestForm.class);
setCommandName("testForm");
}
protected Object formBackingObject(HttpServletRequest request) throws Exception {
if (isFormSubmission(request)) {
testForm = (TestForm) super.formBackingObject(request);
//THIS ALWAYS RETURNS NULL ON FORM SUBMISSION
List<TestObj> testList = testForm.getTestList();
} else {
//load initial data using hibernate. TestObj is hibernate domain object.
List<TestObj> testList = myService.findTestList();
testForm = new TestForm(testList);
}
return testForm;
}
Here is my JSP snippet -
<form:form commandName="testForm" method="post">
<c:forEach items="${testForm.testList}" var="testvar" varStatus="testRow">
<tr>
<td>
<form:hidden path="testList[${testRow.index}].home" />
<c:out value="${testvar.home}" />
</td>
<td>
<form:input path="testList[${testRow.index}].destination" />
</td>
</tr>
</c:forEach>
<tr><td><input type="submit"></td></tr>
</form:form>
While the first time I load the data shows up fine on the form, when I press submit button the control goes to the formBackingObject method and the isFormSubmission returns true. However, when I get the command object using super.formBackingObject(request), it returns the form object with the testList value as null. I am unable to figure out why this simple case is not working?
I will really appreciate any help in getting this to work.
Are you using Spring 3? If so, you should take a look at this post.
With respect to list processing and object binding, take a look at this post.
Try using the following code. May be that can solve your problem.
private List<TestObj> operationParameterses = LazyList.decorate(new ArrayList<TestObj>(), FactoryUtils.instantiateFactory(TestObj.class));
It won't return you all null list.
Hope that helps you.
Cheers.
I guess my understanding of formBackingObject method must be wrong. I removed that method from the implementation, used referenceData for initial form load and onSubmit to process it on submit. This works fine and does get collection in the form back as expected.
Thanks all for the help though.

Spring 3 validation error

I'm trying to get some validators working with Spring 3. I keep getting an error:
org.springframework.beans.NotReadablePropertyException: Invalid property 'name' of bean class [java.lang.String]: Bean property 'name' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
My question is, is this what that error referring to. I believe that in the rejectValue method, it is calling getName() on myobj. Is it saying that myobj.getName() does not exist? Because I can tell you it does. Otherwise this method would not even compile.
public void validate(Object target, Errors errors) {
MyObject myobj = (MyObject)target;
String name = myobj.getName();
if(name.length() >100 || name.length() < 10) {
errors.rejectValue("name", "fieldLength");
}
}
Here is MyObject:
public class MyObject {
public MyObject() {
super();
// TODO Auto-generated constructor stub
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And in my jsp:
<form:form name="MyForm" commandName="myobj" method="post" action="${testurl}">
<table id="mytable" width="100%">
<tbody>
<tr>
<td colspan="2">
<form:errors path="name"/>
</td>
</tr>
<tr>
<td>
Name:
</td>
<td>
<form:input path="name"/>
</td>
</tr>
</tbody>
</table>
My controller:
#ActionMapping(params="myaction=test")
public void test(#ModelAttribute("myobj") MyObject myobj, BindingResult bindingResult,
ActionRequest request, ActionResponse response, SessionStatus sessionStatus) {
}
testValidator.validate(myobj, bindingResult);
if (!bindingResult.hasErrors()) {
response.setRenderParameter("myaction", "nextpage");
} else {
response.setRenderParameter("myaction", "test");
}
}
This is most likely telling you that some EL expression is failing, because Spring cannot figure out what the type of the 'name' property is based on the getter/setter signatures. If you showed us the declaration of (all of) the getters and setters for 'name', maybe we can be more specific.
Annoyingly, it seems like the code was right the whole time. I finally ran maven clean and then rebuilt and redeployed, along with clearing all cache, etc, and now it is working with that code. I am going to modify it to try to get something closer to what I actually want to happen (nested validations) and see where I get with that.
I guess your problem has nothing to do with validation per se. I can only suspect that the code you're pasting is not your exact example, but a hand-made one inspired by the code really executed.
There has to be some basic problem with MyObject property name. My personal guess is that the getter is defined in the super class of MyObject and only the setter is re-defined (or overriden) in the MyObject class.
Anyway, the best advice I can have for you is to try to extract a minimal example of your code and try to run it. Even if for some reasons you can't share the example with us, that will make it easier for you to find the reason of your troubles.
This happened to me with a Spring Validator that kept complaining about two unreadable properties on my domain POJO. One was a java.lang.Boolean, the other was a java.lang.Integer and they both had proper JavaBeans conventional getters and setters.
After some digging around I discovered I initialized the Boolean property with:
#Value("T{Boolean.FALSE}")
and the Integer property with:
#Value("0")
This was residue of a previous instructional project. Anyway, once removed, those annoying unreadable property errors ceased and the validator started doing it's job.

Categories