Servlets Faqs-->1
For
Java Web Server:
- on the file system, it's "servlets"
c:\JavaWebServer1.1\servlets\DateServlet.class
- in a URL path,
it's "servlet"
http://www.stinky.com/servlet/DateServlet
2)
How do I support both GET and POST protocol from the same Servlet?
The
easy way is, just support POST, then have your doGet method call your doPost
method:
public void doGet(HttpServletRequest
req, HttpServletResponse res)
throws ServletException, IOException
{
doPost(req, res);
}
3)
How do I ensure that my servlet is thread-safe?
This
is actually a very complex issue. A few guidelines:
- The init()
method is guaranteed to be called once per servlet instance, when the servlet is loaded. You
don't have to worry about thread safety inside this method, since it is
only called by a single thread, and the web server will wait until that
thread exits before sending any more threads into your service() method.
- Every new client
request generates (or allocates) a new thread; that thread calls the
service() method of your servlet (which may in turn call doPost(), doGet()
and so forth).
- Under most
circumstances, there is only one instance of your servlet, no matter how
many client requests are in process. That means that at any given moment,
there may be many threads running inside the service() method of your solo
instance, all sharing the same instance data and potentially stepping on
each other's toes. This means that you should be careful to synchronize access to
shared data (instance variables) using the synchronized keyword. (Note
that the server will also allocate a new instance if you register the servlet with a new name and,
e.g., new init parameters.)
- Note that you
need not (and should not) synchronize on local data or parameters. And
especially you shouldn't synchronize the service() method! (Or doPost(),
doGet() et al.)
- A simple
solution to synchronizing is to always synchronize on the servlet instance
itself using "synchronized (this) { ... }". However,
this can lead to performance bottlenecks; you're usually better off
synchronizing on the data objects themselves.
- If you
absolutely can't deal with synchronizing, you can declare that your
servlet "implements SingleThreadModel". This empty
interface tells the web server to only send one client request at a time
into your servlet. From the JavaDoc: "If the target servlet is
flagged with this interface, the servlet programmer is guaranteed that no
two threads will execute concurrently the service method of that servlet.
This guarantee is ensured by maintaining a pool of servlet instances for
each such servlet, and dispatching each service call to a free servlet. In
essence, if the servlet implements this interface, the servlet will be
thread safe." Note that this is not an ideal solution, since
performance may suffer (depending on the size of the instance pool), plus
it's more difficult to share data across instances than within a single
instance.
See also What's a better approach for enabling thread-safe
servlets and JSPs? SingleThreadModel Interface or Synchronization?
- To share data
across successive or concurrent requests, you can use either instance
variables or class-static variables, or use Session Tracking.
- The destroy()
method is not necessarily as clean as the init() method. The server calls
destroy either after all service calls have been completed, or
after a certain number of seconds have passed, whichever comes first. This
means that other threads might be running service requests at the same
time as your destroy() method is called! So be sure to synchronize, and/or
wait for the other requests to quit. Sun's Servlet Tutorial has an example
of how to do this with reference counting.
- destroy() can
not throw an exception, so if something bad happens, call log() with a
helpful message (like the exception). See the "closing a JDBC
connection" example in Sun's Tutorial.
4)
What is the difference between URL encoding, URL rewriting, HTML escaping, and
entity encoding?
URL
Encoding
is a process of transforming user input to a CGI form so it is fit for travel
across the network -- basically, stripping spaces and punctuation and replacing
with escape characters. URL Decoding is the reverse process. To perform these
operations, call java.net.URLEncoder.encode() and java.net.URLDecoder.decode()
(the latter was (finally!) added to JDK 1.2, aka Java 2).
Example: changing "We're
#1!" into "We%27re+%231%21"
URL
Rewriting
is a technique for saving state information on the user's browser between page
hits. It's sort of like cookies, only the information gets stored inside the
URL, as an additional parameter. The HttpSession API, which is part of the
Servlet API, sometimes uses URL Rewriting when cookies are unavailable.
Example: changing <A
HREF="nextpage.html"> into
<A
HREF="nextpage.html;$sessionid$=DSJFSDKFSLDFEEKOE"> (or whatever
the actual syntax is; I forget offhand) (Unfortunately, the method in the
Servlet API for doing URL rewriting for session management is called
encodeURL(). Sigh...)
There's
also a feature of the Apache web server called URL Rewriting; it is enabled by
the mod_rewrite module. It rewrites URLs on their way in to the server,
allowing you to do things like automatically add a trailing slash to a
directory name, or to map old file names to new file names. This has nothing to
do with servlets. For more information, see the Apache FAQ
(http://www.apache.org/docs/misc/FAQ.html#rewrite-more-config) .
5)
How do I upload a file to my servlet or JSP?
On
the client side, the client's browser must support form-based upload. Most
modern browsers do, but there's no guarantee. For example,
<FORM
ENCTYPE='multipart/form-data'
method='POST' action='/myservlet'>
<INPUT TYPE='file' NAME='mptest'>
<INPUT TYPE='submit' VALUE='upload'>
</FORM>
The
input type "file" brings up a button for a file select box on
the browser together with a text field that takes the file name once selected.
The servlet can use the GET method parameters to decide what to do with the
upload while the POST body of the request contains the file data to parse.
When
the user clicks the "Upload" button, the client browser locates the
local file and sends it using HTTP POST, encoded using the MIME-type
multipart/form-data. When it reaches your servlet, your servlet must process
the POST data in order to extract the encoded file. You can learn all about
this format in RFC 1867.
Unfortunately,
there is no method in the Servlet API to do this. Fortunately, there are a
number of libraries available that do. Some of these assume that you will be writing the file to disk; others return the
data as an InputStream.
- Jason Hunter's MultipartRequest (available from
http://www.servlets.com/)
- Apache Jakarta
Commons Upload (package
org.apache.commons.upload) "makes it easy to add robust,
high-performance, file upload capability to
your servlets and web applications"
- CParseRFC1867
(available from http://www.servletcentral.com/).
- HttpMultiPartParser by Anil
Hemrajani, at the isavvix Code Exchange
- There is a
multipart/form parser availailable from Anders Kristensen (http://www-uk.hpl.hp.com/people/ak/java/, ak@hplb.hpl.hp.com) at http://www-uk.hpl.hp.com/people/ak/java/#utils.
- JavaMail also
has MIME-parsing routines (see the Purple Servlet
References).
- Jun Inamori has
written a class called org.apache.tomcat.request.ParseMime which is
available in the Tomcat CVS tree.
- JSPSmart has a free set
of JSP for doing file upload and download.
- UploadBean by JavaZoom
claims to handle most of the hassle of uploading for you, including
writing to disk or memory.
- There's an
Upload Tag in dotJ
Once
you process the form-data stream into the uploaded file, you can then either
write it to disk, write it to a database, or process it as an InputStream,
depending on your needs. See How can I access or create a file or folder in the current
directory from inside a servlet? and other questions in the Servlets:Files Topic for information on writing files from a Servlet.
Please
note
that you can't access a file on the client system directly from a servlet; that
would be a huge security hole. You have to ask the user for permission, and
currently form-based upload is the only way to do that.
6)
How does a servlet communicate with a JSP page?
The
following code snippet shows how a servlet instantiates a bean and initializes
it with FORM data posted by a browser. The bean is then placed into the
request, and the call is then forwarded to
the JSP page, Bean1.jsp, by means of a request dispatcher for downstream
processing.
public void doPost (HttpServletRequest
request,
HttpServletResponse
response) {
try {
govi.FormBean f = new govi.FormBean();
String id = request.getParameter("id");
f.setName(request.getParameter("name"));
f.setAddr(request.getParameter("addr"));
f.setAge(request.getParameter("age"));
//use the id to compute
//additional bean properties
like info
//maybe perform a db query, etc.
// . . .
f.setPersonalizationInfo(info);
request.setAttribute("fBean",f);
getServletConfig().getServletContext().getRequestDispatcher
("/jsp/Bean1.jsp").forward(request,
response);
} catch (Exception ex) {
. . .
}
}
The
JSP page Bean1.jsp can then process fBean, after first extracting it from the
default request scope via the useBean action.
<jsp:useBean id="fBean"
class="govi.FormBean" scope="request"/>
<jsp:getProperty
name="fBean" property="name" />
<jsp:getProperty
name="fBean" property="addr" />
<jsp:getProperty
name="fBean" property="age" />
<jsp:getProperty
name="fBean" property="personalizationInfo" />
7)
What's a better approach for enabling thread-safe servlets and JSPs?
SingleThreadModel Interface or Synchronization?
Although
the SingleThreadModel technique is easy to use, and works well for low volume
sites, it does not scale well. If you anticipate your users to increase in the
future, you may be better off implementing explicit synchronization for your
shared data. The key however, is to effectively minimize the amount of code
that is synchronzied so that you take maximum advantage of multithreading.
Also,
note that SingleThreadModel is pretty resource intensive from the server's
perspective. The most serious issue however is when the number of concurrent
requests exhaust the servlet instance pool. In that case, all the unserviced
requests are queued until something becomes free - which results in poor
performance. Since the usage is non-deterministic, it may not help much even if
you did add more memory and increased the size of the instance pool.
8)
Can a servlet maintain a JTA UserTransaction object across multiple servlet
invocations?
No.
A JTA transaction must start and finish within a single invocation (of the
service() method). Note that this question does not address servlets that
maintain and manipulate JDBC connections, including a connection's transaction
handling.
9)
How does the performance of JSP pages compare with that of servlets? How does
it compare with Perl scripts?
The
performance of JSP pages is very close to that of servlets. However, users may
experience a perceptible delay when a JSP page is accessed for the very first
time. This is because the JSP page undergoes a "translation phase"
wherein it is converted into a servlet by the JSP engine. Once this servlet is
dynamically compiled and loaded into memory, it follows the servlet life cycle
for request processing. Here, the jspInit() method is automatically invoked by
the JSP engine upon loading the servlet, followed by the _jspService() method,
which is responsible for request processing and replying to the client. Do note
that the lifetime of this servlet is non-deterministic - it may be removed from
memory at any time by the JSP engine for resource-related reasons. When this
happens, the JSP engine automatically invokes the jspDestroy() method allowing
the servlet to free any previously allocated resources.
Subsequent
client requests to the JSP page do not result in a repeat of the translation
phase as long as the servlet is cached in memory, and are directly handled by
the servlet's service() method in a concurrent fashion (i.e. the service()
method handles each client request within a seperate thread concurrently.)
There
have been some recent studies contrasting the performance of servlets with Perl
scripts running in a "real-life" environment. The results are
favorable to servlets, especially when they are running in a clustered
environment.
10)
How do I call one servlet from another servlet?
[
Short answer: there are several ways to do this, including
- use a
RequestDispatcher
- use a
URLConnection or HTTPClient
- send a redirect
- call
getServletContext().getServlet(name) (deprecated, doesn't work in 2.1+)
-
Alex ]
It
depends on what you mean by "call" and what it is you seek to do and
why you seek to do it.
If
the end result needed is to invoke the methods then the simplest mechanism
would be to treat the servlet like any java object , create an instance and
call the mehods.
If
the idea is to call the service method from the service method of another
servlet, AKA forwarding the request, you could use the RequestDispatcher
object.
If,
however, you want to gain access to the instance of the servlet that has been
loaded into memory by the servlet engine, you have to know the alias of the
servlet. (How it is defined depends on the engine.) For example, to invoke a
servlet in JSDK a servlet can be named by the property
myname.code=com.sameer.servlets.MyServlet
The
code below shows how this named servlet can be accessed in the service method
of another servlet
public void service (HttpServletRequest
request, HttpServletResponse response)
throws ServletException, IOException {
...
MyServlet ms=(MyServlet) getServletConfig().getServletContext().getServlet("myname");
...
}
That
said, This whole apporach of accessing servlets in another servlets has been
deprecated in the 2.1 version of the servlet API due to the security issues.
The cleaner and better apporach is to just avoid accessing other servlets
directly and use the RequestDispatcher instead.
0 comments:
Post a Comment