Servlet Reveal

……… posted by Davide Pisano

The Servlet version 2.5, introduces new  feature, the most important of which is annotation. The following two sections provide a view on the difference between 2.4 and 2.5 versions and  between 2.5 and 3.0 versions.

Servlet 2.5 vs Servlet 2.4

The Servlet Version 2.5 introduces an important feature, that makes servlets "modern": the use of J2EE 5 Containers. Other relevant new features are the introduction of Multiple Occurrences for servlet mapping and filter mapping.

J2EE Containers

Java EE defines a naming environment that allows applications to easily access resources and external information without explicit knowledge of how the external information is named or organized. It has been made in the Web application deployment descriptor for specifying information allowing a servlet to obtain references to resources and enterprise beans:

  • env-entry
  • ejb-ref
  • ejb-local-ref
  • resource-ref
  • resource-env-ref
  • service-ref

Servlets, also supporting annotation and dependency injection to reference resource and enterprise beans. The next annotation introduced into Servlet to operate with J2EE Containers are:

  • @EJB, @EJBs, @PersistenceContext, @PersistenceContexts, @PersistenceUnit,  @PersistenceUnits.  These reference EJB components, particularly the first two annotations provide the equivalent functionality of declaring the ejb-ref or ejb-local-ref elements in the deployment descriptor, they inject a referenced bean

@EJB 
private EJBSample ejbSample;
@EJBs({@EJB(EJBSample1), @EJB(EJBSample2)} ) 
private EJBSample[] ejbSamples;

@PersistenceContext(type=EXTENDED)
EntityManager em;

@PersistenceUnit
EntityManagerFactory emf;

  • @DeclaresRoles, @Run-as. The first annotation is used to define the security roles that comprise the security model of the application. The @RunAs annotation is equivalent to the run-as element in the deployment descriptor.

@DeclaresRoles("Admin")
public class AdminServlet ...

is equivalent to
<web-app>
  <security-role>
    <role-name>Admin</role-name>
  </security-role>
</web-app>

@RunAs("Admin")
public class AdminServlet
 
is equivalent to
<servlet>
  <servlet-name>AdminServlet </servlet-name>
  <run-as>Admin</run-as>
</servlet>
  • @Resource, @Resources, are used to declare a reference to one (first case) or more (second case) data sources. @WebServiceRef, @WebServiceRefs serve to reference a web service resource; This tag annotation is used to define a reference to a web service and (optionally) an injection target for it, it can be used to inject both service and proxy instances. In order, the correspondence with the application deployment descriptor are resource-ref, resource-env-ref, service-ref
@Resource
private javax.jms.ConnectionFactory connectionFactory
@Resources (
{@Resource(name="myDB" type=javax.sql.DataSource),
@Resource(name="myMQ" type=javax.jms.ConnectionFactory)}
)
@WebServiceRef(MyService.class)
private javax.xml.ws.Service service;

MyService is the service class, that extends javax.xml.ws.Service.
@WebServiceRef(name="MyWs",wsdlLocation="META-INF/MyWsEJBServiceService.wsdl")
private MyService service;

where my service class extends javax.xml.ws.Service.
  • Using Servlet 2.5 it is possible to create a custom init() and/or destroy() servlet methods. @PostConstruct: this method is called after the resource injections have been completed and before any life-cycle methods on the component are called. @PreDestroy: the method is called prior to the component being removed by the container.
@PostConstruct
public void postConstruct() {
...
}
@PreDestroy
public void preDestroy() {
// clean up any open resources
...
}

Multiple Occurrences

There are two other relevant new features in servlet version 2.5.

Multiple Occurrences of Servlet Mappings: the previous servlet version allows only a single url-pattern or servlet name per servlet mapping in the web application deployment descriptor. In the current version it is possible to map a servlet to multiple URLs repeating the whole mapping clause.

