Servlet 3.0 Annotations


Following are the annotations that MUST be supported by a Servlet 3.0 compliant web container.

1. @WebServlet

    • This annotation is used to define a Servlet component in a web application.
    • This annotation is specified on a class and contains metadata about the Servlet being declared. The urlPatterns or the value attribute on the annotation MUST be present.
    • It is recommended to use value when the only attribute on the annotation is the url pattern and to use the urlPatterns attribute when the other attributes are also used. It is illegal to have both value and urlPatterns attribute used together on the same annotation.
    • The default name of the Servlet if not specified is the fully qualified class name.
    • The annotated servlet MUST specify at least one url pattern to be deployed.
    • If the same servlet class is declared in the deployment descriptor under a different  name, a new instance of the servlet MUST be instantiated.
    • If the same servlet class is added to the ServletContext via the programmatic API “Programmatically adding and configuring Servlets”  the values declared via the @WebServlet annotation MUST be ignored and a new instance of the servlet with the name specified MUST be created.
    • Classes annotated with @WebServlet class MUST extend the javax.servlet.http.HttpServlet class.
    • Example

 

@WebServlet(”/foo”)
public class CalculatorServlet extends HttpServlet{
...
}
@WebServlet(name=”MyServlet”, urlPatterns={"/foo", "/bar"})
public class SampleUsingAnnotationAttributes extends HttpServlet{
public void doGet(HttpServletRequest req, HttpServletResponse res) {
...}
}

2. @WebFilter

    • This annotation is used to define a Filter in a web application.
    • The default name of the Filter if not specified is the fully qualified class name.
    • The urlPatterns attribute, servletNames attribute or the value attribute of the annotation MUST be specified.
    • Classes annotated with @WebFilter MUST implement javax.servlet.Filter.
    • Example

 

@WebFilter(“/foo”)
public class MyFilter implements Filter 
{
public void doFilter(HttpServletRequest req, HttpServletResponse res){
...
}
}

3. @WebInitParam

    • This annotation is used to specify any init parameters that must be passed to the Servlet or the Filter. It is an attribute of the WebServlet and WebFilter annotation.
    • Example

 

@WebServlet(value="/hello",initParams = {@WebInitParam(name="foo", value="Hello "),
                                         @WebInitParam(name="bar", value=" World!")
                     })
public class HelloServlet extends GenericServlet {
.....
}

4. @WebListener

    • The WebListener annotation is used to annotate a listener to get events for various operations on the particular web application context. Classes annotated with @WebListener MUST implement one of the following interfaces:
      javax.servlet.ServletContextListener
      javax.servlet.ServletContextAttributeListener
      javax.servlet.ServletRequestListener
      javax.servlet.ServletRequestAttributeListener
      javax.servlet.http.HttpSessionListener
      javax.servlet.http.HttpSessionAttributeListener

 

5. @MultipartConfig

    • This annotation, when specified on a Servlet, indicates that the request it expects is of type mime/multipart. The HttpServletRequest object of the corresponding servlet MUST make available the mime attachments via the getParts and getPart methods to iterate over the various mime attachments.

Programmatically adding and configuring web components


The ability to programmatically add a servlet and filter to a context is useful for framework developers.


package com.pkg.servlet30;

import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebListener;

@WebListener
public class SimpleServletContextListener implements ServletContextListener {

 @Override
 public void contextInitialized(ServletContextEvent sce) {
 ServletContext context = sce.getServletContext();

 String simpleServletName = "simpleServlet";
 String simpleFilterName = "simpleFilter";

 Map<String, String> initParams = new HashMap<String, String>();
 initParams.put("param1", "value1");
 initParams.put("param2", "value2");

 String[] urlPatterns = new String[]{"/simple"};

 ServletRegistration.Dynamic addServlet = context.addServlet(simpleServletName, NewServlet.class);
 addServlet.addMapping(urlPatterns);
 addServlet.setInitParameters(initParams);

 context.addFilter(simpleFilterName, NewFilter.class);

 }

 @Override
 public void contextDestroyed(ServletContextEvent sce) {

 }

}

 

The code is straightforward. It acquires the reference to ServletContext and makes use of the methods addServlet(), addMapping(), setInitParameters() and addFilter() for dynamically adding web components.

JSP Page and JSP Document


  • The difference between JSP Page and XML-BASED JSP Document is of syntax.
  • In JSP page we can put normal text but in JSP Document have <jsp:text> tag.
  • The XML syntax gives the JSP page author less complexity and more flexibility.
  • Jsp pages are saved having file extension of .jsp , while JSP documents having .jspx extension.

Rethrowing Exceptions with More Inclusive Type Checking


The Java SE 7 compiler performs more precise analysis of rethrown exceptions than earlier releases of Java SE. This enables you to specify more specific exception types in the throws clause of a method declaration.

Consider the following example:

  static class FirstException extends Exception { }
  static class SecondException extends Exception { }

  public void rethrowException(String exceptionName) throws Exception {
    try {
      if (exceptionName.equals("First")) {
        throw new FirstException();
      } else {
        throw new SecondException();
      }
    } catch (Exception e) {
      throw e;
    }
  }

This examples’s try block could throw either FirstException or SecondException. Suppose you want to specify these exception types in the throws clause of the rethrowException method declaration. In releases prior to Java SE 7, you cannot do so. Because the exception parameter of the catch clause, e, is type Exception, and the catch block rethrows the exception parameter e, you can only specify the exception type Exception in the throws clause of therethrowException method declaration.

