JSP redirect to another page

I found on this forum how to redirect to another page in JSP. One of the respondents explained it perfectly.

Well you have two options. Either you’ll do a server side forward or a client side redirect.
Server side forward has no interaction with the browser and therefore the URL on the location bar won’t change.
But if you do the HTTP redirect, the browser is instructed to load the other page and the contents of the location will change.
It’s your call which one to choose.

forward:

<% if (s1.equals(s2) ) { %>

     <jsp:forward page="s2.jsp"/>

<% } %>

redirect:

<% if (s1.equals(s2) ) {

    response.sendRedirect("s2.jsp");

} %>

ATG Parameter Names

Often in ATG form handler or droplet code one finds code like this:

public static final String OUTPUT = "output";

You can take advantage of ATG’s ParameterName class to represent any parameter name. From the ATG 2006.3 API Reference:

A ParameterName object can represent any parameter name used in Dynamo. Use this class when building your own droplets to create unique parameter names. The parameter names will then be stored in a global hashtable keyed by strings. Using this class allows the parameters of a droplet to be publicly available as well as enforcing good coding standards whereby the parameter name string only appears once in the java code.

Throughout ATG’s public source you can see that many parameter names have already been defined. For brevity sake I have omitted the “public final static” prefix.

ParameterName ARRAY = ParameterName.getParameterName("array");
ParameterName DEBUG = ParameterName.getParameterName("debug");
ParameterName DEFAULT = ParameterName.getParameterName("default");
ParameterName ELEMENT_NAME = ParameterName.getParameterName("elementName");
ParameterName EMPTY = ParameterName.getParameterName("empty");
ParameterName EQUAL = ParameterName.getParameterName("equal");
ParameterName GREATERTHAN = ParameterName.getParameterName("greaterthan");
ParameterName INDEX_NAME = ParameterName.getParameterName("indexName");
ParameterName IN_URL = ParameterName.getParameterName("inUrl");
ParameterName LESSTHAN = ParameterName.getParameterName("lessthan");
ParameterName NONCOMPARABLE = ParameterName.getParameterName("noncomparable");
ParameterName NON_SECURE_URL = ParameterName.getParameterName("nonSecureUrl");
ParameterName OBJ1 = ParameterName.getParameterName("obj1");
ParameterName OBJ2 = ParameterName.getParameterName("obj2");
ParameterName OUTPUT = ParameterName.getParameterName("output");
ParameterName OUTPUT_END = ParameterName.getParameterName("outputEnd");
ParameterName OUTPUT_START = ParameterName.getParameterName("outputStart");
ParameterName PATH = ParameterName.getParameterName("path");
ParameterName REVERSE_ORDER = ParameterName.getParameterName("reverseOrder");
ParameterName SECURE_URL = ParameterName.getParameterName("secureUrl");
ParameterName SORT_PROPERTIES = ParameterName.getParameterName("sortProperties");
ParameterName TRUE  = ParameterName.getParameterName("true");
ParameterName UNSET = ParameterName.getParameterName("unset");
ParameterName VALUE = ParameterName.getParameterName("value");
ParameterName CURRENCY_PARAM = ParameterName.getParameterName("currency");
ParameterName EURO_SYMBOL_PARAM = ParameterName.getParameterName("euroSymbol");
ParameterName LOCALE_PARAM = ParameterName.getParameterName("locale");
ParameterName TARGET_LOCALE_PARAM = ParameterName.getParameterName("targetLocale");
ParameterName YEN_SYMBOL_PARAM = ParameterName.getParameterName("yenSymbol");

Stats on Dreamhost with WordPress

Analog: WWW logfile analysisOn my WordPress blogs hosted by Dreamhost to get stats I needed to add this to the .htaccess file.

# BEGIN Stats
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/(stats|failed_auth\.html).*$ [NC]
RewriteRule . - [L]
</IfModule>
# END Stats

This is further explained in the Dreamhost Wiki page Making stats accessible with htaccess.

