Showing posts with label Java Servlets. Show all posts
Showing posts with label Java Servlets. Show all posts

Friday, October 1, 2010

Programmatic instantiation of Components like servlets, filters, and listeners

With programmatic definition, we can instantiate components programmatically and then configure them. Servlet 3.0 Specification supports dynamic instantiation of servlets and filters.

In this example, we will see how you might programmatically instantiate servlets, filters, and listeners.

@WebListener
public class MyServletContextListener implements ServletContextListener {

public void contextInitialized(ServletContextEvent sce) {
LOG.info("Context Listener Initialized");
doProgrammaticRegistration(sce.getServletContext());
}

private void doProgrammaticRegistration(ServletContext sc) {

// servlet definition
ServletRegistration.Dynamic dynaServlet = sc.addServlet(
"MyProgrammaticServlet",
"com.servlets.MyProgrammaticServlet");
dynaServlet.addMapping("/myprogrammaticservlet");

// filter definition
FilterRegistration.Dynamic dynaFilter = sc.addFilter(
"MyProgrammaticFilter",
"com.filters.MyProgrammaticFilter");
EnumSet dispatcherType = EnumSet.of(
DispatcherType.REQUEST, DispatcherType.FORWARD);
dynaFilter.addMappingForServletNames(dispatcherType, true,
"MyProgrammaticServlet");
}
}

As shown, during context initialization, we instantiate a new servlet and returned class ServletRegistration.Dynamic instance is used to configure the appropriate servlet mapping. We do the similar steps with a filter. These steps are similar to what would have happened when a servlet container encountered the <servlet>, <servlet-mapping>, <filter> and <filter-mapping> elements in a web deployment descriptor.

As it can be seen in the next code listings, the servlet and filter are rather straightforward. Since the configuration occurs programmatically, they do not even need any annotations to be used.

//Note: not even an annotation is required
public class MyProgrammaticFilter implements Filter {
private final Logger LOG = Logger.getLogger("MyProgrammaticFilter");

public void destroy() { }

public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws ServletException, IOException {

LOG.info("Filtering: " + ((HttpServletRequest)req).getRequestURI());
chain.doFilter(req, resp);
}

public void init(FilterConfig config) throws ServletException {
LOG.info("Filter: " + "Initializing ProgrammaticFilter");
}
}

//Note: not even an annotation is required.
public class MyProgrammaticServlet extends HttpServlet {
private final Logger LOG = Logger.getLogger("MyProgrammaticServlet");

protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}

protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
LOG.info("Within request : " + getServletName());
String html = "Added programmatically (no annotation/web.xml entries): " + new Date();

response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println(html);
}
}

Hope this will help.

Servlet 3.0 Annotations

Servlet 3.0 Specification has a number of new features and one of them is annotation. When an application loads, all classes into the application are examined for presence of the annotations. When these annotations are found on a particular class, the container registers instances of the classes as Listeners, Servlets, or Filters based on the annotation.
Servlet 3.0 Specification Annotations are as follows.

* @WebServlet
* @WebFilter
* @WebInitParam
* @WebListner
* @MultipartConfig

@WebServlet
This annotation is used to define a Servlet component in a web application and defines the metadata about the servlet being declared.
Classes annotated with @WebServlet annotation must extend javax.servlet.http.HttpServlet class.
@WebServlet annotation annotation has the following attributes.
* name
* description
* value
* urlPatterns
* initParams
* loadOnStartup
* asyncSupported
* smallIcon
* largeIcon
Note: the spec mandates either value or urlPatterns attribute be specififed.

Example:
@WebServlet(name = "myservlet", urlPatterns = { "/myservlet" })
public class MyServletExample extends HttpServlet {
}

@WebFilter
This annotation is used to define a filter in web application. The classes annotated with @WebFilter annotation must implement javax.servlet.Filter interface.
The @WebFilter annotation has the following attributes
* filterName
* description
* displayName
* initParams
* servletNames
* value
* urlPatterns
* dispatcherTypes
* asyncSupported

Example:
@WebFilter(filterName="samplefilter", urlPatterns={"/foo/*", "/bar"})
public class MyServletSampleFilter implements Filter {
}

@WebInitParam
This annotation is used to specify any init parameters that must be passed to the Servlet or the Filter.
The annotation defines the following attributes:
* name
* value
* description

Example:
@WebServlet(value="/hello",
initParams = {
@WebInitParam(name="name1", value="Hello "),
@WebInitParam(name="name2", value=" World!")
})
public class MyHelloServletExample extends HttpServlet {
}

