Do logic on apache tile attributes - java

In my apache tiles config file, I have a section like this:
<definition name="admin/*/*" extends="adminLayout">
<put-attribute name="key" cascade="true" value="{1}" />
</definition>
Then, in my JSP, I am would like to do some logic on the tile attribute.
Something like:
<c:if test="${key == 'value'}">
// do something
</c:if>
where key comes from the tile attribute.
How can I access this tile attribute inside the expression language?
I have tried
<c:set value="<tiles:insertAttribute name='key'/>" var="theKey"></c:set>
and
<c:if test="${<tiles:insertAttribute name='key'/> == 'value'}">
and both times the raw tiles xml is used as the comparing string - it doesn't get replaced by the attribute.

Use Tiles extras:
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:tiles="http://tiles.apache.org/tags-tiles"
xmlns:tilesx="http://tiles.apache.org/tags-tiles-extras"
version="2.0">
<tilesx:useAttribute id="keyJspVariable" name="key" classname="java.lang.String" />
<c:if test="${keyJspVariable== 'value'}">
// do something
</c:if>
Documentation example: https://tiles.apache.org/framework/tutorial/advanced/list-attributes.html

Related

JSP markup inside <tiles:put> or a or an alternative

I've inherited an old application that is using Struts 1.2 Tiles 1. For various annoying reasons I can't upgrade.
I'm not very familiar with Struts, or specifically Tiles in general and I'm trying to do something that makes sense in my head but I can't seem to make work in practice. Here's an example of what I'm trying to accomplish:
<tiles-definition>
<definition name="content-with-sidebar" path="/content_with_sidebar.jsp">
<put name="top" value="" type="string" />
<put name="sidebar" value="/tiles/sidebar.jsp" />
<put name="main" value="" type="string" />
<put name="bottom" value="" type="string" />
</definition
</tiles-definition>
content_with_sidebar.jsp
...
<tiles:insert attribute="top" flush="false" />
<div id="content">
<aside>
<tiles:insert attribute="sidebar" flush="false" />
</aside>
<div id="main">
<tiles:insert attribute="main" flush="false" />
</diV>
</div>
<tiles:insert attribute="top" flush="false" />
...
actual_page.jsp
<tiles:insert definition="content-with-sidebar" flush="false">
<tiles:put name="top" type="string">
<div>Maybe this page has something on the top that isn't the page header</div>
</tiles:put>
<!-- use the default sidebar -->
<tiles:put name="main">
<strong>Current Location:</strong>
<address><h:outputText value="#{locationDesc} #{zipCode}" /></address>
<!-- Some more dynamic jsp markup -->
</tiles:put>
<!-- This one doesn't have anything extra on the bottom -->
</tiles:insert>
This almost works but the dynamic bits get rendered above and outside the <tiles:insert> and the plain strings go where they should. I understand now, after much searching, that <tiles:put> in this, er, context, is expecting a plain ole string.
Is there a pattern to accomplish what I want with dynamic context?
As it stands I'm having to create another jsp file to be referenced by the <tiles:put> tag. i.e.
<tiles:put name="main" value="/actual_page_body.jsp" />
I'd rather not have to create an additional file when one would do. Any advice would be helpful.
With tiles, when the definition is rendered (content-with-sidebar in your code), the jsp corresponding to the 'path' attribute (/content_with_sidebar.jsp) will be invoked. All other jsps have to be manually invoked using a <tiles:insert>. What tiles provides you is a way to configurationally invoke them as definition attributes.

Composition is not rendered in Richfaces tabPanel

