Struts

The goal of the Apache Struts project is to encourage application architectures based on the "Model 2" approach, a variation of the classic Model-View-Controller (MVC) design paradigm. Under Model 2, a servlet (or equivalent) manages business logic execution, and presentation logic resides mainly in server pages.\\ \\ The Apache Struts project encourages Model 2 designs in two ways. First, by providing open source frameworks and toolkits that help developers build applications for the web. Second, by providing friendly and honest mailing lists where both newcomers and veterans discuss how to use Struts software in their own Model 2 applications.\\ \\ Originally, the Apache Struts software was distributed as one monolithic bundle. Today, the Apache Struts project is comprised of two distinct frameworks and several other subprojects. The two frameworks are the Struts Action Framework and the Struts Shale Framework. Struts Action is the original request-based framework. Struts Shale is a component-based framework based on JavaServer Faces. Both frameworks are first-class citizens of the Apache Struts project.\\ \\ !!Struts Sample *[Install Tomcat|http://www.egjug.org/?q=tomcat_linux] *Create Application Directory After installing tomcat you should create a directory for your application to add the files you will create. In the tomcat directory you will find the __webapps__ directory like that "jakarta-tomcat-5.0.28\webapps" create a directory for your project called __StrutsProject__ and this folder will contain your files and folders. Your web application Should be like webapps | | StrutsProject | |---- java | --- src | --- org | -- egjug | --- WEB-INF | |--- classes | |--- lib *Add Struts Files and Libraries Struts framework require some libraries to be included in your project like: **commons-beanutils.jar **commons-digester.jar **jstl-1.1.1.jar **standard-1.1.1.jar **struts.jar Those files will be located under the __lib__ folder *Edit your web.xml *Create struts-config.xml *Create Your JSP Pages *Create Action Forms *Create Action Class *Edit struts-config.xml *Test your application !!Struts Tips *__Using tag:__ Using this tag, struts will render your page as XHTML. In My opinion, writing XHTML is the right thing to do. *__Using tag:__ As you know, Struts framework come with a set of html tags which encapsulate too many functionalities. ;__Using attributes from Action form__: You can use the setter & getter in the action form in your jsp code wheather you are using Struts HTML or JSTL. Simply write the name of the attribute and Struts will call the getter for you. What if you want to call a function? if the function called getXXX and XXX is not an attribute in the form bean, just call the xXX and Struts will do it also. Wonderfull!, but what if i have a function return boolean called isYYY will struts do it also? YES. ;__Forwarding to an Action in Another web context__: if you have 2 web application in the same project and produce 2 war or ear file how can you forward from action to another? Simply you will make the following code {{{ getServlet().getServletContext().getContext("/Webapp2").getRequestDispat cher("/action22.do").forward(request, response); }}} __Resources:__ *Struts Main Site http://Struts.apache.org *Struts Wiki http://wiki.apache.org/struts/ *[Beginer Tutorial|http://www.isabelle-hurbain.com/doc/struts.html]

Generic struts action to foward to Tiles pages

I had a problem with Struts tiles, every time you want to view a page you have defined in your tiles-def you have to make an action to forward to it, or define it in the global forwards. I consider this as a duplicates of the definition, specially because you really don't have to do any other thing. I solved the problem using the wild card struts action definition. This will let you make a generic action to forward to all your pages. See this example tiles-def.xml the tiles-def.xml contain the pages definitions. And the following struts-config.xml will contain the actions and forwards: if you request from your browser the action __DisplayLogin.do__ this will forward to viewLogin.page I think it is a great solution. I hope that this can help anyone to find the Struts best practice.

Struts Applications and Multilanguage Support

Struts Applications and
Multilanguage Support

In a
world that is getting smaller every day, the software developer's job is
changing. Just a few months or years ago, you wrote software for your company
that covered only this company's particular location or region. Now that you
switched from native applications to a wider range, supporting more than one
region and/or country, some of you are switching to J2EE, Web Applications, and
(in search of a powerful framework) getting in touch with Struts.

This article
introduces you to Struts and shows you how to build an application that can
support multiple languages, preserve the MVC pattern, and help you to easily
maintain your code. First, I discuss the principles of building multiple
language support, including the different choices you have and showing you the
enhanced possibilities that you can have with Struts.

Options for
Multilanguage Support

There are
many opportunities to deliver multiple language support to an application, and
each one has positives and negatives.

User's Choice

One of
the simplest ways to support more than one language is to provide a set of
static HTML pages for each language you want to support. Just consider one HTML
page as your starting point for an application and have a link for each
language (for example, "Click here to view this site in English").

After
this point, you can have separate page sets, but multiple times with the same
application logic. If you think about it, it's not very handy for a user
because he has to click on a link to only start this particular application.
And it's not very friendly for your content team or you as the developer. You
would run into the worst-case scenario: maintaining code that is equal in
multiple sets of pages or servlets.

Server's Choice

The next
step would be: "Hey, the user's browser is adjusted to a particular
region; let me think of it. The browser tells me which region and language the
user might like to see with every request to my server..."

Let's
have a look at the request, sort it out, and redirect the user to the correct
set of pages.

One of
the neat things that HttpServletRequest provides is
a simple way to retrieve the locale that is selected in the user's browser:

java.util.Locale currentLocale = request.getLocale();

Now that
you can get the locale, you can let the server automatically redirect the user
to the correct set of pages and servlets. But one problem is still present,
however: You have to maintain multiple sets of your pages and servlets.
Consider the pain that this may cause to a content publisher.

Struts

There is
an answer to this problem: Struts and its powerful application framework. With
Struts, you can support multiple languages at a glance. The Struts framework
separates your logic from the presented content, later referred to as messages.
You can easily manage your code, develop in a safe way, and stick with the
model view controller (MVC) pattern.

Experience Struts

A simple
way to let Struts manage your multilanguage needs is to use the standard Tag
libraries, which are located in your Struts distribution. There, you can find
the <bean:message/> tag. You have to utilize
the parameter "key", which tells Struts
which message it has to lookup.

To define
the keys and the proper messages, you need an ApplicationResourceBundle.
For every language you want to support, a single
ApplicationResources_xx_XX.properties file is required (where "xx_XX" stands for the specific locale; for
example, en_US).

Don't
forget to adjust struts-config.xml:

<message-resources parameter="strutsmessagewas4.resources.ApplicationResources"/>

The ApplicationResources.properties itself can be used for
messages that are the same for all languages. Make sure that your Resource
Bundles are available in the application's class path. A simple example
follows:

1.      
Include
the standard Struts Tag libraries:

2.   <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>

3.      
Start the
output of your JSP with the following tag:

<html:html locale="true"> 

Make sure that you pass the attribute locale; otherwise, Struts
does not look for the locale that the user's browser passes to the
server via its request.

4.      
Use bean
Tag Library to let the framework generate messages on the JSP:

<bean:message key="view.label.hello"/> 

This code tells Struts to look up a message identified by "view.label.hello" for the locale stored in the
current user's session.

5.      
Close
your JSP appropriately:

</html:html>

6.      
Don't
forget to customize the Resource Bundle mentioned above.

That was
pretty easy, and a lot of our problems are solved for the moment. We have a
solid code base and we don't need to recompile or change the presentation logic
when a change to content has to be made. But do we want content publishers to
be able to edit files on an application server? Especially when mostly every
Web Application accesses database systems? That brings us to the next step:
customizing Struts message handling.

Extending MessageResources

Because
we cannot tell the default message implementation to use a database for looking
up messages, we have to provide our own MessageResources implementation. The
minimum you have to do is to create two classes: the MessageResources
implementation itself and a factory class that is called to instantiate this.

Let's
start with the factory class:

package com.dbt.strutsmessage.model;
 
public class MessageResourcesFactory extends 
org.apache.struts.util.MessageResourcesFactory {
 
  /**
  * Factory to provide access to MessageResource implementation
  */
  public org.apache.struts.util.MessageResources createResources(String
    configuration) {
    return new MessageResources(this, configuration);
  }
}

All this
class does is expose a factory method that returns an instance of your
MessageResources implementation. Ensure that both classes are located in the
same package. I did not import org.apache.struts.util.MessageResourcesFactory
in order to avoid problems with the class loader.

The
second step is to create the MessageResources class. For the smallest
implementation, inherit org.apache.struts.util.MessageResources,
implement java.io.Serializable, and overwrite public String
getMessage(Locale currentLocale, String askedKey) {}
.

This is
the method that is called by the Struts framework to retrieve a message. Here
is where you ask your backend logic for the message, identified by the given
key and locale. A good suggestion for separating your business logic and
database-specific objects from the Struts presentation layer is to use a
singleton ApplicationModel

The last
step is telling Struts to use this implementation instead of the default
classes that come with the framework. This can be achieved by two parameters,
which are passed to the Struts instance via your web.xml.

Find the
section in which the Struts Action servlet is published and add the following:

<init-param>
  <param-name>application</param-name>
  <param-value>com.dbt.strutsmessage.model.MessageResources</param-value>
</init-param>
 
<init-param>
  <param-name>factory</param-name>
  <param-value>com.dbt.strutsmessage.model.MessageResourcesFactory</param-value>
</init-param>

You have
now created your own message handling logic.

Adding a Cache

Every
developer knows the good advice for architectures: they should be bullet-proof,
reliable, and fast in their execution.

"Only
call the datalayer if you can't have it in your cache!"

In this
case, we have to call the database every time a page makes use of <bean:message/>. Thinking of the type of data, we
can assume that this information is fully cacheable:

private synchronized void cacheLocale(Locale locale) {
  
  // has some thread already cached, while we are waiting for 
  // for this method?
  if(messageLocales.contains(locale)) {
    return;
  }
 
  String askedLocale = super.localeKey(locale);
 
  // ask Application for Messages associated to this locale
  Vector Messages = ApplicationModel.
            getApplicationModel().
            getMessagesByLanguage(askedLocale);
 
  // store messages in cache
  // ...
} 

For me,
the best practice is to check the presence of a set of messages for the current
asked locale, at the moment getMessage() is called.
If that fails, the application calls cacheLocale();
otherwise, it does not return either the message for this locale, or (if it is
not present) the message for the parent of the asked locale.

The
interesting thing about cacheLocale() is that you
have to be aware that more than one thread may want to call this method because
every call to the MessageFactory from within your JSP results in multiple
threads in this class. So we should recheck the cache for presence of the asked
locale because it's more than obvious that a thread before has cached the
locale for us.

 

AttachmentSize
strutsMessage.war.zip933.4 KB