Tutorial Downloads |
Welcome to the NetBeans IDE 6.0 tutorial for web applications. In this tutorial, you build a fairly complex web application while being introduced to a number of tools and technologies in NetBeans IDE, as well as a typical web development cycle, from creation to deployment. Beginning with the creating of servlets and JSP pages, the advanced sections of this tutorial show you how to use the JavaServer Pages Standard Tag Library (JSTL) to fetch dynamic data and to internationalize the JSP pages used in this application. You end the tutorial with an introduction to the IDE's HTTP Monitor, which helps you analyze a web application while it is deployed.
Note: If you are new to web development in NetBeans IDE, you are recommended to follow Introduction to Developing Web Applications before continuining.
Before you begin, you need to install the following software on your computer:
Below are explanations of some of the terms used in this tutorial.
When creating a composite view, you can include static content and dynamic content. Static content might consist of an HTML file. Dynamic content is a fragment of a JSP page. The specific content can be determined at either JSP translation time or at runtime.
To create the Midnight Cookie Company application, you need the midnight.zip file, which contains the source files on which you build the application. The source files include the WEB-INF folder, which contains the classes, docs, tlds and lib folders that you will use in this tutorial.
$UNZIPHOME now has a WEB-INF folder, which contains the following files and folders:
File or Folder
|
Description
|
web.xml | Deployment descriptor for the web application. |
classes | Contains the resource bundle property files that are used to internationalize the pages and contains the com/midnightcookies/taghandlers folder. The taghandlers folder contains the class files for the ContentHandler tag handler, the ButtonHandler tag handler, and the LinksHandler tag handler. The ContentHandler includes the contents of the specified JSP file. The ButtonHandler prints a submit button with a localized message. The LinksHandler displays a set of links, including a separator, from the tag attribute. |
docs | Contains the header.jsp file, the index.jsp file, and the nonesuch.jsp file. During the tutorial, you will create the main.jsp page and place it in this folder. Also contains the cookies folder, which includes the CookieCutter.jsp file and the CookieMake.jsp file. During the tutorial, you will create the Tray.jsp page and place it in this folder. The about folder contains the about.jsp file, which outlines this web application's architecture. |
lib | Contains the standard.jar file and the jstl.jar file. These two files contain the implementation for the JSTL. The standard.jar contains the TLDs and the tag handlers. The jstl.jar file contains other application program interfaces (APIs) that are needed. |
tlds | Contains the proprietary midnight.tld. |
Click Finish.
You are prompted to let the IDE delete your class files, because they will automatically be compiled to your project's build folder when you build the project.
Click Delete to let the IDE do this.
The IDE imports your sources, deletes the class files, and creates the Midnight project in the IDE. You can view its logical structure in the Projects window and its file structure in the Files window.
A front controller is responsible for routing incoming user requests and can enforce navigation in web applications. A front controller provides a single entry point through which requests for several resources in a web application pass. A front controller can reduce duplication of code in JSP pages, especially in cases where several resources require the same processing. For more information on front controllers, see the J2EE Patterns catalog.
/docs/*, /
Note that the "," in the line above is a delimiter between URL mappings. It enables you to create multiple URL mappings for each servlet.
FrontController.java opens in the Source Editor.
The servlet mapping "/docs/*" prevents the FrontController servlet from forwarding pages to itself, while the servlet mapping "/" gives the FrontController servlet a servlet mapping to handle a request such as http://hostname:portnumber/midnight/.
Click XML at the top of the editor. The content of the deployment descriptor file is shown in XML format. The servlet mappings are as follows:
Now you will edit the FrontController.java file to include the logic needed to process the requests received by the web application. You will modify the processRequest method and create a new method called createCookie, which demonstrates how to create a cookie used in a web application.
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String id = request.getRequestURI(); id = id.substring(request.getContextPath().length()); getServletContext().log ("Midnight Cookies FrontController received a request for " + id); // The page variable holds the path to the page that will be included // in the content area of the template page /WEB-INF/docs/main.jsp. // It is passed to the template in a request attribute. String page; // If no request is received or if the request received is // for the root, serve /WEB-INF/docs/index.jsp if (id == null || id.trim().equals("") || id.equals("/")){ page = "/WEB-INF/docs/index.jsp"; } // If a request received is for a file that does not end in // .jsp or .html, there was an error. Include the // error page (nonesuch.jsp) and set the nonesuch attribute with // the path requested. else if (!id.endsWith(".jsp") && !id.endsWith(".html")) { page = "/WEB-INF/docs/nonesuch.jsp"; request.setAttribute("nonesuch", id); } else { page = "/WEB-INF".concat(id); if (id.equals("/docs/cookies/CookieMake.jsp")) { Cookie cookie = createCookie(request); if (cookie == null) { page = "/WEB-INF/docs/cookies/CookieCutter.jsp"; } else { response.addCookie(cookie); request.setAttribute("cookie", cookie); } } } request.setAttribute("page", page); try { request.getRequestDispatcher("/WEB-INF/docs/main.jsp").forward(request, response); } catch(Throwable t) { getServletContext().log(t.getMessage()); } }
Note: After you enter code (either by typing or copying and pasting) into the Source Editor, place the cursor in the Source Editor and press Alt-Shift-F to automatically format the code. To show line numbers, right-click the left margin and choose Show Line Numbers from the contextual menu.
The line with the call to the createCookie method is underlined and marked as an error, similar to the following illustration. This is because the method does not exist yet.
Click Alt-Enter in the line with the error and notice that the IDE presents a suggestion of how to solve the error:
private Cookie createCookie(HttpServletRequest request) { String name = (String)request.getParameter("name"); if (name == null || name.trim().equals("")) { request.setAttribute("noname", "noname"); request.setAttribute("error", "true"); return null; } String value = (String)request.getParameter("value"); if (value == null || value.trim().equals("")) { request.setAttribute("novalue", "novalue"); request.setAttribute("error", "true"); return null; } System.out.println(name); System.out.println(value); Cookie cookie = null; try { cookie = new Cookie(name, value); } catch(IllegalArgumentException ex) { // Probably an illegal name ex.printStackTrace(); request.setAttribute("error", "true"); request.setAttribute("noname", "badname"); return null; } String maxage = request.getParameter("maxage"); if (maxage != null && !maxage.trim().equals("")) { try { cookie.setMaxAge(Integer.parseInt(maxage)); } catch(NumberFormatException nfe) { nfe.printStackTrace(); request.setAttribute("badnumber", "badnumber"); request.setAttribute("error", "true"); return null; } } String domain = request.getParameter("domain"); if (domain != null && !domain.trim().equals("")) { cookie.setDomain(domain); } String path = request.getParameter("path"); if (path != null && !path.trim().equals("")) { cookie.setPath(path); } String secure = request.getParameter("secure"); if (secure != null && secure.equals("on")) { cookie.setSecure(true); } else { cookie.setSecure(false); } return cookie; }
Press Ctrl-S to save the document. The asterisk in the file's tab at the top of the Source Editor disappears.
The main.jsp page receives all the requests that the FrontController servlet processes. A dynamic include statement and a LinksHandler are used to create the page.
Now main.jsp opens in the Source Editor.
<%@page contentType="text/html;charset=UTF-8"%> <%@page buffer="none"%> <%-- The <midnight:content/> tag which handles the contents section is simplistically implemented to use an include. Hence this page cannot be buffered --%> <%@taglib prefix="midnight" uri="http://www.midnightcookies.com/midnight"%> <html> <head><title>The Midnight Cookie Company</title></head> <body text="#996633" link="#cc6600" vlink="#993300" alink="#000000"> <span font-style="sans-serif"> <TABLE border="0"> <tr> <table border="0"> <tr><td width="80" height="100"> </td> <td width="500" height="100" text="#996633" bgcolor="#ffff99" valign="center"halign="center"> <jsp:include page="/WEB-INF/docs/header.jsp" flush="true"/> </td> </tr> <tr><td width="90" height="300" text="#996633" bgcolor="#ffff99" valign="top"> <midnight:links separator="<br>"/> </td> <td width="500" height="300" valign="top"cellpadding="15" cellspacing="15"> <midnight:content/> </td> </tr> </table> </tr> <tr><td width="580" height="50" text="#996633" bgcolor="#ffff99" valign="top"> <midnight:links separator="|"/> </td> </tr> </TABLE> </span> </body> </html>
Note: After you enter code (either by typing or copying and pasting) into the Source Editor, place the cursor in the Source Editor and press Alt-Shift-F to automatically format the code.
The parameter files that you create in this section illustrate the use of tags from tag libraries to handle internationalization. They also show how input is passed through the Request parameters, specifically through the JSP expression language (EL) expression ${param.input}, which is set in the input field of the Input.jsp page.
Now Input.jsp opens in the Source Editor.
<%@page contentType="text/html;charset=UTF-8"%> <%@taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %> <%@taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <%@taglib prefix="midnight" uri="/WEB-INF/tlds/midnight.tld"%> <fmt:setBundle basename="com.midnightcookies.Midnight" var="bundle" scope="page"/> <h3><fmt:message key="provide_input" bundle="${bundle}"/></h3> <form method="POST" action="Output.jsp"> <table> <tr> <td><fmt:message key="type_input" bundle="${bundle}"/>:<td> <%-- The value of the Input field will be placed in a request parameter named "input" and it will be passed to Output.jsp --%> <td><input type="text" size="20" name="input" value=""></td> </tr> <tr> <td><fmt:message key="submit" bundle="${bundle}" var="buttonLabel" scope="page"/> <midnight:button/> </td> <td></td> </tr> </table> </form>
<%@page contentType="text/html;charset=UTF-8"%> <%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %> <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <fmt:setBundle basename="com.midnightcookies.Midnight" var="bundle" scope="page"/> <h3><fmt:message key="display_input" bundle="${bundle}"/></h3> <fmt:message key="datareceived" bundle="${bundle}"/>: <!--The following line gets the value of the request parameter named "input". This is a demo application. For security reasons, one should never echo user input without parsing first. --> <c:out value="${param.input}"/>
The Tray.jsp page that you create in this section illustrates the use of the JSTL, instead of scripting, to internationalize the page. The CookieCutter.jsp file, CookieMaker.jsp file, and resource bundle property files have been provided with the midnight.zip file. You can take a closer look at those files and the Tray.jsp file for examples of how internationalization is handled in this application.
<%@page contentType="text/html;charset=UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %> <fmt:setBundle basename="com.midnightcookies.Midnight" var="bundle" scope="page"/> <h3><fmt:message key="cookies" bundle="${bundle}"/></h3> <table border="1"> <tr> <th halign="center">#</th> <th align="left"> <fmt:message key="name" bundle="${bundle}"/> </th> <th align="left"> <fmt:message key="value" bundle="${bundle}"/> </th> <tr> <%-- We have to use expression to get at an array. If we use ${cookie} then we get a map and the entries are not automatically cast --%> <% request.setAttribute("cookies", request.getCookies()); %> <c:set var="i" value="0"/> <c:forEach var="ck" items="${cookies}"> <c:set var="i" value="${i+1}"/> <tr> <td><c:out value="${i}"/></td> <td><c:out value="${ck.name}"/></td> <td><c:out value="${ck.value}"/></td> </tr> </c:forEach> </table>
Once you have completed the development stage as described above, the views in the Projects window and Files window should look as follows:
Note: The application illustrated above deploys to the Tomcat Web Server. If you have registered and selected a different target server instead, you will not have a META-INF/context.xml file. For example, if your server is the Sun Java System Application Server, you will have a WEB-INF/sun-web.xml file as your deployment descriptor.
The HTTP Monitor is enabled by default for the Tomcat Web Server. However, for other servers, you must manually enable the HTTP Monitor. In addition, the HTTP Server must be started for the HTTP Monitor to work for other servers.
Do the following to prepare to use the HTTP Monitor:
A progress monitor window appears as the application is prepared and deployed to the web server.
The web browser launches with the URL set to http://hostname:port/Midnight. The following example shows the web browser running on a Microsoft Windows platform.
The following sections illustrate how you can use the HTTP Monitor to monitor requests, sessions, and cookies.
The last entry represents the request for the Midnight web application.
Your web browser displays information similar to the following.
Your web browser displays the contents of the Output.jsp page, similar to the following.
The HTTP Monitor displays information similar to the following.
Your web browser displays the CookieCutter.jsp page.
Your web browser displays information similar to the following.
The Cookies tab in the HTTP Monitor displays information similar to the following.
The HTTP Monitor displays information similar to the following.
Notice that the content of nonesuch.jsp page is displayed in place of the non-existent Bake.jsp page.
Note that you might have to add these two languages to the list of languages currently available to your web browser.
Notice how the links in the left navigation bar, the links on the bottom of the pages, and the contents of some of the application's JSP pages have been translated to the language you have chosen.
The web application uses the resource bundle property files to help translate some of the pages used in this web application. So, the translation is only as extensive as the contents of the resource bundle property files.
Keyword | Default | French | Swedish |
exit | Exit | Sortie | Utgång |
closingRemark | Goodbye | Au revoir | Hej då |
Use å to display the å character.
Below are some other web application features that you might want to explore.
Expand the tlds/Midnight node to see the list of tags in the library. Look at the the Links tag in the Source Editor and at its Attributes to see that it takes a separator attribute.
Open the docs/main.jsp file in the Source Editor and set a breakpoint by clicking in the margin at approximately line 32 (the line that invokes midnight:content). Right-click the project node in the Projects or Files window and choose Debug Project from the contextual menu. The web application will stop at the breakpoint that you set. Press F7 to step into the code. Whenever a dialog appears because of missing source, press OK to select the default of stopping at the first line with source. Continue pressing F7 until you enter the otherDoStartTagOperations() function in the ContentHandler class. Set a breakpoint at line 50 (request.getRequestDispatcher(page).include(request, response)) and press Ctrl-F5 (continue). Place the cursor over "page", "request", and "response" to see the values. You can also see the values in the Local Variables tab. Note that the Call Stack tab shows the relationship between the JSP code and the generated servlet methods. Try setting other breakpoints. Right-click a variable and choose New Watch from the contextual menu. Click the Watches tab to see the values change as you execute the various pages in the web application. Choose Debug > Finish Session to quit the debugging session.
To run a public JSP file (one that is not under the WEB-INF folder), you simply right-click the file's node and choose Execute from the contextual menu. If a page is loaded, clicking the Browser's reload button will display any modifications that you have made. Private JSP files, like the ones in this tutorial, are a little harder to execute. One way to test a modified private JSP file without having to restart the web application and navigate to that page is to use the HTTP Monitor's replay action. Modify the docs/cookies/Tray.jsp file by setting the table's border to 10 and save your changes. In the HTTP Monitor, right-click a GET Tray.jsp record and choose Replay from the contextual menu. The Tray.jsp page should appear in the browser with a larger table border.
Below are explanations of some of the terms used in this tutorial.
A design pattern that is used to present information in JSP pages. This design pattern creates an aggregate view from component views. Component views might include dynamic and modular portions of the page. The Composite View design pattern pertains to web application design when you are creating a view from numerous subviews. Complex web pages frequently consist of content derived from various resources. The layout of the page is managed independently of the content of its subviews. For instance, a view might have subviews such as Navigation, Search, Feature Story, and Headline.
When creating a composite view, you can include static content and dynamic content. Static content might consist of an HTML file. Dynamic content is a fragment of a JSP page. The specific content can be determined at either JSP translation time or at runtime.
Front controllers are responsible for routing incoming requests and enforcing navigation in web applications. For more information on the use of the Front Controller design pattern, see the J2EE Patterns catalog.
Pages that are used in web applications to present information to end users and to enable data from end users to flow back to the server. JSP pages must be placed within a web application in order for the JSP pages to be executable within the IDE.
Servlets are Java classes that execute within a servlet container, which is typically running within a web server. Servlets are used to do the following:
For more information about using NetBeans IDE 6.0, see the following resources:
To send comments and suggestions, get support, and keep informed on the latest developments on the NetBeans IDE J2EE development features, join the [email protected] mailing list. For more information about upcoming J2EE development features in NetBeans IDE, see j2ee.netbeans.org.