<servlet-mapping> 
  <servlet-name>MyServlet</servlet-name> 
  <url-pattern>/path1/*</url-pattern> 
  <url-pattern>/path2/*</url-pattern> 
  <url-pattern>/path3/*</url-pattern> 
</servlet-mapping>

Multiple Occurrences Filter Mappings: Previous versions of the servlet schema allows only a single url-pattern in a filter mapping, now it is possible to have more than one url-pattern, like in the following example:

<filter-mapping>
  <filter-name>MyFilter</filter-name>
  <url-pattern>/urlpattern1/*</url-pattern>
  <url-pattern>/urlpattern2/*</url-pattern>
  <servlet-name>Logger</servlet-name>
</filter-mapping>

Servlet 3.0 vs Servlet 2.5

The  Servlet version 3.0 follows on from the Servlet 2.5 revolutionary road introducing support for annotations and web fragments and support for suspend / resume to allow async support in servlets. Reading Java Servlet Specification 3.0 (proposed final draft) you can see the changes to Servlet 2.5 as very relevant.

Annotations and Web-Fragment

In this servlet version the deployment descriptor contains  a “metadata-complete” attribute on the web-app element. This attribute defines when the web descriptor is complete or class files must be examined for annotation and web fragment. In other words, if metadata-complete attribute is set to true, the deployment tool must ignore any servlet annotations present in the class files; if the metadata-complete attribute is not specified or is set to "false", the deployment tool must examine the class files.

<metadata-complete> false </metadata-complete>

Let's look at some annotation

  • @WebServlet: define a servlet component in a web application, and is specified on a class. The only required attributes are the url-Patterns or the value attribute.
@WebServlet(name="myservlet", urlPatterns="/url1","/url2"}) 
public class MyServlet extends HttpServlet { 
  .... 
}
  • @WebtFilter: It is specified on a class and defines a Filter in a web application the required attributes are urlPatterns or the value attribute.
@WebFilter(urlPatterns={"/path1","/path2"}) 
public class TestFilter implements .Filter { 
....
}
  • @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.
@WebServlet(name="myservlet", urlPatterns={"/url1","/url2"},initParams={ @WebInitParam(name="p1", value="v1"), @WebInitParam(name="p2", value="v2") }) 
public class MyServlet extends HttpServlet { 
    .... 
}
  • @WebListener: is used to annotate a context listener to get events for various operations on the particular web application context.
@WebListener
public class MyServCListener implements ServletContextListener ....
  • @MultipartConfig This annotation, when specified on a Servlet, indicates that the expected request type is mime/multipart

By default all applications will have index.html and index.jsp in the list of welcome-file-list. The descriptor may to be used to override these default settings.

    This servlet version also anticipates web-fragments. It is a part or all of the web.xml that can be specified and included in a library framework jar's META-INF directory: web.xml file has locatiton into the WEB-INF directory, instead a web-fragment.xml is placed inside jar file and has metadata information in the form of deployment descriptor then the web-fragment.xml descriptor must be in the META-INF/ directory of the jar file. During deployment the container is responsible for scanning the location specified above and discovering the web-fragment.xml and processing them. Next an Example of a web-fragment.xml

<web-fragment>
<servlet>
<servlet-name>ServletInFragment</servlet-name>
<servlet-class>WelcomeServletInFragment</servlet-class>
    </servlet>
    <listener>
        <listener-class>ListenerInFragment</listener-class>
</listener>
</web-fragment>

    The order in which configuration from web-fragment.xml and annotations should be applied is undefined. If ordering is an important aspect for a particular application please see rules defined below on how to achieve the order desired.

In a web.xml or a web-fragment.xml could be present a <name>, it must be considered for ordering options.

To express the ordering preference you could use <absolute-ordering> element in the web.xml. this tag can contains other <name> elements to refers to other web-fragment, they indicate the absolute order in which those named web-fragments, which may or may not be present, must be processed. If there are multiple name element with the same content, only the first occurrence is processed.

A web-fragment.xml may have an <ordering> element for ordering name element. In this case if there are multiple occurrence of name tag with the same name, an exception is made and deployment is interrupted.

If absolute-ordering tag is present in the web-fragment.xml, it is ignored. if an ordering tag is present in a web.xml, it is ignored.

Some example:

web-fragment1.xml
<web-fragment>
<name>MyFragment1</name>
<ordering><after>MyFragment2</after></ordering>
...
</web-fragment>


web-fragment2.xml
<web-fragment>
<name>MyFragment2</name>
...
</web-fragment> 


web-fragment3.xml
<web-fragment>
<name>MyFragment3</name>
<ordering><before><others/></before></ordering>
...
</web-fragment>


web.xml
<web-app>
<name>MyApp</name>
...
</web-app>

the processing order will be
web.xml
web-fragment3.xml
web-fragment2.xml
web-fragment1.xml

In the example:
<before> means the document must be ordered before the document with the name matching what is specified within the nested <name> element
<after> means the document must be ordered after the document with the namematching what is specified within the nested <name> element.
<others /> which may be included zero or one time within the <before> or <after> element. if it is included into <before> it indicate that that the document is moved at the had of the ordered list. If it is into <after> tag, the document is moved at the end of the ordered list.

Another Example:

web.xml
<web-app>
   <name>MyApp</name>
   <absolute-ordering>
     <name>MyFragment3</name>
     <name>MyFragment2</name>
   </absolute-ordering>
...
</web-app>

the sorted document list is:
web.xml
MyFragment3
MyFragment2

Asynchronous processing

Sometimes a filter or a servlet can't complete a request process without waiting for a resource; a servlet may need to wait for an available JDBC connection, a jms message, or an event.For the servlet, waiting is an inefficient operation as it is a blocking operation that consumes a thread and other limited resources. This servlet version provides the ability for asynchronous processing. When an async request begins, another thread is generated and provides for the request, dispatching it so that it may run in the context of the container.

@WebServlet and @WebFiler annotation have an attribute asyncSupported (boolean with default value false). When this parameter is set to true, the application can start an asynchroous processing in a separete thread calling startAsync. The response only after complete is call on the AsyncContext. A way to complete a response is dispatching froma servlet that support async to on that do not support it; in this case the container call complete on the AsyncContext. To complete the asynchronous process is also possible call directly AsyncContext.complete.

To have the Asynchronous processing additional method and classes are added. Into the ServletRequest follow method are added

public AsyncContext startAsync(ServletRequest req,ServletResponse res)
public AsyncContext startAsync()

   This 2 methods put ths request into asyanc mode and initializes it's AsyncContext

public AsyncContext getAsyncContext()

  Return the AsyncContext if startAsync was called.

public boolean isAsyncSupported()

   Return true if request support async processyng

public boolean isAsyncStarted()

   Return true if if startAsync was called

public void addAsyncListener(asyncListener, req, res)
public void addAsyncListener(asyncListener)

   Register a listener for notifications of time-out and complete

public void setAsyncTimeout(long timeoutMilliseconds)

   This is the timeout setter for the async processing to occur.

public long getAsyncTimeout()

   This is the timeout setter for the async processing to occur.

Into the ServletRequest follow method are added:

public ServletRequest getRequest()
   Return the request that was used to initialize the object by the ServletRequest.startAsync

public ServletRequest getResponse()

   Return the response that was used to initialize the object by the ServletRequest.startAsync

public void dispatch(path)
public void dispatch()
public void dispatch(ServletContext context, String path)

   Dispatch the AsyncRequest to the url of the request or to the url passed as parameter. After a call to one of those, the method dispatcher returns immediately after scheduling the dispatch to be done by the container. Control of the request and response objects of this AsyncContext is handed off to the target resource and the response will close when the target resource of the dispatch has completed execution and a subsequent call to startAsync has not been made.

public boolean hasOriginalRequestAndResponse()

   This method check if the AsynContext was initialized with the original request and responce.

public void start(Runnable r)

   This method allows the container to dispatch a thread to run.

public void complete()

   This method MUST be called to complete the async process and close the response.

Other Added class are: ServletRequestWrapper, ServletResponseWrapper, AsyncListener

Follow an example of use of the AsyncContext

@WebServlet("/asyncservlet", asyncSupported=true)
public class MyServlet extends HttpServlet { 

  @WebServiceRef
   private static Service myWebServiceService;
  ......
   public void doGet(HttpServletRequest req, HttpServletResponse res) { 
     ......
    //Attach a listener
     req.addAsyncListener(new MyAsyncListene())
    //setting time-out and obtain AsysncContext
     req.setAsyncTimeout(10000);
     AsyncContext aCtx = req.startAsync(req, res);
    //execute async thread
    AsyncContext.start(new AsyncWebService(aCtx,myWebServiceService));


   }
}

public class AsyncProcess implements Runnable {
  AsyncContext ctx;
  public AsyncProcess (AsyncContext ctx, Service service){ this.ctx = ctx; myWebServiceService=service;}
   public void run() {
      // Do something ....
      // Invoke web service (like now) or connect to a DB or use JMS
      MyWebService myWebService = myWebServiceService.getPort();
      myWebService.sayHallo();
      // the response will be render another servlet
      ctx.forward("/secondservlet");
      ctx.complete();
  }
}
public class MyAsyncListener implements AsyncListener{
  public void onComplete(AsyncEvent event){
    System.out.println("Async Process complete!!");
  }

  public void onTimeout(AsyncEvent event){
    System.out.println("Timeout!!!!");
  }
}
……… posted by Davide Pisano

Comments:

Io di solito non faccio post nel Blog, ma il tuo post sito lavoro mi ha costretto a, il lavoro incredibile .. bella ...

Posted by Titus Lindig on June 09, 2010 at 10:26 PM CEST #

Awesome post. Just found it on Google. Thank you 4 the useful info. Keep up the good work :)

Posted by Jenae Boitnott on June 19, 2010 at 07:40 PM CEST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

.. useful blog on java and middleware technologies.

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today