@WebListner
This annotation is used to define a listener. The @WebListener annotation is used to register the following types of listeners
1. Context Listener (javax.servlet.ServletContextListener)
2. Context Attribute Listener (javax.servlet.ServletContextAttributeListener)
3. Servlet Request Listener (javax.servlet.ServletRequestListener)
4. Servlet Request Attribute Listener (javax.servlet.ServletRequestAttributeListener)
5. Http Session Listener (javax.servlet.http.HttpSessionListener)
6. Http Session Attribute Listener (javax.servlet.http.HttpSessionAttributeListener)

@WebListener is the easiest to use. Registering ServletContextListener.

Example:
@WebListener()
public class MySampleContextListner extends ServletContextListner {
public void contextInitialized(ServletContextEvent event) {
//do some thing on application init
}

public void contextDestroyed(ServletContextEvent event) {
//do some thing on application destroy
}
}

@MultipartConfig
Servlet 3.0 specification comes with the built in file upload support. 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 makes available the mime attachments via the getParts and getPart methods to iterate over the various mime attachments.

The @MultipartConfig annotation can be used to specify the location where the files can be stored, maximum size of the file being uploaded, maximum request size and the size threshold after which the file will be written to the disk. There is any equivalent element in web.xml that can be used for the same purpose.

@MultipartConfig annotation declares the following attributes:
* location
* maxFileSize
* maxRequestSize
* fileSizeThreshold

Example:
@WebServlet(name="UploadServlet", urlPatterns={"/upload"})
@MultipartConfig(location="d://tmp")
public class MyServletExample extends HttpServlet {
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//target directory and location are the same.
req.getPart("content").write("file.txt");
}
}

Hope this will help.

Thursday, September 30, 2010

Servlet 3.0 Uploading files

The Internet is becoming more and more about sharing data and uploading files had become nearly universal requirement for a web application. Prior to Servlet 3.0, implementing file upload successfully required external libraries or tedious input processing.

Servlet 3.0 introduces a new API to handle multipart/form-data submissions. Multipart/form-data is a content type used to submit files, non-ASCII and binary data. Here is an example of file upload servlet.

fileupload.jsp: The browser will submit data using multipart/form-data encoding when an HTML form specifies it as a value for its enctype attribute.
<form action="/file-upload" enctype="multipart/form-data" method="POST">
Submitter: <input name="submitter" type="text">
Upload File: <input name="content" type="file">
<input value="Submit" type="submit">
</form>

When submitting a form, the browser will stream the content in, all parts combined, with each part representing a field of a form. Parts are named after the input elements and separated from each other with string delimiters named boundary.

What submitted header data would look like as follows:

POST /file-upload HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------------8723974127529 Content-Length: 1231

-----------------------------8723974127529 Content-Disposition: form-data; name="submitter"

pulak -----------------------------8723974127529

Content-Disposition: form-data; name="content"; filename="bloggerpoc.txt" Content-Type: application/octet-stream

<<Some data to be uploaded>>

The new Servlet 3.0 API specifies an interface javax.servlet.http.Part for each submission part and javax.servlet.http.HttpServletRequest makes them accessible using two methods:

* getParts()
* getPart(String name)

Since parts are named, method getPart(String name) can be used to access a particular part. Alternatively, method getParts() which returns an Iterable can be used to get an Iterator over all the parts. javax.servlet.http.Part is a really simple interface which provides methods allowing to introspect each part and get its name, size, content-type, query the headers submitted with a part, delete or write part out to a disk.

fileupload servlet: A simple servlet that accepts and saves a file can be as following:

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

@WebServlet(name="UploadServlet", urlPatterns={"/file-upload"})
@MultipartConfig(location = "D://tmp")
public class MyServlet extends HttpServlet {
public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//get the "content" part and save it.
Part part = request.getPart("content");
part.write("file2.txt");
}
}

The Servlet 3.0 Specification introduces a new @javax.servlet.annotation.MultipartConfig annotation that helps the container identify a Servlet as capable of handling multipart/form-data requests. When this annotation is present on a Servlet, the HttpServletRequest makes the parts available.

The annotation can be used to configure location where the container should store temporary files, legal size limits on the entire request and parts, and a threshold size that triggers use of permanent storage.

@MultipartConfig annotation declares the following attributes
* location
* maxFileSize
* maxRequestSize
* fileSizeThreshold

Hope this will help.
I will cover more interesting Servlet 3.0 feature like support for Asynchronous communication next.

Introduction to servlet 3.0 new features

Servlet API is the building block of the Java Web Applications. Almost all the java web application frameworks build on top of the Java Servlet API. Servlet 3.0 is JSR 315 JavaTM Specification. The Servlet API 3.0 Sspecification has come up with many new and exciting features as follows.

