How to use spring:message in a forEach loop - java

I have been working on a system that provides bilingual support to a website from a database using the <spring:message /> tag library.
I can read/write to the applications en/fr properties files. When I hardcode what would be a new key <spring:message /> will display it correctly. Ex) <spring:message code="f12345' /> will display "test data".
What I am having problems doing is using a dynamic key. No matter how I try to attach the key it fails.
Here are the methods I have tried group by end result.
500 error org.apache.jasper.JasperException: (line: [104], column: [29]) [quote/equal] symbol expected
<spring:message var><c:out value="${CLUObject.SpringKey_name()}" /></spring:message>
<spring:message var='<c:out value=\"${CLUObject.SpringKey_name()}\" />" text="wrong" />
<spring:message code="<c:out value="${CLUObject.SpringKey_name()}" />" text="${CLUObject.SpringKey_name()}" />
<spring:message code=<c:out value="${CLUObject.SpringKey_name()}" /> text="${CLUObject.SpringKey_name()}" />
<spring:message code= <c:out value="${CLUObject.SpringKey_name()}" /> />
Next we have the non-server crash which simply causes the table to not display
<spring:message var='<c:out value="application.message" />' arguments="${CLUObject.SpringKey_name()}" />
<spring:message var='<c:out value="${CLUObject.SpringKey_name()}" />' text="wrong" />
<spring:message code="<c:out value=\"${CLUObject.SpringKey_name()}\" />" />
<spring:message code="${CLUObject.SpringKey_name()}" />
<spring:message code="messageCode" arguments="$value1}" />
<c:set var="temp" > <c:out value="${CLUObject.SpringKey_name()}" /> </c:set><td><spring:message code="messageCode" arguments="${temp}" htmlEscape="false" /></td>
The best I have managed to get to simply displays the text of the key instead of the value. Which can already be done using <spring:message text="${CLUObject.SpringKey_name()}" />'
In the applicationResources file
messageCode=Test message for {0}.
Then inside the jsp page
<c:set var="temp" > <c:out value="${CLUObject.SpringKey_name()}" /> </c:set>
displays "Test message for CLUVALUE.C1111."
I found one site online which appeared to be doing the same thing.
<form:select path="${path}">
<c:forEach var="i" items="${items}">
<form:option value="${i[itemValue]}">
<c:choose>
<c:when test="${localize}">
<spring:message code="${i[itemLabel]}" text="${i[itemLabel]}"/>
</c:when>
<c:otherwise>
<c:out value="${i[itemLabel]}"/>
</c:otherwise>
</c:choose>
</form:option>
I have found a second example where they have a dynamic key with the spring message being used in a forEach loop. Search for spring:message and its 14/17.
<c:forEach items="${errors.allErrors}" var="error">
<spring:message code="${error.code}" text="${error.code}"/><br/>
</c:forEach>
I have found a third example.
In the three examples I have found, the spring:message are all used the same, with the code and text attributes being the same.
I cant see the output, and I cant be sure that their text argument isnt being displayed instead.
Here is the controller block
List<CLU_STRUT> myCLUs = cluService.BuildCLUs();
model.addAttribute("CommonLookUp", myCLUs);
And here is the JSP
<c:forEach var="CLUObject" items="${CommonLookUp}" varStatus="vs">
<tr>
<c:set var="temp" > <c:out value="${CLUObject.SpringKey_name()}" /> </c:set>
<td><spring:message code="messageCode" arguments="${temp}" htmlEscape="false" /></td>
<td><c:if test="${CLUObject.getCountNew() gt 0}"> <a href='drillview?drillvalue=${CLUObject.SpringKey_name()}&mode=drill&drilltype=I'><c:out value="${CLUObject.getCountNew()}" /></a></c:if><c:if test="${CLUObject.getCountNew() eq 0}">0</c:if></td>
<td><c:if test="${CLUObject.getCountMod() gt 0}"> <a href='drillview?drillvalue=${CLUObject.SpringKey_name()}&mode=drill&drilltype=U'><c:out value="${CLUObject.getCountMod()}" /></a></c:if><c:if test="${CLUObject.getCountMod() eq 0}">0</c:if></td>
<td><c:if test="${CLUObject.getCountDelete() gt 0}"> <a href='drillview?drillvalue=${CLUObject.SpringKey_name()}&mode=drill&drilltype=D'><c:out value="${CLUObject.getCountDelete()}" /></a></c:if><c:if test="${CLUObject.getCountDelete() eq 0}">0</c:if></td>
<td><c:out value="${CLUObject.getCountTotal()}" /></td>
</tr>
</c:forEach>
TLDR; How to use spring:message where the key is dynamic in a jsp page.