Dreamhost uses Analog to generate web statistics. Other recommended AWStats which seems more powerful. Maybe I’ll switch if I feel the need.

Playing with Dates in Java

I always forget how to do these things so I thought I should write it down.

Changing Dates:

Here is an example of getting the date for seven days ago from now.

    Calendar sevenDaysAgo = Calendar.getInstance();
    sevenDaysAgo.add(Calendar.DATE, -7);
    sevenDaysAgo.set(Calendar.HOUR_OF_DAY, 0);
    sevenDaysAgo.set(Calendar.MINUTE, 0);
    sevenDaysAgo.set(Calendar.SECOND, 0);
    sevenDaysAgo.set(Calendar.MILLISECOND, 0);

Formatting Dates:

Here is the simple way to format a date and time.

    DateFormat.getDateTimeInstance().format(sevenDaysAgo.getTime()))

The output is:

    May 21, 2008 12:00:00 AM

Note that according to the JavaDoc, DateFormats are inherently unsafe for multithreaded use. You should not make a call to a static instance of a DateFormat nor share a single instance across thread boundaries without proper synchronization.  The same applies to Calendar.  For more information on this see Sun Bug #6231579 and Sun Bug #6178997.

Creating Dates:

Here is an example of creating a date, the birth date January 1, 1970.

    Calendar birthDate = Calendar.getInstance();
    birthDate.clear();
    birthDate.set(Calendar.YEAR, 1970);
    birthDate.set(Calendar.MONTH, 0);
    birthDate.set(Calendar.DATE, 1);

For further reading please Create a Date object using the Calendar class and of course the JavaDocs for Calendar, Date and DateFormat.

Invalid column type SQLException with ATG Repository

Recently I was seeing this exception.

CONTAINER:atg.repository.RepositoryException; SOURCE:java.sql.SQLException: Invalid column type
        at atg.adapter.gsa.GSAItemDescriptor.executeQuery(GSAItemDescriptor.java:6682)
        at atg.adapter.gsa.GSAView.executeUncachedQuery(GSAView.java:291)
        at atg.adapter.gsa.GSAView.executeQuery(GSAView.java:1027)
        at atg.repository.rql.RqlStatement.executeQuery(RqlStatement.java:208)

For the longest time I could not figure out what this meant and then it dawned on me as I laid in bed.

ATG expects certain Java class types for certain repository types which correspond to certain class types. I talk about this in my Date and Timestamp Repository Data Types post.

I was trying to do this RQL query:

      lastModified > ?0

with this parameter:

      java.util.Calendar param = java.util.Calendar.getInstance();

When I changed the parameter to type:

      java.sql.Timestamp

I no longer saw this exception which makes sense because the lastModified property is of data-type timestamp.

Log4j levels

I always forget which level is which in Log4j so I copied this from the JavaDoc for the Level class.

static Level ALL
The ALL has the lowest possible rank and is intended to turn on all logging.
static Level DEBUG
The DEBUG Level designates fine-grained informational events that are most useful to debug an application.
static Level ERROR
The ERROR level designates error events that might still allow the application to continue running.
static Level FATAL
The FATAL level designates very severe error events that will presumably lead the application to abort.
static Level INFO
The INFO level designates informational messages that highlight the progress of the application at coarse-grained level.
static Level OFF
The OFF has the highest possible rank and is intended to turn off logging.
static Level TRACE
The TRACE Level designates finer-grained informational events than the DEBUG
static Level WARN
The WARN level designates potentially harmful situations.

JSTL for current URI

I was wondering how do get the current URI using JSTL and found this forum thread, JSTL EL for current page URL?.

If you want the actual URI of the JSP that is being rendered:

<c:out value="${pageContext.request.requestURI}"/>

If you want the original URI, which is probably the case, then:

<c:out value="${requestScope['javax.servlet.forward.request_uri']}"/>

In DSP if you want the original URI you can use the OriginatingRequest bean which implements the HttpServletRequest.

<dsp:valueof bean="/OriginatingRequest.requestURI" />

