Working with Struts 2 Theme & Template

Download It – Struts2-Theme-Example.zip

In Struts2, when you put a “s:textfield” UI tag in the HTML page


<s:textfield key="global.username" name="username" />

The following 2 columns HTML table layout design will be generated automatically


<tr>
<td class="tdLabel">
  <label for="validateUser_username" class="label">Username:</label>
</td>
<td>
  <input type="text" name="username" value="" id="validateUser_username"/>
</td>
</tr>

Struts 2 is using the “Theme & template” feature to generate the pre-designed table layout for you.

Let’s see the sequences :

  1. Struts 2 see a “s:textfield” tag.
  2. Search the declared theme (if no theme declared , the default xhtml theme will be select).
  3. Search the corresponds theme’s template, e.g “s:textfield -> text.ftl” , “s:password ->password.ftl“. All the pre-defined HTML layout is defined in the ftl file.
  4. Bind the value into the template file.
  5. Display the final HTML markup.
Struts 2 tags + Theme’s template file (ftl) = Final HTML markup code.
Struts 2 is using the freemaker framework as the default template engine, all ftl files are written in freemaker script. No worry, the freemarker syntax is almost in human explains words, it’s quite easy to learn.

Working with Struts 2 Theme & Template

In this article, you will create a new theme to customize the error message location. In the default “xhtml” theme, the error message will appear above the field name.

Struts2 xhtml theme

In new theme, the error message will display beside the input field and highlight with a red color.

Struts2 mkyong theme

1. Extract the Theme

All the theme and template files are inside the struts2-core.jar, template folder. Extract it to your local drive.

The ftl file is just a normal text file, you can open it with any prefer text editors.

2. Create a new Theme

Create a new folder, copy all the existing xhtml template files (ftl) and put the new folder into project resource folder.

Struts 2 theme folder
To understand how Struts 2 find the theme template folder, read Struts 2 template directory selection for more detail.
Often times, you just need to copy and modify the existing “xhtml” theme, unless you have reason not to.

3. Define a new Theme

Define the “struts.ui.theme” and “struts.ui.templateDir” to tell Struts 2 where to find your new theme and template folder.

struts.xml


<struts>
    ...
 	<constant name="struts.ui.theme" value="mkyong" />
	<constant name="struts.ui.templateDir" value="template" />
	...
</struts>
Now, when Struts 2 see a “s:textfield“, it will find the “mkyong” theme instead of the default “xhtml” theme. Read Struts 2 select a theme for more detail.

4. Modify the Theme

To modify the existing template (ftl) file, you may need to know a bit freemarker syntax.

1. Create a new error-message.ftl file to display the error message.

error-message.ftl


<#--
	Only show message if errors are available.
	This will be done if ActionSupport is used.
-->
<#assign hasFieldErrors = parameters.name?? && fieldErrors?? && fieldErrors[parameters.name]??/>
<#if hasFieldErrors>
<#list fieldErrors[parameters.name] as error>
   <span class="errorMessage" errorFor="${parameters.id}">${error?html}</span><#t/>
</#list>
</#if>

2. Modify the controlheader.ftl by adding a new “errorsBg” class to “td” tag if errors exists.

controlheader.ftl


<#include "/${parameters.templateDir}/mkyong/controlheader-core.ftl" />
    <td
<#if hasFieldErrors>
    class="errorsBg" <#t/>
</#if>
<#if parameters.align??>
    align="${parameters.align?html}"<#t/>
</#if>
><#t/>

3. Modify the controlheader-core.ftl by delete many unnecessary tags and add a new “errorsBg” class to “td” tag if errors exists.

controlheader-core.ftl


<#--
	Only show message if errors are available.
	This will be done if ActionSupport is used.
-->
<#assign hasFieldErrors = parameters.name?? && fieldErrors?? && fieldErrors[parameters.name]??/>
<#--
	if the label position is top,
	then give the label its own row in the table
-->
<tr>

<td class="tdLabel <#t/>
<#--
<#if hasFieldErrors>
errorsBg"<#t/>
</#if>
-->
><#rt/>

<#if parameters.label??>
    <label <#t/>
<#if parameters.id??>
        for="${parameters.id?html}" <#t/>
</#if>
<#if hasFieldErrors>
        class="errorLabel"<#t/>
<#else>
        class="label"<#t/>
</#if>
 ><#t/>

<#if parameters.required?default(false) && parameters.requiredposition?default("right") != 'right'>
    <span class="required">*</span><#t/>
</#if>
${parameters.label?html}<#t/>
<#if parameters.required?default(false) && parameters.requiredposition?default("right") == 'right'>
 	<span class="required">*</span><#t/>
</#if>

</label><#t/>
</#if>

</td><#lt/>

4. Modify the text.ftl by adding a new template file “error-message.ftl” after the “simple/text.ftl“.

text.ftl


<#include "/${parameters.templateDir}/${parameters.theme}/controlheader.ftl" />
<#include "/${parameters.templateDir}/simple/text.ftl" />
<#include "/${parameters.templateDir}/mkyong/error-message.ftl" />
<#include "/${parameters.templateDir}/xhtml/controlfooter.ftl" />