I finally figured out what the issue was.
Short Answer: the inversion of control was causing things to happen now how I expected. I was trying to access a function or member, and it kept trying to use a get version of it. Since I did not have specifically getmember() to access the variable, it was doing strange and wrong things.
By introducing public String getspring_name() {return spring_name;} all of a sudden the <spring:message code="${CLUObject.spring_name}" /> works.
Long Answer: In another section of my code I discovered what I thought was a private string member being accessed in a jsp page. After considerable testing of other private variable types and functions, my original thought that I was gaining access to the private member was disproved. Yet, this specific one was being accessed. After more testing I discovered when I had a get function in a very specific naming convention this behavior was reproducible. So in this case I had a private String CLU_Name, and was lucky enough to have created the get function as getCLU_Name(). Having named other get functions like getCountDelete() for Count_Delete was not allowing me to reproduce the behavior for THEM, because they did not fit the naming pattern.

Related

JSTL how to get dynamic token position

I have something like this:
22-04-19 20:34:00!Color::blue!Manufacturer::Ford!Seats::4!Climatronic::yes
I want to get the name of the category and its value (category::value).
The problem is that these positions (category::value) can shift places. ForTokens is index is not good here as it can be one or 10 different tokens.
<c:if test="${fn:contains(dataset, 'Color')}">
<c:set var="color1" value="${fn:substringAfter(dataset, 'Color::')}" />
<c:set var="color2" value="${fn:substringBefore(color1, '!')}" />
</c:if>
Something like this will also not work as it will print out the same value until the new one will appear (will fill out all null cells). I'm out of ideas.
You can split the initial string and loop over each item to find the category you need:
<c:set var="string1" value="22-04-19 20:34:00!Color::blue!Manufacturer::Ford!Seats::4!Climatronic::yes" />
<c:set var="categories" value = "${fn:split(string1, '!')}" />
<c:forEach var="category" items="${categories}" varStatus="status" >
<c:if test="${status.index != 0}">
<c:set var="decodedCategory" value="${fn:split(category,'::')}" />
Category: <c:out value="${decodedCategory[0]}" />
Value: <c:out value="${decodedCategory[1]}" />
<br />
</c:if>
</c:foreach>

Spring MVC form checkbox not checked when retriving data

I am setting status property as true in the background but still check box not checked:
JSP:
<c:forEach var="list" items="${someFormList}" varStatus="status">
<tr>
<td>
<form:checkbox path="status" items="${list.status}" />
</td>
</tr>
</c:forEach>
Controller:
model.addObject("someFormList", someFormList);
Path gets you partway there. Add the value property to the form:checkbox tag:
<form:checkbox path="status" value="${status}" />
Instead of addObject, you may want to try addAttribute (see also this solution).

Include a dynamic page using dsp include in atg