1. Programmatic instantiation of Servlets/Filters/listeners
2. Ease of Development through Annotations
3. File upload
4. Modularization of web.xml
5. Asynchronous Servlets and comet support.
6. Pluggable Web framework

1. Programmatic instantiation Filters, servlets, listeners
Servlet 3.0 specification has additional methods to the ServletContext to register dynamically Web components like Servlets or Filters or even Roles.

2. Ease of Development through Annotations
The servlet 3.0, web.xml deployment descriptor is totally optional. Servlet 3.0 specification has made this thing easier through annotations and providing the way to programmatic defination of Filters, servlet, listeners and URL patterns. Deployment descriptor can be used to override the configuration.

For example, you can define a servlet using @WebServlet annotation and put into WEB-INF/classes directory or application's WEB-INF/lib directory. The servlet does not need to be defined into web.xml, at run time container will process classes in WEB-INF/classes and lib directory and identify it based on the annotation.

Note: Classes using annotation will have their annotation processed on if they are located in WEB-INF/classes directory or if they are packaged in a jar file located in WEB-INF/lib directory.

3. File upload support
Servlet API, previously did not provide any built in support for handling file upload. We used various open source/third party libraries like Commons file upload and other APIs. However supporting file upload is so common requirement for any web application that Servlet 3.0 Specification supports it out of the box. Web container itself can parse the multipart request and make mime attachments available through HttpServletRequest object.

Two new methods have been introduced to HttpServletRequest interface are
public Collection getParts()
public Part getPart(String name)

Each part provides access to the headers, content type related with it and also the content via the getInputStream method.

The HTML form must specify multipart/form-data as encoding type and Servlet should be either annotated with @MultiPartConfig or configured with element in deployment descriptor.

4. Modularization of web.xml
The annotations make the web.xml deployment descriptor optional, However web.xml can be used to override the configuration values defined by the annotations. Currently before Servlet 3.0 specification web.xml is a big fat file with all the configuration for entire application. However Servlet 3.0 introduces notion of deployment descriptor fragments. The web.xml can be divided into parts called fragments and bundled in jar file. The fragments must be located into META-INF directory of the jar file.

A web fragment is a logical partitioning of the web application in such a way that the frameworks being used within the web application can define all the artifacts without asking developers to edit or add information in the web.xml. It can include almost all the same elements that the web.xml descriptor does include. However the top level element for the descriptor MUST be web-fragment and the corresponding descriptor file MUST be called web-fragment.xml

5. Asynchronous Servlets and comet support
Servlet 3.0 makes developing Comet applications very easier. Sometime comet is referred as reverse Ajax also.
Servlet 3.0 added new methods into HttpServletRequest class to support the asynchronous request processing and response generation.

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

This method puts the request into asynchronous mode and initializes it’s AsyncContext with the given request and response objects.

6.
Pluggable Web Framework support
Almost all the java web application frameworks build on top of the Servlet API. Examples are Spring MVC, Struts, Struts 2, JSF, Webwork, Stripes and the like. In order to hook this frameworks into your web application, you declare a filter or a servlet into your web application deployment descriptor and map URL patterns to that servlet/filter in addition to including it as a dependency in the WEB-INF/lib directory. There was no way that you can just put the jar file into web application lib directory and ready to go with the framework.

For example, when using Spring MVC, you have to declare DispatcherServlet in web.xml and map URLs to it, you cannot just put the Spring MVC jar into lib directory and start using it. Today in a servlet container the application has one monolithic web.xml that defines all the deployment artifacts for the application, including the dependencies of the application on the framework components.

To overcome this issue in Servlet 3.0 Specification, A framework can define it's own deployment descriptor that declares the necessary components for the framework that is then included for use in the web applicaton. At deployment the container is responsible for discovering the web.xml fragments and processing them. A new element is being added to the descriptor schema for web applications - web-fragment that can define servlets, filters and listeners. The above fragment would be included in the META-INF directory of the framework jar file. However the top level element for the descriptor MUST be web-fragment and the corresponding descriptor file MUST be called web-fragment.xml.

Hope this will help.

Tuesday, September 21, 2010

Why SingleThread model is deprecated in Servlets?

SingleThreadModel ensures that servlets handle only one request at a time. This interface has no methods. In Servlet 2.4 SingleThreadModel is deprecated for a good reason mostly because it does not really provide thread safety.

Note that SingleThreadModel does not solve all thread safety issues. For example, session attributes and static variables can still be accessed by multiple requests on multiple threads at the same time, even when SingleThreadModel servlets are used. Also it is really very expensive to creating one instance for each request is time consuming and difficult.


Alternative to SingleThreadModel:
It is recommended that a developer take other means to resolve those issues instead of implementing this interface, such as avoiding the usage of an instance variable or synchronizing the block of the code accessing those resources.