I am a user of JSF and Richfaces. I will simplify the code about my question to make things easier.
I have a composition named 'mytab.xhtml' defined like following:
<cc:interface>
<cc:attribute name="header" required="true"/>
</cc:interface>
<cc:implementation>
<rich:tab id="my-tab" header="#{cc.attrs.header}" >
<cc:insertChildren />
</rich:tab>
</cc:implementation>
This composition is used in another xhtml file like following:
<rich:tabPanel id="tp" switchType="ajax" headerPosition="top" >
<ic:mytab id="tab1" header="header1">
<h:outputText>content1</h:outputText>
</ic:mytab>
<ic:mytab id="tab2" header="header2">
<h:outputText>content1</h:outputText>
</ic:mytab>
</rich:tabPanel>
But it is very strange that the tab is not rendered at all.
To find the reason, if I add an outputText in the composition definition file like this:
<cc:interface>
<cc:attribute name="header" required="true"/>
</cc:interface>
<cc:implementation>
<h:outputText>#{cc.attrs.header}</h:outputText>
<rich:tab id="my-tab" header="#{cc.attrs.header}" >
<cc:insertChildren />
</rich:tab>
</cc:implementation>
The outputText will be rendered, but tab is not rendered.
Or, if I change one of the tab to richfaces tab directly:
<rich:tabPanel id="tp" switchType="ajax" headerPosition="top" >
<ic:mytab id="tab1" header="header1">
<h:outputText>content1</h:outputText>
</ic:mytab>
<rich:tab id="tab2" header="header2">
<h:outputText>content1</h:outputText>
</rich:tab>
</rich:tabPanel>
The first tab will not be rendered, but the second tab will be rendered.
Thank you if you could give me any help.
Composite components are rendered as own UINamingContainer. So between the UITabPanel and the UITab-component now is a UINamingContainer, UITab might not know what to do with it (same problem with datatable, by the way). What you can do is to use a classic facelet tag instead.

Dynamic JSF UI Components Generation

I'm trying to solve the following problem:
Let's say that I have a settings.xml file that looks as follows:
<SETTINGS>
<username fieldType="TextField" possibleValues="*">username_value</username>
<roletype fieldType="DropDownList" possibleValues="normal,admin,agent">admin</roletype>
<active fieldType="RadioButtons" possibleValues="true,false">true</active>
<SETTINGS>
What I'm trying to achieve is the following:
1- When my page first loads, it will parse this xml file, and layout the UI components based on the fieldType and the possibleValues.
2- When my UI components are loaded, I should be able to configure the value of my fields, which will end up persisting in my settings.xml file.
Is there a ready library that does this? Or do I need to write the code for this myself?
Note: I'm restricted to using JSF 1.x
Thanks in advance.
First of all , i will recommend to change the structure of your XML file as:
<SETTINGS>
<controls>
<control label="username" fieldType="TextField">
<values></values>
<selvalue></selvalue>
</control>
<control label="roletype" fieldType="DropDownList">
<values>
<value>normal</value>
<value>admin</value>
<value>agent</value>
</values>
<selvalue></selvalue>
</control>
<control label="active" fieldType="RadioButtons">
<values>
<value>true</value>
<value>false</value>
</values>
<selvalue></selvalue>
</control>
Now use JAXB to parase this XML file to the different classed, where each xml tab will be act as one independent class.
like :
Settings :
private List<Control> controls;
Control :
String label; // Attribute
String fieldType; // Attribute
Values values; //Property
String selValue; //Property
Values :
List<Value> values; ////Property
Value :
String value; //Property
DynaCritSearchBean : A Bean Class
Settings settings;
Once the data is loaded in to the corresponding class, use the following logic to dynamically create the screen in your XHTML file :
<h:panelGrid>
<c:forEach var="control"
items="#{dynaCritSearchBean.settings.controls}">
<h:panelGroup>
<h:outputText value="#{control.label}" />
</h:panelGroup>
<h:panelGroup>
<c:choose>
<c:when test="#{control.fieldType eq 'TextField'}">
<h:inputText value="#{control.selvalue}" />
</c:when>
<c:when test="#{control.fieldType eq 'DropDownList'}">
<h:selectOneMenu value="#{control.selvalue}">
<f:selectItem itemValue="" itemLabel="--select--" />
<c:forEach var="selOneValue" items="#{control.values.values}">
<f:selectItem itemValue="#{selOneValue}"
itemLabel="#{selOneValue}" />
</c:forEach>
</h:selectOneMenu>
</c:when>
<!-- Same as above logic for Radio button -->
</c:choose>
</h:panelGroup>
</c:forEach>
</h:panelGrid>
Once you submit the form, all selected/entered values are set to corresponding selValue of each Control.
Now, in order to get the XML back, you can use same JAXB concept which is very simple.

which one of these is the better approach of using tiles

