JSP (and Servlets) Random Notes

Until I find time to get more organized, here are a number of miscellaneous notes assembled when I find answers to JSP questions and don't want to have to go looking for them again.


POST oder GET : es ist die Frage

The advantage of using GET is a clear command line.

The advantages of using POST are:

  • Opacity of URL (command line). Sometimes you don't want the browser user to be able to see the mess you put there.
  • No length limit. GET is limited to an average 1K bytes in most implementations.
  • Easier not to run into character set issues—what one attempts to solve by employing:
    	request.setCharacterEncoding("UTF-8");
    			

Default POST action

When a JSP is posted without an explicit action, the behavior is to re-enter that JSP. Here, imagine one.jsp

	<%
	  /* farkle, starting out empty, will be filled in by the user, then
	   * transmitted to another.jsp when the Go button is clicked.
	   *
	   * (Unless passed into this JSP (one.jsp?farkle=something), farkle
	   * has no value to be got by this embedded Java code.
	   */
	  String  farkle = Parm.returnRequestMember( request, "farkle" ).trim();
	%>

	<form method="post" action="another.jsp">
	  <input type="text" name="farkle" value="<%=farkel %>" />
	  .
	  .
	  .
	  <input type="submit" value="Go" />
	</form>

When the submit button is clicked, the JSP containing the code above will launch another.jsp, while the following code will simply re-enter the current one. This is useful if you want to stay with the current one because of your UI design.

	<%
	  /* farkle, starting out empty the first time, will be filled in the
	   * next time through this JSP.
	   *
	   * (Unless passed into this JSP (one.jsp?farkle=something), farkle
	   * has no value to be got by this embedded Java code the first time around.
	   */
	  String  farkle = Parm.returnRequestMember( request, "farkle" ).trim();
	%>

	<form method="post">
	  <input type="text" name="farkle" value="<%=farkel %>" />
	  .
	  .
	  .
	  <input type="submit" value="Go" />
	</form>

Java servlet filters

Servlet filters are components that intercept and modify, for example, HTTP requests and responses from the server. For example, you might want to check the session used in a request to ensure it is current before allowing access to a page. This can be done on one or more pages as appropriate and, if not current, invoke authentication, e.g.: login.jsp so that the user can make it current.

Some cool uses of filters include:

	package com.etretatlogiciels.servlet.filter;

	import java.io.IOException;
	import java.util.Date;

	import javax.servlet.Filter;
	import javax.servlet.FilterChain;
	import javax.servlet.FilterConfig;
	import javax.servlet.ServletException;
	import javax.servlet.ServletRequest;
	import javax.servlet.ServletResponse;
	import javax.servlet.http.HttpServletRequest;

	public class LogFilter implements Filter
	{
	  /**
	   * Implement the actual filter, in this case, the information logging. Here
	   * can request, session or response information be modified, attributes added,
	   * etc.
	   */
	  public void doFilter( ServletRequest  req,
	                        ServletResponse res,
	                        FilterChain     chain)
	    throws IOException, ServletException
	  {
	    HttpServletRequest request = ( HttpServletRequest ) req;

	    // get the IP address of client machine...
	    String ipAddress = request.getRemoteAddr();

	    // log the IP address and current timestamp...
	    System.out.println( "Filter working!\nIP "
	                        + ipAddress
	                        + ", Time "
	                        + new Date().toString() );

	    chain.doFilter(req, res);
	  }

	  /**
	   * FilterConfig is passed from web.xml and contains
	   * Filter-level information and init parameters.
	   */
	  public void init( FilterConfig config ) throws ServletException
	  {
	      // get init parameter...
	      String testParam = config.getInitParameter( "test-param" );

	      // print the init parameter...
	      System.out.println( "Test Param: " + testParam );
	  }

	  /**
	   * This will be called by the container to garbage-collect if the filter hasn't
	   * been used for a while.
	   */
	  public void destroy()
	  {
	      //add code to release any resource
	  }
	}

