• Aucun résultat trouvé

The page Directive

Dans le document Beginning JSP, JSF and Tomcat (Page 59-62)

The page directive defines several page-dependent properties expressed through attributes. These properties should appear only once in a JSP page (unless the multiple instances all have the same value, but why should you do that?). You can write more than one page directive in a JSP page, and they will all apply. Their order or position within the page is generally irrelevant.

This directive is used in all JSP pages. Typically, a JSP page starts with a page directive to tell Tomcat that the scripting language is Java and that the output is to be HTML:

<%@page language="java" contentType="text/html"%>

This is almost always followed by one or more further page directives to tell Tomcat which external class definitions your code needs. For example:

<%@page import="java.util.ArrayList"%>

<%@page import="java.util.Iterator"%>

<%@page import="myBeans.OneOfMyBeans"%>

It is not good coding practice to import whole class libraries, as in

<%@page import="java.util.*"%>

because any relaxation of control, sooner or later, creates problems. In any case, as you can see in the following example, you don’t need to write a separate directive for each class you need to include:

<%@page import="java.util.ArrayList, java.util.Iterator"%>

In addition to language, contentType, and import, the page directive also supports autoFlush, buffer, errorPage, extends, info, isELIgnored, isErrorPage, isScriptingEnabled, isThreadSafe, pageEncoding, session, and trimDirectiveWhitespaces.

Listing 2-14 shows you a simple program that utilizes the isThreadSafe attribute to test concurrency.

Listing 2-14. concurrency.jsp

The program declares the instance variable k, copies it to the variable j, increments j, waits for five seconds, and copies the incremented j back to k. It also displays k at the beginning and at the end.

If you reload the page several times, you’ll see that k is increased every time the page refreshes. Now view the page in another browser (not just another browser window, because caching plays funny tricks); for example, view it in Chrome if you normally use Firefox. If you keep reloading the page in the two browsers, you’ll see the k keeps increasing regardless of which browser you’re looking at. This is because k is an instance variable.

Now reload the page in the first browser and then immediately in the second browser. Do you notice how the second browser takes longer to refresh? This is because you’ve set isThreadSafe="false", and Tomcat doesn’t execute the servlet code for the two requests at the same time. However, k keeps increasing across the browsers with each page refresh.

Now remove the page directive that sets isThreadSafe to false and repeat the test. When you reload the page on both browsers almost simultaneously, they refresh the page at the same time but with the same value of k! This is because the second execution of the servlet starts while the first one is “holding”

for five seconds.

I introduced the five-second delay to be sure that you would see the problem. Without the delay, the time interval between incrementing j and saving it back to k would be vanishingly small. Therefore, you might keep trying for years and never see the problem. Nevertheless, to rely on “it will never happen”

when developing code, especially when concurrency plays a role, is a very bad practice. Other factors might influence the timing, and suddenly you might start seeing a problem once a day or even more rarely. It could have a damaging effect on how users consider your web site.

The price paid for playing it safe with isThreadSafe is that it can slow down execution significantly.

Fortunately, there’s a better way to make the threads safe than relying on Tomcat. Look at Listing 2-15.

Listing 2-15. concurrency2.jsp

You protect the critical part of the code by enclosing it in a synchronized block. The syncK variable, being defined in a declaration element, is an instance variable shared like k among all the requests. I haven’t used k because synchronized requires an object. In this simple case, instead of creating a new object specifically to protect the code, I could have used this, representing the servlet itself. But in general, if there were more than one block of code to protect, it wouldn’t be a good idea. The best strategy to maximize efficiency, besides staying locked as little as possible, is to use specific locks.

I spent a bit of time on the attribute isThreadSafe because concurrency often is not well understood or implemented and causes intermittent bugs that are devilish to eliminate.

Earlier in this chapter, you have already seen how to use errorPage and isErrorPage (in “The Exception Object”), and trimDirectiveWhitespaces, autoFlush, and buffer (in “The Out Object”). Here is a brief description of the remaining attributes of the page directive:

• extends tells Tomcat which class the servlet should extend.

• info defines a string that the servlet can access with its getServletInfo() method.

• isELIgnored tells Tomcat whether to ignore EL expressions.

• isScriptingEnabled tells Tomcat whether to ignore scripting elements.

• pageEncoding specifies the character set used in the JSP page itself.

• session tells Tomcat to include or exclude the page from HTTP sessions.

The bottom line is that, in most occasions, you can leave these additional attribute set to their default values.

Dans le document Beginning JSP, JSF and Tomcat (Page 59-62)