chapter 5 being a web app. very few servlet or jsp stands alone many times in our application,...
TRANSCRIPT
Chapter 5 Being a Web App
Very few servlet or JSP stands alone
Many times in our application, different servlets or JSPs need to share information For example, you entered your name and credit
card info in one page and this info is displayed (shared) in another page, e.g. , order confirmation page
Your application may also want to hide information
Your application also needs to be thread-safe
Make your servlet configurable
Think about an example web application where you want to put your email address in a servletInstead of hard code your email in the servlet, it
is better to make it configurable
Init parameters to the rescue
You cannot use servlet init parameters until the servlet is initialized
Your servlet inherits getServletConfig() automajtically, so you can call that from any method in your servlet to get a reference to a ServletConfigOnce you have a ServletConfig reference, you
can call getInitParameter()Remember you cannot call it from your constructor
You cannot use servlet init parameters until the servlet is initialized
When the container initializes a servlet, it makes a unique ServletConfig for the servlet
The container “reads” the servlet init parameters from the DD and gives them to the ServletConfig, the passes the ServletConfig to the servlet’s init() method
The servlet init parameters are read only ONCE
When the Container makes a servlet, it reads the DD and creates the name/value pairs for the ServletConfig
Once the parameters are in the ServletConfig, they won’t be read again until/unless you redeploy the servlet
How can a JSP get servlet init parameters
A ServletConfig is for servlet configuration (it doesn’t say JSPConfig)
How to pass the init parameters for a servlet to a JSP?The request object lets you set attributes (think
of them as a name/value pair where the value can be any object) that any other servlet or JSP that gets the request can useThat means any servlet or JSP to which the request
is forwarded using a RequestDispatcher
• Setting a request attribute works… but only for the JSP to which you forward the request
How about I want some configurable info to be shared by all servlets and JSPs in my web application?
You can use context init parametersIt work just like servlet init parameters, except
context parameters are available to the entire webapp, not just a single servlet
Context init parameters
Context init parameters
ServletConfig & ServletContext
ServletConfig is one per servletServletContext is one per web appThe container makes a ServletContext
when a web app is deployed, and makes the context available to each Servlet and JSP (which becomes a servlet) in the web app
ServletConfig & ServletContext
Question
Why would I ever use <init-param> anyway? Wouldn’t I always want to use <context-param> so that other parts of my application could reuse the values and I won’t have to duplicate XML code for every servlet declaration?
Answer: It all depends on which part of your app is supposed to see the value
What else can you do with your ServletContext?
Listener
What if you want an app init parameter that is a database DataSource?You can certainly put the DataSource lookup
name in a context init parameter, and that is probably the most common use of context parameter today
But then who does the work of turning the String parameter into an actual DataSource reference that all parts of the web app can share?
Listener (Cont.)
You cannot really put that code in a servlet, because you cannot guarantee one servlet in particular will always run first
You need to listen for a context initialization event, so that you can get the context init parameters and run some code before the rest of the app can service a client
ServletContextListener can help It is not servlet or JSP
What can listener do?
Example listener
Deploy the listener
You need to create the listener class and put the class in WEB-INF/classes
You also need to put a <listener> element in the web.xml Deployment Descriptor
An listener example
public void contextInitialized (ServletContextEvent event){
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
} catch (Exception ex) {
System.out.println("*****Error loading the driver*******");
}
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost/j2ee?user=root&password=");
ServletContext sc = event.getServletContext();
sc.setAttribute("dbconnection1", conn);
System.out.println("*******set dbconnection attribute *******");
} catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
}
An listener example
public void contextDestroyed (ServletContextEvent event){
try{
conn.close();
conn = null;
}catch (SQLException ex) {
// handle any errors
System.out.println("SQLException: " + ex.getMessage());
System.out.println("SQLState: " + ex.getSQLState());
System.out.println("VendorError: " + ex.getErrorCode());
}
}
web.xml for the listener
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<listener>
<listener-class>
edu.nku.j2ee.MysqlContextListener
</listener-class>
</listener>
</web-app>
What is an attribute?
You can think of it as simply a name/value pair (where the name is a String and the value is an Object) in a map instance variable
In reality, we really care about the scope in which the attribute exists.In other words, who can see it and how long
does it live.
Attributes
Three scopes: Context Request Session
Attributes are not parameters
Context attributes
Session attributes
Request attributes
Attribute API
The three attribute scopes – context, request, and session – are handled by the ServletContext, ServletRequest, HttpSession interfaces
The API methods for attributes are exactly the same in every interface
The dark side of attributes...
Kim decides to test out attributes. He sets attribute and then immediately gets the value of the attribute
Here is what he sees the first time he runs it
But then something goes horribly wrong
Kim put this code in a test servlet that is part of a larger test web app. In other words, the servlet that holds this doGet() method was deployed as part of a larger app.Can you figure out what happened? How to fix it?
Context scope is not thread-safe
Remember everyone in the app has access to context attributesSince requests are concurrently handled in
separate threads, You may have multiple servlets (mean you might
have multiple threads) accessing the context attributes concurrently
You may have multiple threads from one servlet accessing the context attributes concurrently
Either of the above two cases can cause problems
context attributes’ thread-safe issue
Can we synchronize doGet() method to make it thread safe?
context attributes’ thread-safe issue
No. Synchronize doGet() will not only kiss your
concurrency goodbye, but also does not protect context attributes at allSynchronizing the service method would stop other
threads from the same servlet from accessing the context attributes, but it won’t do anything to stop a completely different servlet
context attributes’ thread-safe issue
By the way, the figure in Page 192 and 196 of our book has a little bit of problem…It draws two instance of servlet A, it is a little
confusingBy default, one instances of a servlet is responsible
for taking care of multiple requests coming in to the same servlet
If you look at figure at P101 of the book, you will be very clear
context attributes’ thread-safe issue
You don’t need a lock on the servlet… you need the lock on the context
If everyone accessing the context has to first get the lock on the context object, then you’re guaranteed that only one thread at a time can be getting or setting the context attributeIt only works if all of the other code that manipulates
the same context attributes ALSO synchronize on the ServletContext
If code doesn’t ask for the lock, then that code is still free to hit the context attribute
The right way to synchronize context attribute’s multiple concurrent access
Are session attributes thread-safe?
We have not talked about HTTP sessions in detail yet, but you already know that a session is an object used to maintain conversational state with a client
The session persists across multiple requests from the same client
And if it’s one client, and a single client can be in only one request at a time, doesn’t that automatically mean that session are thread-safe?
Are session attributes thread-safe?
No.The client could open a new browser window
(from the same browser)
The container can see the request from the second window (of the same browser) as coming from the same session
Correct way to synchronize accessing to session attributes
You can protect session attributes by synchronizing on the HttpSession object
Question
Isn’t it a bad idea to synchronize code, because it causes a lot of overhead and hurts concurrency?
Answer: You should always think carefully before synchronizing any code, because you’re right-it does add some expense in checking, acquiring, and releasing locks. If you need protection, then use synchronization but remember the standard rule of all forms of locking-keep the lock for the shortest amount of time to accomplish your goal!
Request attributes and local variables
Only request attributes and local variables are thread-safe
Everything else is subject to manipulation by multiple threads, unless you do something to stop it
Request attributes and request dispatching
Request attributes make sense when you want some other component of the app to take over all or part of the requestThe component that take over the request will be able
to access the request attributes
Our typical simple example is an MVC app that starts with a servlet controller, but ends with a JSP view
We can make another part of the component take over the request with a RequstDispatcher
Request attributes and request dispatching