However, in Java SE 7, you can specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration. The Java SE 7 compiler can determine that the exception thrown by the statement throw e must have come from the try block, and the only exceptions thrown by the try block can be FirstException and SecondException. Even though the exception parameter of the catch clause, e, is type Exception, the compiler can determine that it is an instance of either FirstException or SecondException:

  public void rethrowException(String exceptionName)
  throws <strong>FirstException, SecondException</strong> {
    try {
      // ...
    }
    catch (Exception e) {
      throw e;
    }
  }

This analysis is disabled if the catch parameter is assigned to another value in the catch block. However, if the catch parameter is assigned to another value, you must specify the exception type Exception in the throws clause of the method declaration.

In detail, in Java SE 7 and later, when you declare one or more exception types in a catch clause, and rethrow the exception handled by this catch block, the compiler verifies that the type of the rethrown exception meets the following conditions:

  • The try block is able to throw it.
  • There are no other preceding catch blocks that can handle it.
  • It is a subtype or supertype of one of the catch clause’s exception parameters.

The Java SE 7 compiler allows you to specify the exception types FirstException and SecondException in the throws clause in the rethrowException method declaration because you can rethrow an exception that is a supertype of any of the types declared in the throws.

In releases prior to Java SE 7, you cannot throw an exception that is a supertype of one of the catch clause’s exception parameters. A compiler from a release prior to Java SE 7 generates the error, “unreported exception Exception; must be caught or declared to be thrown” at the statement throw e. The compiler checks if the type of the exception thrown is assignable to any of the types declared in the throws clause of the rethrowException method declaration. However, the type of the catch parameter e is Exception, which is a supertype, not a subtype, of FirstException and SecondException.

Handling More Than One Type of Exception


In Java SE 7 and later, a single catch block can handle more than one type of exception. This feature can reduce code duplication and lessen the temptation to catch an overly broad exception.

Consider the following example, which contains duplicate code in each of the catch blocks:

catch (IOException ex) {
     logger.log(ex);
     throw ex;
catch (SQLException ex) {
     logger.log(ex);
     throw ex;
}

In releases prior to Java SE 7, it is difficult to create a common method to eliminate the duplicated code because the variable ex has different types.

The following example, which is valid in Java SE 7 and later, eliminates the duplicated code:

catch (IOException|SQLException ex) { logger.log(ex); throw ex; }

The catch clause specifies the types of exceptions that the block can handle, and each exception type is separated with a vertical bar (|).

Note: If a catch block handles more than one exception type, then the catch parameter is implicitly final. In this example, the catch parameter ex is final and therefore you cannot assign any values to it within the catch block.

Bytecode generated by compiling a catch block that handles multiple exception types will be smaller (and thus superior) than compiling many catch blocks that handle only one exception type each. A catch block that handles multiple exception types creates no duplication in the bytecode generated by the compiler; the bytecode has no replication of exception handlers

Strings in switch Statements


In the JDK 7 release, you can use a String object in the expression of a switch statement:

public String getTypeOfDayWithSwitchStatement(String dayOfWeekArg)
{
String typeOfDay;
switch (dayOfWeekArg)
{
case "Monday": typeOfDay = "Start of work week"; break;
case "Tuesday":
case "Wednesday":
case "Thursday": typeOfDay = "Midweek"; break;
case "Friday": typeOfDay = "End of work week"; break;
case "Saturday":
case "Sunday": typeOfDay = "Weekend"; break;
default: throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
}
return typeOfDay;
}

The switch statement compares the String object in its expression with the expressions associated with each case label as if it were using the String.equals method; consequently, the comparison of String objects in switch statements is case sensitive. The Java compiler generates generally more efficient bytecode from switch statements that use String objects than from chained if-then-else statements.

Underscores in Numeric Literals


In Java SE 7 and later, any number of underscore characters (_) can appear anywhere between digits in a numerical literal. This feature enables you, for example, to separate groups of digits in numeric literals, which can improve the readability of your code.

For instance, if your code contains numbers with many digits, you can use an underscore character to separate digits in groups of three, similar to how you would use a punctuation mark like a comma, or a space, as a separator.

The following example shows other ways you can use the underscore in numeric literals:

long creditCardNumber = 1234_5678_9012_3456L;
long socialSecurityNumber = 999_99_9999L;
float pi = 	3.14_15F;
long hexBytes = 0xFF_EC_DE_5E;
long hexWords = 0xCAFE_BABE;
long maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
long bytes = 0b11010010_01101001_10010100_10010010;

You can place underscores only between digits; you cannot place underscores in the following places:

  • At the beginning or end of a number
  • Adjacent to a decimal point in a floating point literal
  • Prior to an F or L suffix
  • In positions where a string of digits is expected

The following examples demonstrate valid and invalid underscore placements (which are highlighted) in numeric literals:

<strong>float pi1 = 3_.1415F;      // Invalid; cannot put underscores adjacent to a decimal point
float pi2 = 3._1415F;      // Invalid; cannot put underscores adjacent to a decimal point
long socialSecurityNumber1
  = 999_99_9999_L;         // Invalid; cannot put underscores prior to an L suffix</strong>

int x1 = _52;              // This is an identifier, not a numeric literal
int x2 = 5_2;              // OK (decimal literal)
<strong>int x3 = 52_;              // Invalid; cannot put underscores at the end of a literal</strong>
int x4 = 5_______2;        // OK (decimal literal)

<strong>int x5 = 0_x52;            // Invalid; cannot put underscores in the 0x radix prefix</strong>
<strong>int x6 = 0x_52;            // Invalid; cannot put underscores at the beginning of a number</strong>
int x7 = 0x5_2;            // OK (hexadecimal literal)
<strong>int x8 = 0x52_;            // Invalid; cannot put underscores at the end of a number</strong>

int x9 = 0_52;             // OK (octal literal)
int x10 = 05_2;            // OK (octal literal)
<strong>int x11 = 052_;            // Invalid; cannot put underscores at the end of a number