Home » Articles » Java Tips & FAQ

 Search   Site Map  

Keep your scopes clean

Avoiding polluted request, session and application objects

by Günther

Context

While writing web applications, some data has to be kept while processing incoming requests.
Any Java programmer who has ever written a web application with JSP and/or servlets will probably have used statements like these:
<% String language = (String)session.getAttribute("lang") %>
or
getServletContext().setAttribute("profile", profile );

As you'll probably already know, there are three scopes in which such data can be stored:

request
data in request scope is only available during the processing of that particular request. After that, it's gone.
This scope is particularly usefull when a single-point-of-access is created in the form of a Front Controller Servlet. This Front Controller is then able to set all needed data for the view to display in the request as attributes

session
Data bound in session scope is available during all requests in a particular session. If it is set during one request, it will be still around during the next requests of the same user, until the session times out or is invalidated. It is, however, strictly related to one and only one user

application
The Application scope is shared by all users of the web application and is the ideal place to store references to singleton instances, etc...

Problem

This way of working is very intuitive and easy.
There are however a few problems with this approach:

* All access is untyped.
Since any Object can be bound in any scope, the lookup also returns the Object type. This way, a cast to the expected type is required.
Only at runtime will the type of each and every attribute retrieved be checked.

* The namespace of request, session and application scope tends to become polluted in big projects.

When more then two or three attributes are to be stored in a scope, problems start to rise. Did we call the language parameter 'language', or was it 'lang'?
If you're honest, you'll have to admit that while working in a team, it's very difficult to keep these things under control.

If something goes wrong in your application with these issues, it's very time-consuming to debug, as the checks are only done at runtime.
Incorrect behaviour of the application ('forgetting' settings, etc...) may indicate problems related to what I described above.
Any good programmer will be able to clearly distinct what data belongs in request, session or application scope.

If you keep your code very clean (by using public static final String declarations for the binding keys, for example), and you make good progression.

Solution - A JavaBean per scope

There is, however a clean and simple solution that I haven't seen many programmers using.
In order to keep the data per scope well-defined, you could create a simple javabean with all needed accessore (get and set methods) per scope.
An instance of this javabean class will then be the only object that's bound in a particular scope.

An example: instead of coding a user's profile in session scope like this:

int id = ((Integer)session.getAttribute("userId", userId)).intValue();
String language = (String)session.getAttribute("language", language");

you could easily create a javabean like this:

public class SessionData {

public static final String = "SESSION_DATA_KEY";

protected int id;
protected String language;

public void setLanguage ( String language ) {
this.language = language;
}
public String getLanguage ( ) {
return language;
}

public void setUserId ( int id ) {
this.id = id;
}

public int getUserId ( ) {
return id;
}

}

This has the following advantages:

* Only one untyped lookup is needed
There is only one well-defined object bound in a particular scope. This removed the risk of 'polluted' session or application scopes.

* References to the actual needed data is typed
Once the reference to the bean is retrieved, every request to data becomes a simple getter method call.
For data set methods, the desired parameter type is checked by the compiler.

* primitive types (int, ...) can be stored easily. If you would store these in the session directly, you would need a wrapper class (java.lang.Integer, ...)

* Good overview of what data is available in what scope
Since the information about data is put explicitly in a javabean, you have a good overview of what data is in what scope.
When using request, session and application in direct, this is only done implicitly, and problems as dupplicated data, etc... always seem to emerge after a while.

In our example, the access to the data you need would become very simple:

SessionData sessionData = (SessionData) session.getAttribute(SessionData.SESSION_DATA_KEY);
int userId = sessionData.getUserId();
String language = sessionData.getLanguage ( );

This may seem quite a simple thing at first, merely worth mentioning in an article, but day-to-day practice has proven that many development hours are wasted on problems that could have been avoided with this approach.



New site design

Hope you like our new, more readable site design.

2004-03-07

JSpider project

We are officially announcing our newest project, JSpider!

2003-01-17   more ...

Articles section online

Our articles section is there! Subjects of all kind are covered.

2002-10-01   more ...

Please visit
WHIZlabs Software

they've got very good Certification test simulators!

BEA WebLogic & MySQL

Learn how to configure a MySQL datasource in BEA WebLogic in this article ...

Java WebServices

Read our book review of Beginning Java Webservices, and download a sample chapter!

Bruce Eckel e-books

We're mirroring some of Bruce Eckel's free e-books on Java and design patterns here!

http://www.javacoding.net