I'm trying to include a page listusers.jsp which simply says "Hello World". I'm reading the name of the listusers.jsp from a parameter as shown below from profile.jsp.
<!-- profile.jsp -->
<table width="100%" border="0px">
<tr><td>
<table border="0px">
<tr>
<td>
<dsp:a page="profile.jsp">List Users
<dsp:param name="includepage" value="listusers.jsp"/>
</dsp:a>
<dsp:a page="profile.jsp">Shop
<dsp:param name="includepage" value="shop.jsp"/>
</dsp:a>
</td>
</tr>
</table>
</td>
<td>
<dsp:getvalueof param="includepage" id="subpage" >
<dsp:include page="<%= subpage %>" />
</dsp:getvalueof>
</td></tr>
</table>
This is giving me the following error when I'm trying to open profile.jsp
A:\Tomcat\apache-tomcat-7.0.37\atgbases\ATG\work\Catalina\localhost\MyStore\org\apache\jsp\profile_jsp.java:168: error: method setPage in class IncludeTag cannot be applied to given types;
_jspx_th_dsp_005finclude_005f1.setPage( subpage );
^
required: String
found: Object
reason: actual argument Object cannot be converted to String by method invocation conversion
1 error
1 warning
Please let me know the right way of including a dynamic page using
You are simply giving the getvalueof the wrong attribute for the variable.
Instead of:
<dsp:getvalueof param="includepage" id="subpage" >
<dsp:include page="<%= subpage %>" />
</dsp:getvalueof>
Rather try:
<dsp:getvalueof param="includepage" var="subpage" >
<dsp:include page="<%= subpage %>" />
</dsp:getvalueof>
Note the attribute is var not id.
I think specifying idtype="java.lang.String" to the <dsp:getvalueof /> tag might resolve your problem. It looks like currently the variable, subpage is created as Object rather than String.
<dsp:getvalueof param="includepage" id="subpage" idtype="java.lang.String">
<dsp:include page="<%= subpage %>" />
</dsp:getvalueof>

In tag <td></td> DOUBLE_WHITESPCE in query href

I have a very strange problem.
<table border ="1">
<tbody>
<c:forEach var="question" items="${questions}">
<tr>
<td>
${question.getQuestion()}
</td>
<td>
<c:forEach var="answer" items="${question.getAnswers()}">
<input type="checkbox" name ="user_answer" value="${answer.getAnswer()}">
${answer.getAnswer()}
<br />
</c:forEach>
</td>
<td>
<a href="/TutorWebApp/controller?command=edit_qestion&question=${question}">
Edit
</a>
</td>
</tr>
</c:forEach>
</tbody>
</table>
But If I use in I get next error
But if I don't use tag <a> in <td> it's OK. I don't have any ideas.
Thanks
I think this is just a bug/limitation of your editor. Try deploying your JSP and see if it works as expected or not.
That said, if your question contains characters that must be URL and/or HTML escaped, your HTML code will be invalid. You should use the c:url tag to avoid that:
<c:url var="editQuestionUrl" value="/TutorWebApp/controller">
<c:param name="command" value="edit_question"/>
<c:param name="question" value="${question}"/>
</c:url>
<%-- now the params are url-encoded --%>
Edit
<%-- now the query string is HTML-escaped --%>
You need to encode your question text (or whole URL) here by calling URLEncoder#encode()
You can look at this Q&A on how to encode a URL in JSTL.
Alternatively you can try calling JSTL's escapeXml function on your question text.
try replacing this line
<a href="/TutorWebApp/controller?command=edit_qestion&question=${question}">
with
<a href="/TutorWebApp/controller?command=edit_qestion&question='${question}'">

Assigning outcome of another JSTL tag as value of one JSTL tag

I've got this, which is working:
<c:choose>
<c:when test="${sometest}">
Hello, world!
</c:when>
<c:otherwise>
<fmt:message key="${page.title}" />
</c:otherwise>
</c:choose>
And I want to change it to this:
<c:choose>
<c:when test="${sometest}">
<c:set var="somevar" scope="page" value="Hello, world!"/>
</c:when>
<c:otherwise>
<c:set var="somevar" scope="page" value="<fmt:message key="${page.title}">"
</c:otherwise>
</c:choose
But of course the following line ain't correct:
<c:set var="somevar" scope="page" value="<fmt:message key="${page.title}">"
How can I assign to the somevar variable the string resulting from a call to fmt:message?
The fmt:message has a var attribute as well which does effectively what you want.
<fmt:message key="${page.title}" var="somevar" />
That's all. Bookmark the JSTL tlddoc, it may come in handy.
It is also possible to specify the value to set using the contents of the body, rather than through the value attribute:
<c:set var="somevar" scope="page">
<fmt:message key="${page.title}"/>
</c:set>
You'll have to do with:
<c:set var="title"><fmt:message key="${page.title}"></c:set>
<c:set var="somevar" scope="page" value="${title}" />
Since you can't use <fmt:message .. /> on that spot is my experience, has to do with nesting like you suggested. Or go with #balusc suggestion ;-)

Categories