5. Put the CSS in your view page to format the error message.


<style type="text/css">
.errorsBg{
	background-color:#fdd;
	color:red;	
	border: 1px solid;
}

.errorMessage{
	padding:0px 8px;
}

table{
	border-spacing: 4px;
}
td{
	padding:4px;
}
</style>

5. Done, saved it, now the error message will display beside the input field and highlight with red color.

Hope this article can give you a general concept about how to create or modify a theme in Struts2.

Reference

  1. http://freemarker.sourceforge.net/
  2. http://www.vitarara.org/cms/struts_2_cookbook/creating_a_theme
  3. http://struts.apache.org/2.0.14/docs/themes-and-templates.html
  4. http://www.packtpub.com/article/themes-and-templates-with-apache-struts2

About the Author

author image
mkyong
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter, or befriend him on Facebook or Google Plus. If you like my tutorials, consider make a donation to these charities.

Comments

Leave a Reply

avatar
newest oldest most voted
Mary James
Guest
Mary James

Get a free core java tutorial and java frameworks tutorials at how to program in java.

http://www.how-to-program-in-java.com/

Laddu
Guest
Laddu

Nice tutorial and you can also check here for spring framework tutorial and hibernate tutorial and core java tutorial
http://www.javalschool.com

mahesh sharma
Guest
mahesh sharma

Learn Java, Android with interview question At – javatpoint
http://www.javatpoint.com/java-tutorial

sarath
Guest
sarath

I have a doubt in double list.
the doubleOnChange not working in double list. but its working in the first part of doube list is; OnChange

Sascha Kleiber
Guest
Sascha Kleiber

IntelliJ keeps telling me it can’t resolve the symbol “mkyong” in the struts.ui.theme-value…

Sen
Guest
Sen

I did exactly the tutorial tells, but nothing works out….

Nitya
Guest
Nitya

Hi,Nice example.It works for me.But My submit button is rendering in the middle of the page..

Hemant
Guest
Hemant

I have taken the same example which is given here. But when I try to execute it shows the following error.

java.io.FileNotFoundException: Template /template/mkyong/form.ftl not found.
at freemarker.template.Configuration.getTemplate(Configuration.java:495)
at freemarker.template.Configuration.getTemplate(Configuration.java:458)
at org.apache.struts2.components.template.FreemarkerTemplateEngine.renderTemplate(FreemarkerTemplateEngine.java:96)
at org.apache.struts2.components.UIBean.mergeTemplate(UIBean.java:559)
at org.apache.struts2.components.ClosingUIBean.start(ClosingUIBean.java:59)
at org.apache.struts2.views.jsp.ComponentTagSupport.doStartTag(ComponentTagSupport.java:53)
at org.apache.jsp.index_jsp._jspx_meth_s_005fform_005f0(index_jsp.java:140)
at org.apache.jsp.index_jsp._jspService(index_jsp.java:109)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:389)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)

VenuGopal
Guest
VenuGopal

Hi,

I am using Simple theme in my application. It seems using Simple theme does not create javascript code in JSP. My validations are woking fine with Action-validation.xml. But I wish to have client side validation before posting the request to server. Is it possible to generate javascript code by using Simple theme?

AlexR
Guest
AlexR

I believe this article with the comments is sufficient to scare off the potential Freemaker users. And this is good. In order to move one label to another place I now need a directory of ftl files. I have to modify struts.xml, learn a crazy freemaker syntax, then modify 3 ftl files. And this is not enough. I’ll get absolutely incomprehensible errors (Java TemplateException etc.), and to fix them I have to study the implementation of the framework and change some sophisticated directives. I need all this to make a simplest example to work. Oh!

Nitish Bansal
Guest
Nitish Bansal

Search the corresponds theme’s template, e.g “s:textfield -> text.ftl” , “s:password ->password.ftl“. All the pre-defined HTML layout is defined in the ftl file.

My question is how these ftl file read by corresponding java file.
ex:
TextField.java read text.ftl how?????

<a href='http://yahoo.com'>marry
Guest
<a href='http://yahoo.com'>marry

thanks 4 this nice tutorial ..

Muthu
Guest
Muthu

Hai,

Thanks for your tutorial. Its working fine. But how can i change the color and style of

buttons and textboxes. Pls reply me!!!!

Binay
Guest
Binay

But how to inplement this tutorial for dropdown list and checkbox list..???
Thanks Binay

Aslan
Guest
Aslan

Christmas Sony Camera Deals 2012 on Light It Up This Christmasnot everyone would need a nose job but my giirfrlend really needs some rhinoplasty coz her nose is kind of…

Binay
Guest
Binay

It helped me alot..Thanks

trackback
Including html in Struts2 form tags. | atechnicaljourney

[…] banging my head against this, I eventually I found that the way to fix this was to use themes.  This blog describes a similar […]

JasonWee
Guest
JasonWee

works for me.. for the sample attachment, in the template folder, you only have a folder mkyong. it should also contain template from simple and xhtml. simple and xhtml can be extracted from struts2-core-.jar. i think that should solve majority of the errors reported by the devs in the comments. thanks.

winston
Guest
winston