This is combined with additions to a deployment file:

	<?xml version="1.0" encoding="UTF-8"?>
	<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	         xmlns="http://java.sun.com/xml/ns/javaee"
	         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
	                             http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	         id="WebApp_ID"
	         version="2.5">
	  <display-name>ServletFilterProject</display-name>
	  <welcome-file-list>
	    <welcome-file>index.html</welcome-file>
	    <welcome-file>index.htm</welcome-file>
	    <welcome-file>index.jsp</welcome-file>
	    <welcome-file>default.html</welcome-file>
	    <welcome-file>default.htm</welcome-file>
	    <welcome-file>default.jsp</welcome-file>
	  </welcome-file-list>

	  <filter>
	    <filter-name>LogFilter</filter-name>
	    <filter-class>
	      com.etretatlogiciels.servlet.filter.LogFilter
	    </filter-class>
	    <init-param>
	      <param-name>test-param</param-name>
	      <param-value>This parameter is for testing.</param-value>
	    </init-param>
	  </filter>
	  <filter-mapping>
	    <filter-name>LogFilter</filter-name>
	    <url-pattern>/*</url-pattern>
	  </filter-mapping>
	</web-app>

If we were identifying requests that needed to be authenticated, we could verify whether a session was current or not. We'd insert code similar to this:

	    .
	    .
	    .
	    HttpServletRequest  req = ( HttpServletRequest ) request;
	    HttpServletResponse res = ( HttpServletResponse ) response;

	    boolean             authorized   = false;
	    String              fileName     = "";
	    String              parentFolder = "";

	    int i = request.getRequestURI().lastIndexOf('/');

	    if( i > -1 )
	    {
	      fileName = request.getRequestURI().substring( i );

	      int j = request.getRequestURI().lastIndexOf( '/', i-1 );

	      if( j > -1 )
	        parentFolder = request.getRequestURI().substring( j );
	    }

	    request.setCharacterEncoding( "UTF-8" );
	    response.addHeader( "Expires", "-1" );

	    /* Check all pages to see if the user is properly logged in. The only ones not
	     * subject to this check are index.jsp and login.jsp (of course).
	     *
	     * If not logged in, redirect to login.jsp.
	     */
	    if (
	           !fileName.equals(" /index.jsp" )
	        && !fileName.equals(" /login.jsp" )
	       )
	    {
	      HttpSession session = request.getSession(false);

	      if( session != null )
	        authorized = isLoggedIn( session );

	      if( !authorized )
	      {
	        if( session != null )
	          session.invalidate();

	        log.debug( "Unauthorized access detected from "
	                   + request.getRemoteAddr()
	                   + "  ... redirecting to login page.");

	        RequestDispatcher r = req.getRequestDispatcher( "/login.jsp" );
	        r.forward(req, res);
	        return;
	      }
	    }
	  }

	  // pass along to next filter
	  chain.doFilter( request, response );
	}

	private boolean isLoggedIn( HttpSession session )
	{
	  Object o = session.getAttribute( "logged_in" );

	  return( o != null );
	}

Servlet parameters

Yet more servlet stuff. This is a means of communication between two applications via HTTP.

An HTTP servlet accepts the following URI consisting of

  1. protocol
  2. domain
  3. port-number
  4. path
  5. method
  6. method-name
  7. parameter
  8. value
  9. etc.

...assuming servlet.jsp is written to accept a method, name and parameters parm1 and parm2. The parameters come back by means of HttpServletRequest.getParameters( name ). The method and name pair is just another parameter and its value, and it could appear unorthogonally anywhere including the end of the URI. You have to be looking for by name to see if it's there.


	http://127.0.0.1:8080/Servlet/myservlet.jsp?method=name&parm1=value&parm2=value
	^       ^           ^    ^----------------------- ^       ^     ^      ^      ^      ^
	|       |           |    |                        |       |     |      |      |      |
	|       |           |    |                        |       |     |      |      |      value
	|       |           |    |                        |       |     |      |      parm
	|       |           |    |                        |       |     |      value
	|       |           |    |                        |       |     parm
	|       |           |    |                        |       method-name
	|       |           |    |                        method
	|       |           |    path
	|       |           port-number
	|       domain
	protocol

In Java, ...

	class MyServlet
	{
	  public static void processMethod1( String parm1, String parm2 )
	  {
	    // do first method processing...
	  }

	  public static void processMethod2( String parm1, int parm2 )
	  {
	    // do second method processing...
	  }
	}

...and in the JSP the processing is dispatched thus:

	<%
	String method = request.getParameter( "method" );

	if( method.equals( "method_1" ) )
	  MyServlet.processMethod1( request.getParameter( "parm1" ),
	                            request.getParameter( "parm2" ) );
	else if( method.equals( "method_2" ) )
	  MyServlet.processMethod1( request.getParameter( "parm1" ),
	                            Integer. parseInt( request.getParameter( "parm2" ) ) );
	%gt;

...etc. Obviously, different methods can have different parameters (or different types.