Best practice struts/jsp/i18n/resourceBundle - java

I am using Struts 2 and Apache tiles, and I'm new to both. I am trying to "clean" some existing sources that don't feel correct to me (tell me if I'm wrong).
I have the following structure :
in a layout.jsp :
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title><tiles:getAsString name="title" /></title>
<tiles:insertAttribute name="header" />
</head>
<body>
<div id="content-size-and-border">
<s:if test="display!='nomenu'">
<tiles:insertAttribute name="menu" />
</s:if>
<div id="maincontent">
<tiles:insertAttribute name="maincontent" />
</div>
</div>
</body>
The main content part displays various jsp/action depending on the item-menu clicked.
The menu part uses some java code directly in the jsp to generate a number of sub-folders by iterating on a list.
<li class="highlight sousmenu"><a href="#"><s:text
name="menu.demarrage" /></a>
<ul class="niveau2">
<%
Locale language = (Locale) session.getAttribute("WW_TRANS_I18N_LOCALE");
// the attribute (used by i18n struts interceptor)
// set in session when the user changes the language
if (language == null)
language = request.getLocale() ;
// if the language was not changed, get the default Locale from browser
User user = ((CustomUserDetails) SecurityContextHolder.getContext()
.getAuthentication().getPrincipal()).getBpmUser();
if (user != null) {
for (Iterator iterator = user.getProcesses().iterator(); iterator
.hasNext();) {
String processToStart = (String) iterator.next();
String processPath = BpmUiConstantes.BPMUI_PROCESS_CONFIG_ROOT + "/" + processToStart ;
String processLib = "process." + processToStart + ".label";
%>
<li>
<a href="<%=request.getContextPath()%>/restricted/DemarrerProcessAvecTache?processName=<%=processToStart%>">
<fmt:setLocale value="<%=language%>"/>
<fmt:bundle basename="<%=processPath%>">
<fmt:message key="<%=processLib%>"/>
</fmt:bundle>
</a>
</li>
<%
}
}
%>
</ul>
</li>
I was wondering if there was a better way to achieve the same result, without the java code in the jsp. Is it important to remove the java code from the jsp from a conception point of view ?
The application uses struts i18n interceptor for the language changes. Is there a way to have the menu use a struts i18n interceptor in some way?

I would definitely look more into JSTL core (C tag to use foreach) and fmt(for the locale- language), with these two libraries you should be able able to safely remove the embedded java code into your page and use a more congruent/safe approach
Here is the oracle webpage to JSTL so you can have some reference
JSTL Reference
Feel free to ask if you have any other questions.

I will add some piece of answer to the previous post :
There is no way to have this menu use a struts i18n interceptor and, above all, it is useless because ResourceBundle's Locale or fmt:bundle's Locale would not be set by this interceptor. It is necessary to specify explicitely the Locale (like I did in the code) => this part cannot be changed.
I'm still not sure about the importance of removing this java code from the jsp though.

Related

List with springboot and thymeleaf

I am trying to get a list of objects that are sent to the server from the html form as parameters for my list, then I will loop through those entries and then return them through the springboot th:each. But it doesn't seem to be working at all. On load the form appears but when I enter a value in it, then it returns an error page and the URL however turns:
http://localhost:8080/#%7B/%7D?%24%7Bcontent%7D=hello
this output in eclipse says:
Expression "content" is not valid: only variable expressions ${...} or selection expressions *{...} are allowed in Spring field bindings
Note: content here is the value property in my form.
My controller looks like this:
#Controller
public HelloList() {
this.addUs = new ArrayList <>();
}
#RequestMapping("/")
public String getlist(#RequestParam (required = false) String content, Model model) {
if (content != null && !content.trim().isEmpty()) {
this.addUs.add(content);
}
model.addAttribute("list",addUs);
return "index";
}
the index.html looks like this
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Insert title here</title>
</head>
<body>
<div>
<ul>
<li th:each="amHere: ${addUs}">
<span th:text="${amHere}">hello! world</span>
</li>
</ul>
<form action="#{/}" method="GET">
<input type="text" name="content"/>
<input type="submit" value="Submit"/>
</form>
</div>
</body>
</html>
This might be a duplicate but it seems like most of the solutions I came across are not helping. So any help is mostly appreciated. Thank you in advance.
Turns out I was missing the initialization of my list in the constructor. I initialized the list by adding a value to it first in the constructor like this.
this.addUs.add("Hello World");
Because the #RequestMapping is mapped to the home path in my case index.html, any request gets sent there automatically.
working example
action = "#{/}" should be th:action="#{/}". That's the reason you're seeing the weird url (because it's url encoding #{/}). Thymeleaf only evaluates expressions that start with th:.
I'm not sure about the other error. It looks like the html you've pasted doesn't match up with the error you are getting.
If you urldecode http://localhost:8080/#%7B/%7D?%24%7Bcontent%7D=hello, you get http://localhost:8080/#{/}?${content}=hello, which doesn't line up with your form.

Recommended template engine to reduce redundancy of dynamic content (Spring Boot)

I am about to re-write a web-platform, and I am using Spring Boot/Spring MVC. A major part of the platform is the website. I am struggling deciding which template-engine to use. Thymeleaf seems to be recommended, while JSP discouraged. I am not sure if my requirements are unusual, at least they do not sound like that to me:
I do not want to repeat myself in the different templates, they should all be displayed inside a "master template/layout"
The master template/layout will have navigation and footer, which have dynamic content (eg. it is not only the main content that is dynamic)
1) With Thymeleaf, from what I have been able to understand, using Layouts would be the recommended (only?) approach. However, it looks to me like all dynamic content much still be generated in each template (where it flows into the layout using the layout:fragment attribute). This sounds less than ideal, as it would mean I would still have to generate the dynamic part of the layout in each template. Is there no way to include dynamic content in Thymeleaf layouts, where the content (menu, footer, twitter-feed etc) is generated separately from the actual content-template?
2) JSP seems to be able to solve this rather easily, using a custom tag for the layout, that has <jsp:include> -tags for the dynamic content and a <jsp:doBody> -tag for the actual content-template. However, from reading the Spring Boot documentation, I somehow got the impression that it is encouraged to use a different template-engine that JSP. The approach described above would however let me define a header.jsp, navigation.jsp, footer.jsp and twitterFeed.jsp that generates the content dynamically (based on database content, logged in user etc), while the actual content-template purely focuses on the content to display. Is there something I am missing in my comparison between Thymeleaf and JSP here, why would I not chose JSP as my project's template engine?
3) With the approach meantioned in 2), would I be limited to putting all my Java logic in the JSPs for the templates included in the main layout (header, navigation, footer, twitter-feed), or is there a better way to back these stubs up with a controller-like class?
4) Are there any other template engines that integrate well with Spring MVC / Spring Boot, that would be a better choice that any of the above mentioned ones?
Use can use Thymeleaf Ultraq Layout to create a base template which will act as a decorator for your other templates as shown below:
base-template.html:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<title layout:title-pattern="$CONTENT_TITLE - $LAYOUT_TITLE">Sample</title>
<meta name="description" content=""/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<!-- all CSS links here -->
</head>
<body>
<div class="container">
<div class="content">
<div layout:fragment="page_content">
<!-- Content from other pages which decorate using this template -->
</div>
</div>
</div>
<!-- /.container -->
<!-- All script tags here -->
<th:block layout:fragment="scripts">
<!-- If you have any page specific scripts -->
</th:block>
</body>
</html>
Then the other pages will use the above template as a decorator as shown below:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{base-template}">
<head>
<title>This page title</title>
</head>
<div layout:fragment="page_content">
<!-- content for this page -->
</div>
<th:block layout:fragment="scripts">
<!-- add any scripts related to this page -->
</th:block>
</html>
The syntax ~{base-template} is used with Thymeleaf 3 onward.
You can proceed with the above approach and not repeat the navigations, headers and footers on your other pages.