Monit and Mongrel

This post about Monit and Mongrel is based on this fantastic post, Monit makes Mongrel play nice!

Install Monit from source:

$ wget http://www.tildeslash.com/monit/dist/monit-4.10.1.tar.gz
$ tar xvfz monit-4.10.1.tar.gz
$ cd monit-4.10.1
$ ./configure -prefix=/usr  (the default prefix is /usr/local)
$ make
$ make install

Configure Monit:

In the monit source you will find a sample monitrc which is completely commented out. You can then copy it to wherever you like and then edit it. Here is my monitrc.

# Start monit in the background (run as a daemon) and check services at
# 1-minute intervals.
set daemon  60

# Set logging.
set logfile /tmp/monit.log

# Set the list of mail servers for alert delivery.
set mailserver localhost

# Set alert recipients.
set alert foo@example.com                # receive all alerts

# Start Monit's embedded web server.
set httpd port 2812 and
     allow admin:monit      # require user 'admin' with password 'monit'

# Mongrel - Development
# Check that Mongrel is running and that it responds to HTTP
# requests. Check its resource usage such as cpu and memory. If the
# process is not running, monit will restart it by default. In case
# the service was restarted very often and the problem remains, it is
# possible to disable monitoring using the TIMEOUT statement.
check process mongrel-dev with pidfile /rails/log/mongrel.pid
    start program = "/usr/bin/mongrel_rails start -d  -c /rails
                          -p 3000 -P /rails/log/mongrel.pid"
    stop program  = "/usr/bin/mongrel_rails stop
                           -P /rails/log/mongrel.pid"
    if cpu > 50% for 2 cycles then alert
    if cpu > 80% for 5 cycles then restart
    if totalmem > 60.0 MB for 5 cycles then restart
    if loadavg(5min) greater than 10 for 8 cycles then restart
    if failed port 3000 protocol http
       with timeout 15 seconds
       for 2 cycles
       then restart
    if 3 restarts within 5 cycles then timeout
    group mongrel-dev

After you are done configuring monitrc copy it to /etc.

$ sudo cp monitrc /etc

To test the configuration:

$ sudo monit -t

Run Monit:

To start monit:

$ sudo monit

To restart monit:

$ sudo monit reload

To stop monit:

$ sudo monit quit

To see monit’s log (assuming you are using my configuration):

$ tail -f /tmp/monit.log

Learn More:

Monit Getting Started
Monit Manual

Google Doctype

Chris Weekly says Google Doctype looks like “a new, excellent resource for keeping up with webdev tips and tricks, browser compatibility issues, etc.”

Documenting the Open Web

Browse Google Doctype

Google Doctype is an open encyclopedia and reference library. Written by web developers, for web developers. It includes articles on web security, JavaScript DOM manipulation, CSS tips and tricks, and more. The reference section includes a growing library of test cases for checking cross-browser and cross-platform compatibility.

Google Doctype is 100% open.

  • Open source
  • Open content
  • Open to contributions from anyone

Size of collection in a JSP/DSP page

leaf pile on Flickr

(Photo: leaf pile by oeimah)

Sometimes in a JSP/DSP page you will want to get the size of a collection and unless you are within a Range, ForEach or similar droplet you won’t have access to this value.

Struts has a nice solution using the bean:size tag.  JSTL 1.1 has a nice solution using the fn:length function.

Here is an example of how to use Struts, DSPEL and JSTL to get the size of a collection.

  <dspel:getvalueof param="book.pages" var="pages"
                    vartype="java.util.Collection"/>
  <bean:size id="numPages" name="pages"/>
  Number of Pages: <c:out value="${numPages}"/>
  Number of Pages: <dspel:valueof value="${numPages}"/>

Here is an example of how to use JSTL 1.1 and DSPEL to get the size of a collection.

 

  <dspel:getvalueof param="book.pages" var="pages"
                    vartype="java.util.Collection"/>
  Number of Pages: <c:out value="${fn:length(pages)}"/>