Problem: I have two identical pages home.jsp and contact.jsp with same structure. They differs only in body content and title. I want to create a Layout page using tiles framework and reuse the code for the two JSPs. The controller framework is yet not decided, it may be Spring MVC 3 or Struts 2.
Solution A: Calling JSP files/views directly from controller/action classes.
I write a single definition in tiles.xml like:
<definition name="baseLayout" template="/WEB-INF/jsp/layout/baseLayout.jsp">
<put-attribute name="title" value="" />
<put-attribute name="header" value="/WEB-INF/jsp/includes/header.jsp"/>
<put-attribute name="body" value="" />
</definition>
Now in baseLayout.jsp:
<html>
<head><title><tiles:insertAttribute name="title"/></title></head>
<body>
<div class="wrapper">
<div class="header"><tiles:insertAttribute name="header"/></div>
<div class="body"><tiles:insertAttribute name="body"/></div>
</div>
</body>
</html>
Now in home.jsp
<tiles:insertDefinition name="baseLayout">
<tiles:putAttribute name="title">
Title for home page
</tiles:putAttribute>
<tiles:putAttribute name="body">
Content for home page
</tiles:putAttribute>
</tiles:insertDefinition>
Similarly for contact.jsp :
<tiles:insertDefinition name="baseLayout">
<tiles:putAttribute name="title">
Title for contact page
</tiles:putAttribute>
<tiles:putAttribute name="body">
Content for contact page
</tiles:putAttribute>
</tiles:insertDefinition>
Solution B: Calling the tiles definition of different JSP files from cotrollers/action classes. This approach requires one tiles definition for each of the JSP file I would be writing. So altogether 3 tiles definitions (one is for baseLayout and other two are for home and contact).
tiles.xml :
<definition name="baseLayout" template="/WEB-INF/jsp/layout/baseLayout.jsp">
<put-attribute name="title" value="" />
<put-attribute name="header" value="/WEB-INF/jsp/includes/header.jsp"/>
<put-attribute name="body" value="" />
</definition>
<definition name="home" extends="baseLayout">
<put-attribute name="title" value="Title for home page" />
<put-attribute name="header" value="/WEB-INF/jsp/home.jsp"/>
</definition>
<definition name="contact" extends="baseLayout">
<put-attribute name="title" value="Title for contact page" />
<put-attribute name="header" value="/WEB-INF/jsp/contact.jsp"/>
</definition>
baseLayout.jsp : Same as **Solution A**
home.jsp : Content for home page
contact.jsp : Content for contact page
I want advice on which one of the above approaches I should stick to.
The second solution is the best way:
You can have independent section in your tiles properties for each
jsp layout.
You can change anytime without effecting other layouts later on
The most traditional way using in struts
First solution:
May cause problems later on with having to edit them with any change
specially when you are deep in the project in advanced levels
More generic approach not suitable for struts/tiles architectural
designs
Solution B is the best approach to implement,
you will have individual style template what you can reuse later if required for other jsp's without messing the code in jsp like Solution A.
As of understanding the second approach is more clear and a common standard to follow.
Solution A helps maintenance in large applications by distributing configuration and also promoting name convention over explicit configuration. Moreover it is conceptually compatible with other templating solutions such as JSF or plain tags. For example see this: JSP tricks to make templating easier?
Think an application with hundreds of controllers and views written by different people over a large period of time. With solution B you will have to face a huge tiles.xml file. Add a slight lack of discipline and view names end up an inconsistent mess and content present inside the configuration (like your example).

Output key to localized message returning 0

I'm trying to output a key to a localized message in a jsp template in the following way:
<c:set var="logo-tooltip-title">
<fmt:message key="logo.tooltip.title"/>
</c:set>
<c:out value="${logo-tooltip-title}"/>
With the following in my messages.properties file:
logo.tooltip.title=Test
Does anyone know what I'm doing wrong here? Why does it return 0 instead of Test?
My goal is to output that message as title of the following link:
<a class="logo" href="/site/" title="${logo-tooltip-title}">
<img src="<hst:link path="/img/logo.png"/>" alt="logo" class="headlogo" width="80" height="100" />
</a>
Any thoughts on the best approach to do this?
Thanks!
EDIT:
yes I have set the context param in web.xml:
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>messages</param-value>
</context-param>
resource
Update:
This seems to work:
<fmt:message key="logo.tooltip.title" var="tooltip"/>
<c:out value="${tooltip}"/>
I don't think your problem is specific to HippoCMS.
I tried your syntax and I think you're missing a bundle declaration. If I add an org/ecausarano/Example.properties file to the war resources and:
<fmt:setBundle basename="org.ecausarano.Example" />
<c:set var="message">
<fmt:message key="message.message" />
</c:set>
<c:out value="${message}" />
it works for me.
JSTL tries to do math for "logo - tooltip - title" which results in 0. You've already found out that replacing the - by . solved the issue.

Categories

Resources