Pass selected value from dropdown using JSP

I need to implement some basic dropdown using jsp and java, but I can't find more info how to do that. So I never write something using JSP and when I didnt find nothing that help the last options for me was to ask.
I want to get the selected value and when click the button to send the value to anoher .jsp file ("selector.jsp in my case")
Please folks help me with some easy solution.
p.P.: Sorry for my english (:
index.jsp
<FORM method="post" action="selector.jsp">
<select name="select" id="dropdown">
<%
Test t = new Test();
t.getList().add("a");
t.getList().add("b");
t.getList().add("c");
for(int i=0; i < t.getList().size(); i++){
%>
<Option value="<%t.getList().get(i);%>"><%=t.getList().get(i)%></Option>
<%}%>
</select>
<input type="submit" value="click">
selector.jsp
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
You selected:
<%
request.getParameter("select");
request.getParameterValues("select");
%>
</body>
</html>
I found a solution by removing
value="<%t.getList().get(i);%>"
from and leave the code just with
<Option><%=t.getList().get(i)%></Option>
but i don't know why... if someone can explain will be great.
Thx! (:
As you have indicated in your post, the problem is solved by replacing
value="<%t.getList().get(i);%>"
with
<Option><%=t.getList().get(i)%></Option>
The reason that works is as follows:
In your first form, <%t.getList().get(i);%>, you have a JSP scriptlet. This is Java code that is executed inline. In your case, this executes the "get" method. Note however that the get method returns a value, but this value is not output into the response stream.
In your second form, you have formed a JSP expression by using "<%=". "<%=" is shorthand for "out.println", thus you have provided shorthand for the following:
<Option><% out.println(t.getList().get(i)) %></Option>
This writes the return value of the method call to the output stream. So that when this output reaches the browser, there is an actual value within the Option tags.

struts 1.0 logic tag choice - if/else logic

What I have is a dropdown list. When the user selects a certain option, where each option represents a specific String on the Java server side.
Right now, the Java server side able to check which option is selected, and the number to correspond. At the moment, I am able to output the value in Java backend, not on the JSP page.
Is there an if/else tag for Struts 1.0?
I am not sure which logic tag is the best to pass a Java value for frontend processing:
JSP page
if(value = 666)
this textbox is readonly
else
this textbox row is active
My research so far:
Looking at logic:equal, it seems to pass a value on the JSP page using taglibs like below. This doesn't work for me, because I want to pass the value FROM a Java class on the server side.
<logic:equal name="name" property="name" value="<%= theNumber %>" >
<c:choose>
<c:when test="${the number}">
Both are equal.
</c:when>
<c:otherwise>
Both are not equal.
</c:otherwise>
</c:choose>
this is jstl tag
you need to use
<%#taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
The JSTL answer is the best one, however, in my case it was an old Java legacy application without JSTL and I couldn't introduce it.
This was the requirement I had with some legacy Struts 1.3 code. Set a checkbox to match the value of a form bean's value from a database call, as in "Y", "N", "", or null.
I also had to keep in within struts logic tags and not use JSTL, which was my original preference. I know that the struts docs
said the checkbox should equate to a boolean variable in the
actionForm, but I used a string value, which worked.
From the docs link above:
NOTE: The underlying property value associated with this field should be of type boolean, and any value you specify should correspond to one of the Strings that indicate a true value ("true", "yes", or "on"). If you wish to utilize a set of related String values, consider using the multibox tag.
I had thought about converting my string values to booleans in the
form, but it took the strings this way.
Last of all, I used some javascript to set the checked status. All of this is verbose and not the best solution, but faced with the requirement, it does work.
Here is the code:
<logic:equal name="<%=formName%>" property="formInd" value="Y">
<html:checkbox name="<%=formName%>" onchange="setDataChanged()" property="formInd"/>
<script type="text/javascript" LANGUAGE="JavaScript">
document.<%=formName%>.formInd.checked = true;
</script>
</logic:equal>
<logic:equal name="<%=formName%>" property="formInd" value="N">
<html:checkbox name="<%=formName%>" onchange="setDataChanged()" property="formInd"/>
<script type="text/javascript" LANGUAGE="JavaScript">
document.<%=formName%>.formInd.checked = false;
</script>
</logic:equal>
<logic:empty name="<%=formName%>" property="formInd" >
<html:checkbox name="<%=formName%>" onchange="setDataChanged()" property="formInd"/>
<script type="text/javascript" LANGUAGE="JavaScript">
document.<%=formName%>.formInd.checked = false;
</script>
</logic:empty>

include a jsp as a header based on a condition inJSF

I'm using JSF-2.0 and I'm trying to include a jsp as a header for my current jsp.But all i want is the included jsp should be altered based on the login credentials.
More clearly...depending on the person logging in to my application, the header menu (included jsp) should be different.I've tried implementing in the below way but it did not work..any help would be appreciated
<html>
<head></head>
<body>
<%
String menuHeader = (String) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("menuAssigned");
if (menuHeader.equals("XX")){ %>
<f:view> <jsp:include page="XHeader.jsp" /> </f:view>
<% }else if(menuHeader.equals("YY")){ %>
<f:view> <jsp:include page="YHeader.jsp" />
<%}%>
---
</f:view>
</body>
</html>
Don't use Scriptlets. Ever.
Your menuAssigned variable is just available in EL by #{menuAssigned}. I suggest to align your menuAssigned variable value with the JSP include filename. Then you can just use
<jsp:include page="#{menuAssigned}Header.jsp" />
Imagine that menuAssigned is XX, then this will include XXHeader.jsp.
Unrelated to the concrete problem, why are you using legacy JSPs while you're apparently already on JSF 2.0 which comes along with JSP's awesome successor Facelets (XHTML)?
Short answer, use EITHER JSP or JSF flow control. Don't mix them too much.
<html>
<head></head>
<body>
<f:view>
<h:panelGroup rendered="#{menuHeader == 'XX'}">
<%#include file=”XHeader.jsp" %>
</h:panelGroup>
<h:panelGroup rendered="#{menuHeader == 'YY'}">
<%#include file=”YHeader.jsp" %>
</h:panelGroup>
</f:view>
</body>
</html>
Perhaps static includes? Again, I've been using facelets with JSF for several years now. Not used to the JSP stuff anymore. Its been a while.

Categories