Thank you jason, your suggestion solved my problem….

Kumar
Guest
Kumar
I am working on the themes in struts 2. I have taken the same example which is given here. But when I try to execute it shows the following error . FreeMarker template error! Error reading included file template/simple/form-common.ftl The problematic instruction: ———- ==> include “/${parameters.templateDir}/simple/form-common.ftl” [on line 26, column 1 in template/kumar/form.ftl] ———- Java backtrace for programmers: ———- freemarker.template.TemplateException: Error reading included file template/simple/form-common.ftl at freemarker.core.Include.accept(Include.java:153) at freemarker.core.Environment.visit(Environment.java:196) at freemarker.core.MixedContent.accept(MixedContent.java:92) at freemarker.core.Environment.visit(Environment.java:196) at freemarker.core.Environment.process(Environment.java:176) at freemarker.template.Template.process(Template.java:232) at org.apache.struts2.components.template.FreemarkerTemplateEngine.renderTemplate(FreemarkerTemplateEngine.java:148) at org.apache.struts2.components.UIBean.mergeTemplate(UIBean.java:530) at org.apache.struts2.components.ClosingUIBean.start(ClosingUIBean.java:58) at org.apache.struts2.views.jsp.ComponentTagSupport.doStartTag(ComponentTagSupport.java:54) at org.apache.jsp.login_jsp._jspx_meth_s_005fform_005f0(login_jsp.java:126) at org.apache.jsp.login_jsp._jspService(login_jsp.java:96) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:320) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:266) at… Read more »
Pierre
Guest
Pierre

Hello, i ve some trouble with your project ! did you test it before ?

i ve this error message : Could not find action or result: There is no Action mapped for namespace / and action name . – [unknown location]

I think there is an error in struts.xml or files are missing.

Can you help me ?

Bittu
Guest
Bittu

let check and test ur project @ Java Learning& Practice

Ashok
Guest
Ashok

Nothing works………..

Ashok
Guest
Ashok

Nothing works….

skl
Guest
skl

Hi,
where to copy the css file..
the step no. 5 is ambigous ??

@5. Put the CSS in your view page to format the error message.@

Can you pls elborate this.. I can’t figure out where to put the CSS..
I am using eclipse ! Many thanks

Daneal
Guest
Daneal

Hello, I can fixed it by :

1. form.ftl is reference a form-common.ftl
2. I has been change it to #include “/${parameters.templateDir}/simple/form.ftl” /

(I can not write open tag and close tag please fill it yourself)

Daneal
Guest
Daneal

Case :
include “/${parameters.templateDir}/simple/form-common.ftl” [on line 24, column 1 in template/mkyong/form.ftl]

Because : form-common.ftl is not found

Hello, I can fixed it by :

1. form.ftl is reference a form-common.ftl
2. I has been change it to

Daneal
Guest
Daneal

It’s error :

FreeMarker template error!

Error reading included file template/simple/form-common.ftl
The problematic instruction:
———-
==> include “/${parameters.templateDir}/simple/form-common.ftl” [on line 24, column 1 in template/mkyong/form.ftl]
———-

Java backtrace for programmers:
———-
freemarker.template.TemplateException: Error reading included file template/simple/form-common.ftl
at freemarker.core.Include.accept(Include.java:153)
at freemarker.core.Environment.visit(Environment.java:196)
at freemarker.core.MixedContent.accept(MixedContent.java:92)
at freemarker.core.Environment.visit(Environment.java:196)
at freemarker.core.Environment.process(Environment.java:176)
at freemarker.template.Template.process(Template.java:232)
at org.apache.struts2.components.template.FreemarkerTemplateEngine.renderTemplate(FreemarkerTemplateEngine.java:168)
at org.apache.struts2.components.UIBean.mergeTemplate(UIBean.java:530)
at org.apache.struts2.components.ClosingUIBean.start(ClosingUIBean.java:58)
at org.apache.struts2.views.jsp.ComponentTagSupport.doStartTag(ComponentTagSupport.java:54)
at org.apache.jsp.user.pages.login_jsp._jspx_meth_s_005fform_005f0(login_jsp.java:165)
at org.apache.jsp.user.pages.login_jsp._jspService(login_jsp.java:103)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:388)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.struts2.dispatcher.FilterDispatcher.doFilter(FilterDispatcher.java:413)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:291)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Unknown Source)
Caused by: java.io.FileNotFoundException: Template template/simple/form-common.ftl not found.
at freemarker.template.Configuration.getTemplate(Configuration.java:489)
at freemarker.core.Environment.getTemplateForInclusion(Environment.java:1357)
at freemarker.core.Include.accept(Include.java:143)
… 32 more

How to fix it?

Suresh
Guest
Suresh

It is very useful for developers who needs resources of J2EE..

John
Guest
John

Hello,
Could you do a post to modify the freemaker template in order to show error message underneath every field instead of above a field?

thanks

zanwar501
Guest
zanwar501

Please disregard. Eclipse is restarted and it is now working fine.

Thanks!

trackback
Working with Struts 2 Theme & Template | CSS Guru How to CSS

[…] reading here: Working with Struts 2 Theme & Template Share and […]