|
1) Is it the "servlets" directory or the
"servlet" directory?
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:
1.
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.
2.
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).
3.
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.)
4.
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.)
5.
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.
6.
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?
7.
To share data across
successive or concurrent requests, you can use either instance variables or
class-static variables, or use
Session
Tracking.
8.
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.
9.
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
&quot;file&quot; 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.
java6 ejb3 jsf hibernate eclipse ajax groovy spring seam java struts webservice j2me guice java5 jca tapestry soa linux ria books
|