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
Tags :

About the Author

mkyong
Founder of Mkyong.com and HostingCompass.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

  • Pingback: paypal loans()

  • Pingback: laan nu og her()

  • Pingback: water ionizer machines()

  • Pingback: car parking()

  • Pingback: her og nu laan()

  • Pingback: car parking()

  • Pingback: fue.mobi()

  • Pingback: best DIRECTV deals()

  • Pingback: Cable for business owners()

  • Pingback: stream movies()

  • Pingback: watch movies online free()

  • Pingback: watch movies online free()

  • Pingback: stream movies()

  • Pingback: streaming movies()

  • Pingback: Blue Coaster33()

  • Sen

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

  • Nitya

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

  • 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

    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

    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

    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?????

  • http://yahoo.com <a href=’http://yahoo.com’>marry

    thanks 4 this nice tutorial ..

  • 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

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

    • http://www.facebook.com/profile.php?id=100003444641915 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

    It helped me alot..Thanks

  • Pingback: Including html in Struts2 form tags. | atechnicaljourney()

  • http://- 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.

    • http://www.facebook.com/winstonnanda winston

      Thank you jason, your suggestion solved my problem….

  • 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 javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
    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:414)
    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:230)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
    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

    Hope to get the solution for this problem

  • 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 ?

  • Ashok

    Nothing works………..

  • Ashok

    Nothing works….

  • 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

    • http://www.mkyong.com mkyong

      Put the CSS into the page that you want to use the new theme.

      Download the project to see how it works.

      • skl

        Thank you so much..it works !!

      • http://www.javatpoint.com jhon

        I think u r trying to make fool us. 2 exceptions are throwing this example. it is waste 4 me. u wasted my time

      • kumaran

        Hi Mykong,

        Iam very new to freemaker,i need suggestion from u r end. iam having a 3overview screen
        and different action class but i want to create one freemaker template for all action class
        according to the actin it should display the content. how can i do this please respond meeeeeee

        Thanks
        kumaran

  • 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

    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

    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

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

  • 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

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

      Thanks!

  • Pingback: Working with Struts 2 Theme & Template | CSS Guru How to CSS()