Clean way for conditionally rendering HTML in view? - java

Is there a cleaner way to do this in a JSP/Struts1 setup ?
... some HTML here ...
EDIT: In admin mode I would like to have access to additional parameters from a form element,
e.g. from the form element:
input type="text" value="Test user" name="Owner"
EDIT 2: Actually, my problem is very similar to the question that was asked in : Conditionally Render In JSP By User
But I don't really get the "pseudo-code" from the likely answer

Is SessionConfig exposed as a bean in your JSP (as part of request / session / Struts Form)?
If it's not, you can expose it. And if it's a static class containing global settings (which, by the looks of it, is a possibility), you can create a small wrapper and put it in the servlet context which you'd then be able to access from Struts tags as scope="application".
Once that's done you can check your condition via Struts tags:
<logic:equal name="sessionConfig" property="adminMode" value="true">
... your HTML here
</logic:equal>
Or, if you're using EL / JSTL, same can be done via <core:if>.

Without more information, it's hard to answer this, but I'd think instead of separate views: one for admin mode, one for normal mode. Extracting the parts of your pages into tiles will help you do this without a lot of pain; see: http://tiles.apache.org/

Related

Message bundle intermittently not rendering correct

In my application I am trying to get labels out of a message bundle.
However rather then use constant key values I am using variables
<c:forEach var="emailAddress" items="${emailAddresses}">
...
<c:set var="labelKey" value="Contact_Label_${emailAddress.type}"/>
...
<h:outputText value="#{faces_translations[labelKey]}"/>
...
</c:forEach>
Most of the time this works correctly, but every so often when a page is
loaded some of the label are not processed correctly and the following
message is displayed:
???Contact_Label_???
It looks like the email.type does not return a value, however I added some
debug code to print out the value of email.type by including
${emailAddress.type}
and saw that a value was returned.
Another thing I tried was to remove the value everytime before setting it
again inside the loop using . This resulted in the following
exception. I verified that I had the tag library included in the WAR file
(jstl-api-1.2.jar and jstl-impl-1.2.jar as well as javax.faces-2.1.7).
<c:remove> Tag Library supports namespace: http://java.sun.com/jsp/jstl/core,
but no tag was defined for name: remove
Both these issues are really baffling. The label works most of the time,
but not consistently. The tag is defined in the included library, but cannot be found.
Thanks in advance for any pointers.
JSF UI components and tag handlers like JSTL doesn't run in sync. JSTL runs when the JSF view is to be built. The result is a JSF component tree without any tag handlers like <c:xxx> and <f:xxx>. JSF UI components runs when the JSF view needs to generate HTML for the HTTP response. That very same JSF view can be reused multiple times in subsequent HTTP requests as long as you're interacting with the same view by returning null or void on POST actions (like as you should use a #ViewScoped bean). It is not true that JSTL tags runs on every single HTTP request. That's most likely where it went wrong in your case.
Rather use JSF UI components if you want consistent render-time behaviour while reusing the same view. Your construct can be replaced as follows:
<ui:repeat var="emailAddress" value="#{emailAddresses}">
...
<ui:param name="labelKey" value="Contact_Label_#{emailAddress.type}" />
...
<h:outputText value="#{faces_translations[labelKey]}" />
...
</ui:repeat>
See also:
JSTL in JSF2 Facelets... makes sense?

Spring and dynamic inclusion of JSP files

I'm starting building web apps in Spring 3 (and in J2EE) in general.
Looking at the petclinic example I've seen that the programmer creates many JSP pieces, like header, includes, footer and then stitches them together using static inclusion. Anyway what I'd like is that I may have a base page, like Base.jsp and be able to include things like this:
<body>
<jsp:include page="${subpage}"></jsp:include>
</body>
the reason is that I'd like a main page, then being able to put in the ModelAndView returned by the controller which parts of the pages display in each situation (with the data attached to it). This works, but it gives no errors in case ${subpage} is not found, the jsp name is wrong or missing. I'd like more error checking...
Is this the best and recommended way to do this? And if this seems a good idea for what I've in mind, what's the correct way of doing it?
You might want to use Apache Tiles 2 integration for managing your JSP files. Spring has good integration support Apache Tiles. It also shows if there's an error in your page. I've put an example of it at http://krams915.blogspot.com/2010/12/spring-mvc-3-tiles-2-integration.html
It appears you have additional quotes in your subpage. Get rid of them. For example:
<c:set var="subpage" value="/jsp/index.jsp" />
If you have to set it in a controller or servlet - just use request.setAttribute("subpage", "/jsp/index.jsp")
For error checking you can use:
<c:catch var="myException">
<c:import url="${subpage}" />
</c:catch>
and later you can check it with:
<c:if test="${myException != null}">
...
</c:if>
Take a look at Sitemesh (http://www.opensymphony.com/sitemesh). It is a servlet filter-based page layout system that is easy to use. I have done a number of projects using it with Spring MVC and it worked very well.

Two pass JSP page rendering

Suppose an example. I have following interface:
public interface DataSource<T> {
Future<T> fetch();
}
This datasource can do asynchronous data fetching. And we have following tag for using datasource in JSP:
<html>
<d:fetch from="${orderDS}" var="orders">
<c:foreach in="${orders}" var="order">
<div class="order">
<c:out value="${order.title}" />
</div>
</c:foreach>
</d:fetch>
</html>
So, what I want? I want JSP rendering engine to call my custom tag (FetchTag in this example) twice. On first call FetchTag will do DataSource.fetch() call and save Future locally as a object field. On second call FetchTag do Future.get() call and will be blocked until data becomes available.
Is there any way to do such a thing?
I think a better design would not try to alter JSP rendering. Put all that database code on the server side, where it belongs, and use an AJAX call to get that data from a server-side component.
In general, I've found that embedding stuff in custom tag libraries is a bad idea. JSTL and/or Spring tag libraries are all that I need. If I feel like my UI needs to do more, I'm thinking about it incorrectly.
For JS disabled clients, I'd just make them do the round trip for the data and not try to do it in the background. Give them a choice: wait or turn on JS.

How do I expose bean in JSP?

How can I expose a Java bean to a JSP page by using struts? I know how to configure a StrutsAction to include a form-bean, but I wonder if there are other ways to interact with Java code from a JSP page? I ask this question because I don't understand fully a likely answer to a problem that I have asked here:
Clean way for conditionally rendering HTML in view?
EDIT:
I understand that a JavaBean is defined as a class that contains mainly getters and setters for its properties.
My problem was that I did not see how I can access parameters from Java classes in my JSP. Currently, I use a DynaForm to communicate parameters to the view. E.g. in the ActionClass I set the parameter, and in the JSP I can access it with
bean:write name="MyFormBean" property="myParameter"
My question was basically if there are other classes than a DynaForm class that can easily be accessed from inside the JSP with tags, and if so, if someone could provide an example.
In your action class:
MyBean myBean = new MyBean();
myBean.setSomeProperty("someValue");
request.setAttribute("myBean", myBean);
In your JSP:
<bean:write name="myBean" property="someProperty" scope="request"/>
You can do the same with session as well. Note that you don't have to explicitly specify the scope in <bean:write> tag - if you don't, Struts will look in all scopes from page to application.
More information on scopes is available in Java EE tutorial.

Using HTML builders in grails instead of GSP

is there a way to use groovy builders to build JSP files in a Grails application keeping things enough integrated?
To explain better: by default Grails uses gsp files that are nice but quite verbose..
<div class="clear">
<ul id="nav">
<li><g:link controller="snippets" action="list">Snippets</g:link></li>
<li><g:link controller="users" action="list">Users</g:link></li>
<li><g:link controller="problems" action="list">Problems</g:link></li>
<li><g:link controller="messages" action="list">Messages</g:link></li>
</div>
<div id="content">
is there a way to use groovy.xml.MarkupBuilder tha would turn the previous piece into
div(class:'clear') {
ul(id:'nav') {
li { g_link(controller:'snippets', action:'list', 'Snippets') }
// and so on
Of course g_link is invented just to give the idea..
Do a search for builder under the web layer section of the grails user guide. There is an example in there that shows you exactly how to do this using the xml builder.
I don't have a complete answer for you, but I suspect the key will be gaining access to the "view resolvers". In a normal SpringMVC app, these are configured in views.properties (or views.xml) as follows:
csv=com.example.MyCSVResolver
xml=com.example.MyXMLResolver
audio=com.example.MySpeechResolver
In a regular SpringMVC app, you return something like new ModelAndView(myModel, 'csv') from a controller action.
This would cause the CSVResolver class to be invoked passing it the data in myModel. In addition to containing the data to be rendered, myModel would likely also contain some formatting options (e.g. column widths).
Spring searches the views file for a key matching the view name. If it doesn't find a match, by default it just renders a JSP with the view name and passes it the model data.
Now back to Grails....remember that Grails is really just a Groovy API over SpringMVC and most of the features of SpringMVC can be accessed from Grails. So if you can figure out how to modify the views file, just change your controller actions to return an appropriate ModelAndView instance, and it should work as described above.
GSP allows you to run arbitrary Groovy code inside <% %> brackets. So you can have something like this (borrowing example from page linked to by BlackTiger):
<% StringWriter w = new StringWriter()
def builder = new groovy.xml.MarkupBuilder(w)
builder.html{
head{
title 'Log in'
}
body{
h1 'Hello'
builder.form{ }
}
}
out << w.toString()
%>
Note that the above calls g:form tag, and you can pass additional stuff to it.
So what you are asking for is certainly possible, though I am not sure if it will end up being a win. I'd suggest you perhaps look more at TagLibs in combination with Templates and SiteMesh Layouts - can definitely simplify things tremendously.

Categories