| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| |
| <html> |
| <head> |
| <meta name="author" content="troy.giunipero@sun.com"> |
| <meta http-equiv="content-type" content="text/html; charset=UTF-8"> |
| <meta name="description" content="The NetBeans E-commerce Tutorial (Complete Version)"> |
| |
| <meta name="keywords" content="NetBeans, IDE, integrated development environment, |
| Java, Java EE, open source, web technology, e-commerce"> |
| |
| <link rel="stylesheet" type="text/css" href="../../../../netbeans.css"> |
| <link rel="stylesheet" type="text/css" href="../../../../print.css" media="print"> |
| <link rel="stylesheet" type="text/css" href="../../../../lytebox.css" media="screen"> |
| <script type="text/javascript" src="../../../../images_www/js/lytebox-compressed.js"></script> |
| |
| <script src="../../../../images_www/js/listCollapse.js" type="text/javascript"></script> |
| |
| <title>The NetBeans E-commerce Tutorial</title> |
| </head> |
| |
| <body> |
| |
| <!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. --> |
| |
| <h1 id="intro">The NetBeans E-commerce Tutorial - Introduction</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><strong>Introduction</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#about">About this Tutorial</a></li> |
| <li><a href="#whatEcommerce">What is an E-commerce Application?</a></li> |
| <li><a href="#whatJava">What is Java?</a></li> |
| <li><a href="#jcp">What is the Java Community Process?</a></li> |
| <li><a href="#ide">Why use an IDE?</a></li> |
| <li><a href="#netBeans">Why use NetBeans?</a></li> |
| <li><a href="#seeAlsoIntro">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>Welcome to the NetBeans E-commerce Tutorial. In this multi-part tutorial, you |
| learn how to create a simple yet effective e-commerce application that demonstrates |
| various important features of Java web and EE development. In doing so, you'll |
| familiarize yourself with the NetBeans IDE and become capable of applying it to |
| your own development purposes.</p> |
| |
| <p>Taking the time to master the IDE will ultimately lead you to become more efficient |
| and versatile as a developer. While you work through the tutorial units, you'll learn |
| how to make best use of the IDE's facilities and tools. These include:</p> |
| |
| <ul style="margin-left: 320px" class="toc"> |
| <li><strong>Editor support for different languages:</strong> syntax highlighting, |
| code completion, API documentation support, keyboard shortcuts, refactoring |
| capabilities, and code templates</li> |
| |
| <li><strong>Window system:</strong> Projects, Files and Services windows, the |
| Tasks window, Javadoc window, HTTP Monitor, Navigator and Palette</li> |
| |
| <li><strong>Integration with other services: </strong>automatic deployment to |
| a registered server, database connectivity, browser interoperability</li> |
| |
| <li><strong>Development tools:</strong> Debugger, Profiler, HTTP Server |
| Monitor, Local History support, and a graphical Diff Viewer</li> |
| </ul> |
| |
| <p>The tutorial is modular in fashion, with each unit focusing on specific concepts, |
| technologies, and features of the IDE. You can successfully follow a tutorial unit |
| on its own using the provided setup instructions and application snapshots (from |
| Unit 5 onward). However, you'll get the most benefit by working through all units |
| consecutively, from beginning to end. This will also help to illustrate the |
| development process.</p> |
| |
| <p>Unit 3, <a href="#setup-dev-environ">Setting up the Development Environment</a> |
| introduces you to the NetBeans IDE. In it, you create a Java web project which |
| is the basis for the work you undertake in later tutorial units. In Unit 4, |
| <a href="#data-model">Designing the Data Model</a>, you primarily work with |
| <a href="http://wb.mysql.com/" target="_blank">MySQL WorkBench</a>, a visual |
| database design tool, to create a data model for the application. Each successive |
| tutorial unit provides you with a <em>project snapshot</em> that corresponds to |
| the project's beginning state for that given unit. This enables you to work through |
| a single tutorial unit outside of the E-commerce Tutorial's larger context. To use |
| these snapshots, download them to your computer and open them in the IDE using the |
| Open Project wizard (Ctrl-Shift-O; ⌘-Shift-O on Mac).</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans |
| E-commerce Tutorial Demo Application</a>.</p> |
| |
| <p>The remainder of this unit covers some information relevant to the tutorial, as |
| well as basic concepts necessary for Java EE development. Make sure you understand |
| the concepts outlined below before proceeding with development.</p> |
| |
| <br clear="left"> |
| |
| |
| <br> |
| <h2 id="about">About this Tutorial</h2> |
| |
| <div class="indent"> |
| <h3>Who this Tutorial is for</h3> |
| |
| <p>The content of this tutorial caters to four demographics:</p> |
| |
| <ul> |
| <li>Java developers interested in expanding their skill set to include Java |
| EE technologies</li> |
| |
| <li>Newcomers to the NetBeans IDE wanting to try out its development |
| environment</li> |
| |
| <li>Web developers wanting to see how Java compares to other web-based |
| technologies</li> |
| |
| <li>Students wanting to understand the nuts and bolts a simple e-commerce |
| application, and how its development could apply to a real-world |
| use-case</li> |
| </ul> |
| |
| <p>If you fall into any of these categories, this tutorial will be helpful to |
| you. Depending on your background, you may find that certain tutorial units |
| are more difficult to grasp than others. Understanding how technologies |
| work is key to leveraging the IDE for your purposes. Therefore, if you are |
| really interested in learning the technologies involved, you may find that |
| this tutorial works best as a companion to the |
| <a href="http://download.oracle.com/docs/cd/E17410_01/javaee/6/tutorial/doc/" target="_blank">Java |
| EE Tutorial</a>. For each tutorial unit, make best use of the provided links |
| to relevant areas in the Java EE Tutorial, as well as to other useful resources.</p> |
| |
| |
| <h3>What this Tutorial Covers</h3> |
| |
| <p>The application that you develop in this tutorial involves numerous concepts, |
| technologies, and tooling components:</p> |
| |
| <ul class="toc"> |
| <li><strong>Concepts</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li>Front-end development</li> |
| <li>Web application project structure</li> |
| <li>Data modeling</li> |
| <li>Database connectivity</li> |
| <li>Object-relational mapping</li> |
| <li>Session management</li> |
| <li>Transactional business logic</li> |
| <li>Client and server-side validation</li> |
| <li>Localization</li> |
| <li>Web application security</li> |
| <li>Design patterns, including <a href="http://java.sun.com/blueprints/patterns/MVC.html" target="_blank">Model-View-Controller</a> |
| (MVC) and <a href="http://java.sun.com/blueprints/patterns/SessionFacade.html" target="_blank">Session Facade</a></li> |
| </ul></li> |
| |
| <li><strong>Technologies</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li>HTML, CSS, and JavaScript technologies</li> |
| <li>Servlet and JavaServer Pages (JSP) technologies</li> |
| <li>Enterprise JavaBeans (EJB) technology</li> |
| <li>Java Persistence API (JPA)</li> |
| <li>The JavaServer Pages Standard Tag Library (JSTL)</li> |
| <li>Java Database Connectivity (JDBC)</li> |
| </ul></li> |
| |
| <li><strong>Development Tools</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li>NetBeans IDE</li> |
| <li>GlassFish, a Java EE application server</li> |
| <li>MySQL, a relational database management server (RDBMS)</li> |
| <li>MySQL WorkBench, a visual database design tool</li> |
| </ul> |
| </li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2 id="whatEcommerce">What is an E-commerce Application?</h2> |
| |
| <p>The term <em>e-commerce</em>, as we think of it today, refers to the buying and |
| selling of goods or services over the Internet. For example, you may think of |
| <a href="http://www.amazon.com/" target="_blank">Amazon</a>, which provides online |
| shopping for various product categories, such as books, music, and electronics. |
| This form of e-commerce is known as electronic retailing, or <em>e-tailing</em>, |
| and usually involves the transportation of physical items. It is also referred |
| to as <em>business-to-customer</em>, or B2C. Other well-known forms include:</p> |
| |
| <ul> |
| <li><strong>Consumer-to-consumer (C2C): </strong>Transactions taking place |
| between individuals, usually through a third-party site such as an online |
| auction. A typical example of C2C commerce is <a href="http://www.ebay.com/" target="_blank">eBay</a>.</li> |
| |
| <li><strong>Business-to-business (B2B): </strong>Trade occurring between |
| businesses, e.g., between a retailer and wholesaler, or between a wholesaler |
| and manufacturer.</li> |
| |
| <li><strong>Business-to-government (B2G): </strong>Trade occurring between |
| businesses and government agencies.</li> |
| </ul> |
| |
| <p>This tutorial focuses on business-to-customer (B2C) e-commerce, and applies the |
| typical scenario of a small retail store seeking to create a website enabling |
| customers to shop online. Software that accommodates a B2C scenario generally |
| consists of two components:</p> |
| |
| <ol> |
| <li><strong>Store Front:</strong> The website that is accessed by customers, |
| enabling them to purchase goods over the Internet. Data from the store catalog |
| is typically maintained in a database, and pages requiring this data are |
| generated dynamically.</li> |
| |
| <li><strong>Administration Console:</strong> A password-protected area that is |
| accessed over a secure connection by store staff for purposes of online management. |
| This typically involves CRUD (create read update delete) access to the store |
| catalog, management of discounts, shipping and payment options, and review |
| of customer orders.</li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="whatJava">What is Java?</h2> |
| |
| <p>In the computer software industry, the term "Java" refers to the |
| <em>Java Platform</em> as well as the <em>Java Programming Language</em>.</p> |
| |
| <div class="feedback-box margin-around"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/intro/duke.png" |
| class="margin-around" alt="Image of Duke" title="Duke, the Java mascot"> |
| |
| <p>Duke, the Java mascot</p> |
| </div> |
| |
| <div class="indent"> |
| <h3>Java as a Programming Language</h3> |
| |
| <p>The Java language was conceptualized by |
| <a href="http://en.wikipedia.org/wiki/James_Gosling" target="_blank">James Gosling</a>, |
| who began work on the project in 1991. The language was created with the following |
| 5 design principles<sup><a href="#footnote1Intro" id="1Intro" style="text-decoration:none">[1]</a></sup> |
| in mind:</p> |
| |
| <ol> |
| <li><strong>Simple, Object-Oriented, and Familiar:</strong> Java contains |
| a small, consistent core of fundamental concepts that can be grasped |
| quickly. It was originally modeled after the then popular C++ language, |
| so that programmers could easily migrate to Java. Also, it adheres to |
| an <em>object-oriented</em> paradigm; systems are comprised of |
| encapsulated objects that communicate by passing messages to one another.</li> |
| |
| <li><strong>Robust and Secure:</strong> The language includes compile-time |
| and run-time checking to ensure that errors are identified quickly. It |
| also contains network and file-access security features so that distributed |
| applications are not compromised by intrusion or corruption.</li> |
| |
| <li><strong>Architecture Neutral and Portable:</strong> One of Java's primary |
| advantages is its <em>portability</em>. Applications can be easily |
| transferred from one platform to another with minimum or no modifications. |
| The slogan "Write once, run anywhere" accompanied the Java 1.0 |
| release in 1995, and refers to the cross-platform benefits of the language.</li> |
| |
| <li><strong>High Performance:</strong> Applications run quickly and efficiently |
| due to various low-level features, such as enabling the Java interpreter |
| to run independently from the run-time environment, and applying an |
| automatic garbage collector to free unused memory.</li> |
| |
| <li><strong>Interpreted, Threaded, and Dynamic:</strong> With Java, a developer's |
| source code is compiled into an intermediate, interpreted form known as |
| <em>bytecode</em>. The bytecode instructional set refers to the machine |
| language used by the Java Virtual Machine (JVM). With a suitable interpreter, |
| this language can then be translated into <em>native code</em> for the |
| platform it is run on. Multithreading capabilities are supported primarily |
| by means of the <code>Thread</code> class, enabling numerous tasks to occur |
| simultaneously. The language and run-time system are dynamic in that |
| applications can adapt to environment changes during execution.</li> |
| </ol> |
| |
| <p>If you'd like to learn more about the Java language, see |
| the <a href="http://java.sun.com/docs/books/tutorial/" target="_blank">Java Tutorials</a>.</p> |
| |
| |
| <h3 id="platform">Java as a Platform</h3> |
| |
| <p>The Java Platform signifies a software-based platform that is comprised of two |
| parts:</p> |
| |
| <ul> |
| <li><strong>The Java Virtual Machine (JVM)</strong>: The JVM is an engine that |
| executes instructions generated by the Java compiler. The JVM can be thought |
| of as an instance of the Java Runtime Environment, or JRE, and is embedded |
| in various products, such as web browsers, servers, and operating systems.</li> |
| |
| <li><strong>The Java Application Programming Interface (API)</strong>: |
| Prewritten code, organized into packages of similar topics. For instance, |
| the Applet and AWT packages include classes for creating fonts, menus, |
| and buttons.</li> |
| </ul> |
| |
| <p>The Java Development Kit, or JDK, refers to the Java SE Edition, while other |
| kits are referred to as "SDK", a generic term for "software |
| development kit." For example, the <a href="http://java.sun.com/javaee/sdk/" target="_blank">Java |
| EE SDK</a>.<sup><a href="#footnote2Intro" id="2Intro" style="text-decoration:none">[2]</a></sup></p> |
| |
| <p>You can see a visual representation of the Java platform by viewing the |
| conceptual diagram of component technologies provided in the |
| <a href="http://download.oracle.com/javase/6/docs/index.html" target="_blank">JDK Documentation</a>. |
| As shown below, the diagram is interactive, enabling you click on components |
| to learn more about individual technologies. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/intro/jdk-diagram.png" |
| class="margin-around" alt="Diagram of JDK 6" |
| title="The Java platform represented by the JDK"></p> |
| |
| <p>As the diagram indicates, the JDK includes the Java Runtime Environment (JRE). |
| You require the JRE to run software, and you require the JDK to develop |
| software. Both can be acquired from |
| <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java SE Downloads</a>.</p> |
| |
| <p>The Java platform comes in several <em>editions</em>, such as |
| <a href="http://java.sun.com/javase/" target="_blank">Java SE</a> (Standard Edition), |
| <a href="http://java.sun.com/javame/index.jsp" target="_blank">Java ME</a> (Micro Edition), |
| and <a href="http://java.sun.com/javaee/" target="_blank">Java EE</a> (Enterprise Edition).</p> |
| |
| |
| <h3>Java EE</h3> |
| |
| <p>The Java Platform, Enterprise Edition (Java EE) builds upon the Java SE platform |
| and provides a set of technologies for developing and running portable, robust, |
| scalable, reliable and secure server-side applications.</p> |
| |
| <p>EE technologies are loosely divided into two categories:</p> |
| |
| <ul> |
| <li><a href="http://java.sun.com/javaee/technologies/webapps/" target="_blank">Web application technologies</a></li> |
| <li><a href="http://java.sun.com/javaee/technologies/entapps/" target="_blank">Enterprise application technologies</a></li> |
| </ul> |
| |
| <p>Depending on your needs, you may want to use certain technologies from either |
| category. For example, this tutorial makes use of |
| <a href="http://java.sun.com/products/servlet/index.jsp" target="_blank">Servlet</a>, |
| <a href="http://java.sun.com/products/jsp/" target="_blank">JSP/EL</a>, and |
| <a href="http://java.sun.com/products/jsp/jstl/" target="_blank">JSTL</a> "web" |
| technologies, as well as |
| <a href="http://java.sun.com/products/ejb/" target="_blank">EJB</a> and |
| <a href="http://java.sun.com/javaee/technologies/persistence.jsp" target="_blank">JPA</a> |
| "enterprise" technologies.</p> |
| |
| <p>Java EE currently dominates the market, especially in the financial sector. The following |
| diagram is taken from an |
| <!-- <a href="http://www.sun.com/aboutsun/media/analyst/european_fsa.pdf"> --> |
| <a href="http://docs.google.com/viewer?a=v&q=cache:2NNYG8LtVFIJ:www.sun.com/aboutsun/media/analyst/european_fsa.pdf+european_fsa.pdf&hl=en&pid=bl&srcid=ADGEESi3vpbc32J7GzXFiqk__DvMp7_3deYe9td-HP3_QEXh77yBABi35uvL1z7ytj6o17io7_YFPnRFmhju5PQgrpgjVxt-2qXQSUh8xGUbeNP0k00dDsiq1Tl0DWJLOEH3SNubhit5&sig=AHIEtbTKL5tks3AlgEt57h4Aku_H55OXag" target="_blank"> |
| independent survey for European markets</a> performed in 2007.</p> |
| |
| <div class="indent"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/intro/java-ee-vs-net.png" |
| class="margin-around b-all" alt="Survey Java EE vs .Net" |
| title="Java EE dominates the financial market"> |
| </div> |
| |
| <p class="tips">For a recent, informal comparison of Java EE to .NET, see the blog post |
| <a href="http://www.adam-bien.com/roller/abien/entry/java_ee_or_net_an" target="_blank">Java |
| EE or .NET - An Almost Unbiased Opinion</a> by a well-known member of the Java EE community.</p> |
| |
| |
| <h3>What's the Difference Between...?</h3> |
| |
| <p>There are many abbreviations and acronyms to parse. If you're new to all of this |
| and find the above explanation somewhat confusing, the following resources can |
| help explain what the differences are between some of the commonly used terminology.</p> |
| |
| <ul> |
| <li><a href="http://www.java.com/en/download/faq/jre_jdk.xml" target="_blank">What's the Difference between the JRE and the JDK?</a></li> |
| <li><a href="http://www.java.com/en/download/faq/java_diff.xml" target="_blank">What's the Difference between the JRE and the Java SE platform?</a></li> |
| <li><a href="http://www.oracle.com/technetwork/java/javaee/javaee-faq-jsp-135209.html#diff" target="_blank">What's the Difference between Java EE and J2EE?</a></li> |
| <li><a href="http://java.sun.com/new2java/programming/learn/unravelingjava.html" target="_blank">Unraveling Java Terminology</a></li> |
| </ul> |
| |
| </div> |
| |
| |
| <br> |
| <h2 id="jcp">What is the Java Community Process?</h2> |
| |
| <p>The <a href="http://jcp.org/" target="_blank">Java Community Process</a> (JCP) is a |
| program that manages the development of standard technical specifications for Java |
| technology. The JCP catalogs Java Specification Requests (JSRs), which are formal |
| proposals that document the technologies which are to be added to the Java platform. |
| JSRs are run by an <em>Expert Group</em>, which typically comprises representatives |
| of companies that are stakeholders in the industry. The JCP enables Java technology |
| to grow and adapt according to the needs and trends of the community.</p> |
| |
| <p>The JSRs of technologies used and referred to in this tutorial include the following:</p> |
| |
| <ul> |
| <li><a href="http://jcp.org/en/jsr/summary?id=52" target="_blank">JSR 52: A Standard Tag Library for JavaServer Pages</a></li> |
| <li><a href="http://jcp.org/en/jsr/summary?id=245" target="_blank">JSR 245: JavaServer Pages 2.1</a></li> |
| <li><a href="http://jcp.org/en/jsr/summary?id=315" target="_blank">JSR 315: Java Servlet 3.0</a></li> |
| <li><a href="http://jcp.org/en/jsr/summary?id=316" target="_blank">JSR 316: Java Platform, Enterprise Edition 6</a></li> |
| <li><a href="http://jcp.org/en/jsr/summary?id=317" target="_blank">JSR 317: Java Persistence 2.0</a></li> |
| <li><a href="http://jcp.org/en/jsr/summary?id=318" target="_blank">JSR 318: Enterprise JavaBeans 3.1</a></li> |
| </ul> |
| |
| <p>You can use the <a href="http://jcp.org/" target="_blank">JCP website</a> to search for individual JSRs. |
| You can also view all current EE technologies (Java EE 6) at:</p> |
| |
| <ul> |
| <li><a href="http://java.sun.com/javaee/technologies/index.jsp" target="_blank">http://java.sun.com/javaee/technologies/index.jsp</a></li> |
| </ul> |
| |
| <p>Java EE 5 technologies are listed at:</p> |
| |
| <ul> |
| <li><a href="http://java.sun.com/javaee/technologies/javaee5.jsp" target="_blank">http://java.sun.com/javaee/technologies/javaee5.jsp</a></li> |
| </ul> |
| |
| <p>A JSR's final release provides a <em>reference implementation</em>, which is a free |
| implementation of the technology. In this tutorial, you utilize these implementations |
| to develop the sample e-commerce application. For example, the GlassFish v3 application |
| server, which is included in the standard Java download bundle for |
| <a href="https://netbeans.org/downloads/6.8/index.html" target="_blank">NetBeans |
| 6.8</a>, is the reference implementation of the Java EE 6 platform specification |
| (<a href="http://jcp.org/en/jsr/summary?id=316" target="_blank">JSR 316</a>). As a |
| reference implementation for the Java EE platform, it includes reference implementations |
| for the technologies included in the platform, such as Servlet, EJB and JPA technologies.</p> |
| |
| |
| <br> |
| <h2 id="ide">Why use an IDE?</h2> |
| |
| <p>Firstly, the term <em>IDE</em> stands for <em>integrated development environment</em>. |
| The purpose of an IDE has traditionally been to maximize a developer's productivity |
| by providing tools and support such as:</p> |
| |
| <ul class="toc"> |
| <li>a source code editor</li> |
| <li>a compiler and build automation tools</li> |
| <li>a window system for viewing projects and project artifacts</li> |
| <li>integration with other commonly-used services</li> |
| <li>debugging support</li> |
| <li>profiling support</li> |
| </ul> |
| |
| <p>Consider what would be necessary if you wanted to create a Java-based web application |
| manually. After installing the <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java |
| Development Kit (JDK)</a>, you would need to set up your development environment by |
| performing the following steps.<sup><a href="#footnote3Intro" id="3Intro" style="text-decoration:none">[3]</a></sup></p> |
| |
| <ol> |
| <li>Set your <code>PATH</code> environment variable to point to the JDK installation.</li> |
| |
| <li>Download and configure a server that implements the technologies you plan to use.</li> |
| |
| <li>Create a development directory where you plan to create and work on the web application(s). |
| Furthermore, you are responsible for setting up the application directory structure so |
| that it can be understood by the server. (For example, see |
| <a href="http://java.sun.com/blueprints/code/projectconventions.html#99632" target="_blank">Java |
| BluePrints: Strategy for Web Applications</a> for a recommended structure.)</li> |
| |
| <li>Set your <code>CLASSPATH</code> environment variable to include the development |
| directory, as well as any required JAR files.</li> |
| |
| <li>Establish a deployment method, i.e., a way to copy resources from your development |
| directory to the server's deployment area.</li> |
| |
| <li>Bookmark or install relevant API documentation.</li> |
| </ol> |
| |
| <p>For educative purposes, it is worthwhile to create and run a Java web project manually |
| so that you are aware the necessary steps involved. But eventually, you'll want to |
| consider using tools that reduce or eliminate the need to perform tedious or repetitious |
| tasks, thereby enabling you to focus on developing code that solves specific business |
| needs. An IDE streamlines the process outlined above. As demonstrated in Unit 3, |
| <a href="#setup-dev-environ">Setting up the Development Environment</a>, you'll |
| install NetBeans IDE with the GlassFish application server, and be able to set up |
| a web application project with a conventional directory structure using a simple |
| 3-step wizard. Furthermore, the IDE provides provides built-in API documentation which |
| you can either call up as you code in the editor, or maintain open in an external |
| window.</p> |
| |
| <p>An IDE also typically handles project compilation and deployment in a way that is |
| transparent to you as a developer. For example, the web project that you create in |
| NetBeans includes an Ant build script that is used to compile, clean, package and |
| deploy the project. This means that you can run your project from the IDE, and it |
| will automatically be compiled and deployed, then open in your default browser. |
| Taking this a step further, many IDEs support a Deploy on on Save feature. In other |
| words, whenever you save changes to your project, the deployed version on your |
| server is automatically updated. You can simply switch to the browser and refresh |
| the page to view changes.</p> |
| |
| <p>IDEs also provide templates for various file types, and often enable you to add them |
| to your project by suggesting common locations and including default configuration |
| information where necessary.</p> |
| |
| <p>Aside from the "basic support" described above, IDEs typically provide |
| interfaces to external tools and services (e.g., application and database servers, |
| web services, debugging and profiling facilities, and collaboration tools) which |
| are indispensable to your work if Java development is your profession.</p> |
| |
| <p>Finally, IDEs usually provide enhanced editor support. The editor is where you likely |
| spend most of your time working, and IDE editors typically include syntax highlighting, |
| refactoring capabilites, keyboard shortcuts, code completion, hints and error messages, |
| all aiming to help you work more efficiently and intelligently.</p> |
| |
| |
| <br> |
| <h2 id="netBeans">Why use NetBeans?</h2> |
| |
| <p>The NetBeans IDE is a free, open-source integrated development environment written |
| entirely in Java. It offers a range of tools for create professional desktop, |
| enterprise, web, and mobile applications with the Java language, C/C++, |
| and even scripting languages such as PHP, JavaScript, Groovy, and Ruby.</p> |
| |
| <p>People are saying great things about NetBeans. For a list of testimonials, see |
| <a href="../../../../features/ide/testimonials.html" target="_blank">NetBeans IDE |
| Testimonials</a>. Many developers are migrating their applications to NetBeans |
| from other IDEs. For reasons why, read <a href="../../../../switch/realstories.html" target="_blank">Real |
| Stories From People Switching to NetBeans IDE</a>.</p> |
| |
| <p>The IDE provides many <a href="../../../../features/web/index.html" target="_blank">features |
| for web development</a>, and several advantages over other IDEs. Here are several |
| noteworthy points:</p> |
| |
| <ul> |
| <li><strong>Works Out of the Box:</strong> Simply download, install, and run the |
| IDE. With its small download size, installation is a breeze. The IDE runs on |
| many platforms including Windows, Linux, Mac OS X and Solaris. All IDE tools |
| and features are fully integrated - no need to hunt for plug-ins - and they |
| work together when you launch the IDE.</li> |
| |
| <li><strong>Free and Open Source:</strong> When you use the NetBeans IDE, you join |
| a vibrant, <a href="../../../../community/index.html" target="_blank">open source |
| community</a> with thousands of users ready to help and contribute. There are |
| discussions on the <a href="../../../../community/lists/index.html" target="_blank">NetBeans |
| project mailing lists</a>, blogs on <a href="http://www.planetnetbeans.org/" target="_blank">Planet |
| NetBeans</a>, and helpful FAQs and tutorials on the <a href="http://wiki.netbeans.org/" target="_blank">community |
| wiki</a>.</li> |
| |
| <li><strong>Profiling and Debugging Tools:</strong> With NetBeans IDE |
| <a href="../../../../features/java/profiler.html">profiler</a>, you get real time |
| insight into memory usage and potential performance bottlenecks. Furthermore, you can |
| instrument specific parts of code to avoid performance degradation during profiling. |
| The <a href="http://profiler.netbeans.org/docs/help/6.0/heapwalker.html" target="_blank">HeapWalker</a> |
| tool helps you evaluate Java heap contents and find memory leaks.</li> |
| |
| <li><strong>Customizable Projects:</strong> Through the NetBeans IDE build process, which |
| relies on industry standards such as <a href="http://ant.apache.org/" target="_blank">Apache |
| Ant</a>, <a href="http://www.gnu.org/software/make/" target="_blank">make</a>, |
| <a href="http://maven.apache.org/" target="_blank">Maven</a>, and |
| <a href="http://rake.rubyforge.org/" target="_blank">rake</a> - rather than a |
| proprietary build process - you can easily customize projects and add functionality. |
| You can build, run, and deploy projects to servers outside of the IDE.</li> |
| |
| <li><strong>Collaboration Tools:</strong> The IDE provides built-in support for version |
| control systems such as CVS, Subversion, and Mercurial.</li> |
| |
| <li><strong>Extensive Documentation:</strong> There's a wealth of tips and instructions |
| contained in the IDE's built-in help set. Simply press F1 (fn-F1 on Mac) on a component |
| in the IDE to invoke the help set. Also, the IDE's <a href="../../../index.html" target="_blank">official |
| knowledge base</a> provides hundreds of online tutorials, articles and |
| <a href="../../intro-screencasts.html" target="_blank">screencasts</a> that are |
| continuously being updated.</li> |
| </ul> |
| |
| <p>For a more extensive list of reasons why you should consider choosing NetBeans, see |
| <a href="../../../../switch/why.html" target="_blank">NetBeans IDE Connects Developers</a>.</p> |
| |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Introduction">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <h2 id="seeAlsoIntro">See Also</h2> |
| |
| <div class="indent"> |
| <h3>Online Resources</h3> |
| |
| <ul> |
| <li><a href="http://java.sun.com/docs/books/tutorial/" target="_blank">The Java Tutorials</a></li> |
| <li><a href="http://www.oracle.com/technetwork/java/javaee/javaee-faq-jsp-135209.html" target="_blank">Java EE FAQ</a></li> |
| <li><a href="http://java.sun.com/javaee/reference/apis/" target="_blank">Java EE APIs & Docs</a></li> |
| <li><a href="http://java.sun.com/new2java/programming/learn/unravelingjava.html" target="_blank">Unraveling Java Terminology</a></li> |
| <li><a href="http://www.java.com/en/javahistory/index.jsp" target="_blank">The History of Java Technology</a></li> |
| <li><a href="http://java.sun.com/new2java/gettingstarted.jsp" target="_blank">New to Java Programming Center</a></li> |
| </ul> |
| |
| <h3>Books</h3> |
| |
| <ul> |
| <li><a href="http://www.apress.com/book/view/1590598954" target="_blank">Pro NetBeans |
| IDE 6 Rich Client Platform Edition</a></li> |
| |
| <li><a href="http://www.informit.com/store/product.aspx?isbn=0130092290" target="_blank">Core |
| Servlets and JavaServer Pages, Volume 1: Core Technologies, 2nd Edition</a></li> |
| |
| <li><a href="http://www.informit.com/store/product.aspx?isbn=0131482602" target="_blank">Core |
| Servlets and JavaServer Pages, Volume 2: Advanced Technologies, 2nd Edition</a></li> |
| |
| <li><a href="http://java.sun.com/docs/books/faq/" target="_blank">The Java FAQ</a></li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2 id="referencesIntro">References</h2> |
| |
| <ol> |
| <li id="footnote1Intro"><a href="#1Intro" style="text-decoration:none">^</a> The white paper, |
| <a href="http://java.sun.com/docs/white/langenv/Intro.doc2.html" target="_blank">The Java |
| Language Environment</a>, outlines the 5 design principles.</li> |
| |
| <li id="footnote2Intro"><a href="#2Intro" style="text-decoration:none">^</a> Current version names and |
| numbers are defined in |
| <a href="http://download.oracle.com/javase/6/webnotes/version-6.html" target="_blank">Java SE |
| 6, Platform Name and Version Numbers</a>.</li> |
| |
| <li id="footnote3Intro"><a href="#3Intro" style="text-decoration:none">^</a> These steps are loosely |
| based on those outlined in Chapter 2: Server Setup and Configuration, from |
| <a href="http://pdf.coreservlets.com/" target="_blank">Core Servlets and JavaServer Pages</a>, |
| by Marty Hall and Larry Brown. This book is freely available in PDF format from: |
| <a href="http://pdf.coreservlets.com/" target="_blank">http://pdf.coreservlets.com/</a></li> |
| </ol> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="design">The NetBeans E-commerce Tutorial - Designing the Application</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><strong>Designing the Application</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#scenario">The Scenario</a></li> |
| <li><a href="#requirements">Gathering Customer Requirements</a></li> |
| <li><a href="#mockups">Preparing Mockups</a></li> |
| <li><a href="#architecture">Determining the Architecture</a></li> |
| <li><a href="#planning">Planning the Project</a></li> |
| <li><a href="#seeAlsoDesign">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>The application that you design in this tutorial is based on a real-world scenario. After |
| being introduced to the tutorial scenario, you consolidate a high-level list of customer |
| requirements. You then prepare a diagram of the application's business process flow, |
| and a series of <em>mockups</em> which help both you and your customer get a clearer |
| picture of how the final application will look to an end-user. Finally, you break down |
| the customer requirements into a set of implementation tasks, and structure your application |
| so that the responsibilities and interactions among functional components are clearly |
| defined.</p> |
| |
| <p>This tutorial unit discusses the MVC (Model-View-Controller) design pattern. After |
| investigating the benefits that this pattern offers, you set about mapping JSP, Servlet, |
| and other technologies to the MVC architecture, and draft a diagram that illustrates |
| the components of the application in terms of MVC.</p> |
| |
| <p>This unit makes various references to <a href="http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/" target="_blank">Designing |
| Enterprise Applications with the J2EE Platform, Second Edition</a>. This book contains |
| guidelines promoted by <a href="http://java.sun.com/reference/blueprints/index.jsp" target="_blank">Java |
| BluePrints</a>.</p> |
| |
| <p>Although this tutorial unit does not require use of the NetBeans IDE, it is essential |
| because it lays the groundwork for tasks that will be covered in the following units.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans E-commerce |
| Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left"> |
| |
| |
| <br> |
| <h2 id="scenario">The Scenario</h2> |
| |
| <p>This tutorial is based on the following scenario. Although this is a fictitious |
| scenario, it demonstrates how the software you are about to develop can be applied |
| to real-world business needs. It also serves as a platform from which you can derive |
| customer requirements. Customer requirements should be established as clearly as possible |
| before any design or implementation begins.</p> |
| |
| <div class="indent"> |
| <div class="feedback-box margin-around float-left" style="width:700px"> |
| |
| <h4>The Scenario</h4> |
| |
| <p>A small grocery store, the Affable Bean, collaborates with several local farms to |
| supply a community with organic produce and foods. Due to a long-standing customer |
| base and increasing affluence to the area, the store has decided to investigate |
| the possibility of providing an online delivery service to customers. A recent |
| survey has indicated that 90% of its regular clientele has continuous Internet |
| access, and 65% percent would be interested in using this service.</p> |
| |
| <p>The grocery store staff have asked you, the Java web developer, to create a website |
| that will enable their customers to shop online. They have also asked that you |
| create an administration console alongside the website, which will allow staff |
| members to keep track of orders.</p> |
| |
| <p>The store's location is in Prague, in the Czech Republic. Because regular clientele |
| are both English and Czech-speaking, staff have requested that the website support |
| both languages.</p> |
| |
| <p>The grocery store has already purchased a domain and web hosting plan that provides |
| a Java EE 6-compliant server and MySQL database server. Staff have indicated that |
| one technically-oriented member is able to deploy the application to the production |
| server once it is ready.</p> |
| </div> |
| </div> |
| |
| <br style="clear:both"> |
| |
| |
| <br> |
| <h2 id="requirements">Gathering Customer Requirements</h2> |
| |
| <p>The initial phase of any project involves gathering information before making any design |
| or implementation decisions. In its most common form, this involves direct and frequent |
| communication with a customer. Based on the provided scenario, the Affable Bean staff |
| have communicated to you that the application you are to create should fulfill the |
| following requirements:</p> |
| |
| <ol> |
| <li>An online representation of the products that are sold in the physical store. |
| There are four categories (dairy, meats, bakery, fruit & veg), and four products |
| for each category, which online shoppers can browse. Details are provided for each |
| product (i.e., name, image, description, price).</li> |
| |
| <li>Shopping cart functionality, which includes the ability to: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li>add items to a virtual shopping cart.</li> |
| <li>remove items from the shopping cart.</li> |
| <li>update item quantities in the shopping cart.</li> |
| <li>view a summary of all items and quantities in the shopping cart.</li> |
| <li>place an order and make payment through a secure checkout process.</li> |
| </ul></li> |
| |
| <li>An administration console, enabling staff to view customer orders.</li> |
| |
| <li>Security, in the form of protecting sensitive customer data while it is |
| transferred over the Internet, and preventing unauthorized access to the |
| administration console.</li> |
| |
| <li>Language support for both English and Czech. (Website only)</li> |
| </ol> |
| |
| <p>The company staff are able to provide you with product and category images, |
| descriptions and price details, as well as any website graphics that are to |
| be used. The staff are also able to provide all text and language translations |
| for the website.</p> |
| |
| <p class="tips">There are many practices and methods devoted to software |
| development management. <a href="http://en.wikipedia.org/wiki/Agile_software_development" target="_blank">Agile |
| software development</a> is one methodology that encourages frequent customer |
| inspection, and places importance on adaptation during the development cycle. |
| Although this is outside the scope of this tutorial, each tutorial unit concludes |
| with a functional piece of software that could be presented to a customer for |
| further communication and feedback.</p> |
| |
| |
| <br> |
| <h2 id="mockups">Preparing Mockups</h2> |
| |
| <p>After gathering customer requirements, you work with the Affable Bean staff |
| to gain a clearer picture of how they expect the website to look and behave. |
| You create a use-case that describes how the application will be used and |
| encapsulates its behavior:</p> |
| |
| <div class="indent"> |
| <div class="feedback-box margin-around float-left" style="width:700px"> |
| |
| <h3 id="useCase">Use-Case</h3> |
| |
| <p>Customer visits the welcome page and selects a product category. Customer browses |
| products within the selected category page, then adds a product to his or her |
| shopping cart. Customer continues shopping and selects a different category. |
| Customer adds several products from this category to shopping cart. Customer |
| selects 'view cart' option and updates quantities for cart products in the cart |
| page. Customer verifies shopping cart contents and proceeds to checkout. In the |
| checkout page, customer views the cost of the order and other information, fills |
| in personal data, then submits his or her details. The order is processed and |
| customer is taken to a confirmation page. The confirmation page provides a unique |
| reference number for tracking the customer order, as well as a summary of the order.</p> |
| </div> |
| </div> |
| |
| <br style="clear:both"> |
| <br> |
| |
| <p>You also begin creating mockups. There are numerous ways to go about this task. For |
| example, you could use storyboard software, or create a set of wireframes to relay |
| the relationships between pages. Another common method is known as |
| <a href="http://en.wikipedia.org/wiki/Paper_prototyping" target="_blank">paper |
| prototyping</a>, where you collaborate with the customer by sketching ideas on paper.</p> |
| |
| <p>In this scenario, we've produced <em>mockups</em> of the primary pages the user expects |
| see when navigating through the website. When we later discuss the MVC design pattern, |
| you'll note that these pages map to the <em>views</em> used by the application.</p> |
| |
| <table> |
| <tr style="vertical-align:top"> |
| <td style="width:420px; padding:10px"> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/design/mockup-index.png" |
| rel="lytebox" title="Mockup of welcome page" id="index"> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/design/mockup-index-small.png" |
| style="width:400px" alt="Mockup of welcome page" class="b-all margin-around"></a> |
| </td> |
| |
| <td style="width:350px; padding:10px"> |
| <br> |
| <h4>welcome page</h4> |
| |
| <p>The welcome page is the website's home page, and entry point for the |
| application. It introduces the business and service to the user, and |
| enables the user to navigate to any of the four product categories.</p> |
| </td> |
| </tr> |
| |
| <tr style="vertical-align:top"> |
| <td style="width:420px; padding:10px"> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/design/mockup-category.png" |
| rel="lytebox" title="Mockup of category page" id="category"> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/design/mockup-category-small.png" |
| alt="Mockup of category page" class="b-all margin-around"></a> |
| </td> |
| |
| <td style="width:350px; padding:10px"> |
| <br> |
| <h4>category page</h4> |
| |
| <p>The category page provides a listing of all products within the |
| selected category. From this page, a user is able to view all |
| product information, and add any of the listed products to his |
| or her shopping cart. A user can also navigate to any of the |
| provided categories.</p> |
| </td> |
| </tr> |
| |
| <tr style="vertical-align:top"> |
| <td style="width:420px; padding:10px"> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/design/mockup-cart.png" |
| rel="lytebox" title="Mockup of cart page" id="cart"> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/design/mockup-cart-small.png" |
| alt="Mockup of cart page" class="b-all margin-around"></a> |
| </td> |
| |
| <td style="width:350px; padding:10px"> |
| <br> |
| <h4>cart page</h4> |
| |
| <p>The cart page lists all items held in the user's shopping cart. |
| It displays product details for each item, and tallies the subtotal |
| for the items in the cart. From this page, a user can:</p> |
| |
| <ul> |
| <li>Clear all items in his or her cart |
| <br> |
| (Clicking 'clear cart' causes the 'proceed to checkout' buttons |
| and shopping cart table to disappear.)</li> |
| |
| <li>Update the quantity for any listed item |
| <br> |
| (The price and quantity are updated; the subtotal is recalculated. |
| If user sets quantity to '0', the product table row is removed.)</li> |
| |
| <li>Return to the previous category by clicking 'continue shopping'</li> |
| |
| <li>Proceed to checkout</li> |
| </ul> |
| </td> |
| </tr> |
| |
| <tr style="vertical-align:top"> |
| <td style="width:420px; padding:10px"> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/design/mockup-checkout.png" |
| rel="lytebox" title="Mockup of checkout page" id="checkout"> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/design/mockup-checkout-small.png" |
| alt="Mockup of checkout page" class="b-all margin-around"></a> |
| </td> |
| |
| <td style="width:350px; padding:10px"> |
| <br> |
| <h4>checkout page</h4> |
| |
| <p>The checkout page collects information from the customer using a |
| form. This page also displays purchase conditions, and summarizes |
| the order by providing calculations for the total cost.</p> |
| |
| <p>The user is able to send personal details over a secure channel.</p> |
| </td> |
| </tr> |
| |
| <tr style="vertical-align:top"> |
| <td style="width:420px; padding:10px"> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/design/mockup-confirmation.png" |
| rel="lytebox" title="Mockup of confirmation page" id="confirmation"> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/design/mockup-confirmation-small.png" |
| alt="Mockup of confirmation page" class="b-all margin-around"></a> |
| </td> |
| |
| <td style="width:350px; padding:10px"> |
| <br> |
| <h4>confirmation page</h4> |
| |
| <p>The confirmation page returns a message to the customer confirming |
| that the order was successfully recorded. An order reference number |
| is provided to the customer, as well as a summary listing order |
| details.</p> |
| |
| <p>Order summary and customer personal details are returned over a secure channel.</p> |
| </td> |
| </tr> |
| </table> |
| |
| <p>Also, you agree with staff on the following rules, which apply to multiple pages:</p> |
| |
| <ul> |
| <li>The user is able to proceed to checkout from any page, provided that: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li>The shopping cart is not empty</li> |
| <li>The user is not already on the checkout page</li> |
| <li>The user has not already checked out (i.e., is on the confirmation page)</li> |
| </ul></li> |
| |
| <li>From all pages, the user is able to: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li>View the status of his or her shopping cart (if it is not empty)</li> |
| <li>Return to the welcome page by clicking the logo image</li> |
| </ul></li> |
| |
| <li>The user is able to select the language (English or Czech) to view the page |
| in for all pages except the confirmation page.</li> |
| </ul> |
| |
| <p class="notes"><strong>Note:</strong> Although not presented here, you would equally |
| need to work with the client to produce use-cases and mockups, and establish rules |
| for the administration console. The NetBeans E-commerce Tutorial focuses on developing |
| the store front (i.e., the website). However, Unit 11, <a href="#security">Securing the |
| Application</a> demonstrates how to create a login mechanism to access the administration |
| console. Also, you can examine the provided implementation of the administration console by |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_complete.zip">downloading |
| the completed application</a>.</p> |
| |
| <div class="indent"> |
| <h3 id="business">The Business Process Flow</h3> |
| |
| <p>To help consolidate the relationships between the proposed mockups and better |
| illustrate the functionality that each page should provide, you prepare a |
| diagram that demonstrates the process flow of the application.</p> |
| |
| <p>The diagram displays the visual and functional components of each page, and |
| highlights the primary actions available to the user in order to navigate |
| through the site to complete a purchase.</p> |
| |
| <div class="indent"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/design/process-flow.png" |
| class="margin-around" alt="Process-flow diagram of the AffableBean application" |
| title="The process flow of the AffableBean application" |
| id="processFlowDiagram"> |
| </div> |
| </div> |
| |
| |
| <br> |
| <h2 id="architecture">Determining the Architecture</h2> |
| |
| <p>Before you start coding, let's examine the ways in which you can architect |
| the project. Specifically, you need to outline the responsibilities among |
| functional components, and determine how they will interact with each other.</p> |
| |
| <p>When you work with JSP technologies, you can code all of your business logic |
| into JSP pages using scriptlets. Scriptlets are snippets of Java code enclosed |
| in <code><% %></code> tags. As you may already be aware, JSP pages are |
| compiled into servlets before they are run, so Java code is perfectly valid in |
| JSP pages. However, there are several reasons why this practice should be avoided, |
| especially when working in large projects. Some reasons are outlined in |
| <a href="http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/" target="_blank">Designing |
| Enterprise Applications with the J2EE Platform, Second Edition</a> as |
| follows:<sup><a href="#footnote1Design" id="1Design" style="text-decoration:none">[1]</a></sup></p> |
| |
| <ul> |
| <li><strong>Scriptlet code is not reusable: </strong>Scriptlet code appears |
| in exactly one place: the JSP page that defines it. If the same logic is |
| needed elsewhere, it must be either included (decreasing readability) or |
| copied and pasted into the new context.</li> |
| |
| <li><strong>Scriptlets mix logic with presentation: </strong>Scriptlets are |
| islands of program code in a sea of presentation code. Changing either |
| requires some understanding of what the other is doing to avoid breaking |
| the relationship between the two. Scriptlets can easily confuse the intent |
| of a JSP page by expressing program logic within the presentation.</li> |
| |
| <li><strong>Scriptlets break developer role separation:</strong> Because scriptlets |
| mingle programming and Web content, Web page designers need to know either |
| how to program or which parts of their pages to avoid modifying.</li> |
| |
| <li><strong>Scriptlets make JSP pages difficult to read and to maintain: </strong> |
| JSP pages with scriptlets mix structured tags with JSP page delimiters and |
| Java language code.</li> |
| |
| <li><strong>Scriptlet code is difficult to test: </strong>Unit testing of scriptlet |
| code is virtually impossible. Because scriptlets are embedded in JSP pages, |
| the only way to execute them is to execute the page and test the |
| results.</li> |
| </ul> |
| |
| <p>There are various design patterns already in existence which provide considerable |
| benefits when applied. One such pattern is the MVC (Model-View-Controller) |
| paradigm, which divides your application into three interoperable |
| components:<sup><a href="#footnote2Design" id="2Design" style="text-decoration:none">[2]</a></sup></p> |
| |
| <ul> |
| <li><strong>Model:</strong> Represents the business data and any business logic |
| that govern access to and modification of the data. The model notifies views |
| when it changes and lets the view query the model about its state. It also |
| lets the controller access application functionality encapsulated by the model.</li> |
| |
| <li><strong>View:</strong> The view renders the contents of a model. It gets data |
| from the model and specifies how that data should be presented. It updates |
| data presentation when the model changes. A view also forwards user input to |
| a controller.</li> |
| |
| <li><strong>Controller:</strong> The controller defines application behavior. It |
| dispatches user requests and selects views for presentation. It interprets user |
| inputs and maps them into actions to be performed by the model. In a web |
| application, user inputs are HTTP GET and POST requests. A controller selects |
| the next view to display based on the user interactions and the outcome of the |
| model operations.</li> |
| </ul> |
| |
| <div class="indent"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/design/mvc-model.png" |
| class="margin-around" alt="Diagram of the MVC pattern" |
| title="The Model View Controller pattern" |
| id="mvcModel"> |
| </div> |
| <br> |
| |
| <p>Adhering to the MVC design pattern provides you with numerous benefits:</p> |
| |
| <ul> |
| <li><strong>Separation of design concerns:</strong> Because of the decoupling |
| of presentation, control, and data persistence and behavior, the application |
| becomes more flexible; modifications to one component have minimal impact on |
| other components. You can, for example, create new views without needing to |
| rewrite the model.</li> |
| |
| <li><strong>More easily maintainable and extensible:</strong> Good structure can |
| reduce code complexity. As such, code duplication is minimized.</li> |
| |
| <li><strong>Promotes division of labor:</strong> Developers with different skill |
| sets are able to focus on their core skills and collaborate through clearly |
| defined interfaces.</li> |
| </ul> |
| |
| <p class="notes"><strong>Note:</strong> When JSP technology was first introduced in |
| 1999, the early specifications included a description of two model architectures: |
| Model 1 and Model 2. Model 1 involves implementing business logic directly within |
| JSP pages, whereas Model 2 applies the MVC pattern. For more information on Model |
| 1 and Model 2 architectures, see |
| <a href="http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/web-tier/web-tier5.html#1078527" target="_blank">Designing |
| Enterprise Applications with the J2EE Platform, section 4.4.1: Structuring the Web |
| Tier</a>.</p> |
| |
| <p>You can apply the MVC pattern to the application that you develop for the Affable |
| Bean company. You can use a servlet as a <em>controller</em> to handle incoming |
| requests. The pages from the <a href="#processFlowDiagram">business process flow |
| diagram</a> can be mapped to <em>views</em>. Finally, the business data, which will |
| be maintained in a database, can be accessed and modified in the application using |
| <a href="http://java.sun.com/products/ejb/" target="_blank">EJB</a> session beans with |
| <a href="http://java.sun.com/javaee/technologies/persistence.jsp" target="_blank">JPA</a> |
| entity classes. These components represent the <em>model</em>.</p> |
| |
| <div class="indent" id="mvcDiagram"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/design/mvc-diagram.png" |
| class="margin-around" alt="MVC diagram of the AffableBean application" |
| title="MVC diagram of the AffableBean application"> |
| </div> |
| <br> |
| |
| <br> |
| <h2 id="planning">Planning the Project</h2> |
| |
| <p>In order to plan the project, you need to extrapolate functional tasks from the customer |
| requirements. The tasks that we produce will structure the implementation plan for the |
| project, and form the outline for tutorial units that follow. In practice, the more capable |
| you are of identifying tasks and the work they entail, the better you'll be able to stick |
| to the schedule that you and your customer agree upon. Therefore, begin with a high-level |
| task list, then try to drill down from these tasks dividing each task into multiple sub-tasks, |
| and possibly dividing sub-tasks further until each list item represents a single unit of work.</p> |
| |
| <ul id="collapsableList"> |
| <li>Set up the development environment |
| |
| <ul> |
| <li>Register the development server in the IDE</li> |
| <li>Create a web project in the IDE</li> |
| <li>Run the web project from the IDE (test compilation, deployment, run |
| capabilities, and ensure interoperability between IDE, server and browser)</li> |
| <li>Register the database server in the IDE</li> |
| <li>Establish a connection to the database server from the IDE</li> |
| <li>Create a database instance on the database server</li> |
| </ul> |
| </li> |
| |
| <li>Prepare the data model for the application |
| |
| <ul> |
| <li>Create an entity-relationship diagram (use a visual database design tool) |
| |
| <ul> |
| <li>Identify objects</li> |
| <li>Create a schema</li> |
| <li>Create entities</li> |
| <li>Add entity properties</li> |
| <li>Identify relationships between entities |
| |
| <ul> |
| <li>One-to-Many relationships</li> |
| <li>Many-to-Many relationships</li> |
| </ul> |
| </li> |
| </ul></li> |
| |
| <li>Forward-engineer the entity-relationship diagram into an SQL script</li> |
| |
| <li>Run the script on the database server to generate the schema</li> |
| </ul> |
| </li> |
| |
| <li>Create front-end project files |
| |
| <ul> |
| <li>Stylesheet</li> |
| <li>Placeholders for JSP pages (requires implementing HTML and CSS |
| content to get pages to display like mockups) |
| |
| <ul> |
| <li>welcome page</li> |
| <li>category page</li> |
| <li>cart page</li> |
| <li>checkout page</li> |
| <li>confirmation page</li> |
| </ul> |
| </li> |
| </ul></li> |
| |
| <li>Organize the application front-end |
| |
| <ul> |
| <li>Place JSP pages in the application's <code>WEB-INF</code> directory</li> |
| <li>Create page header and footer</li> |
| <li>Remove instances of code duplication (header and footer code from JSP pages)</li> |
| <li>Register header and footer includes with the web deployment descriptor</li> |
| </ul></li> |
| |
| <li>Create a controller servlet |
| |
| <ul> |
| <li>Create mappings for views in deployment descriptor</li> |
| <li>Create skeleton code in servlet to handle client requests</li> |
| </ul></li> |
| |
| <li>Connect the application to the database |
| |
| <ul> |
| <li>Add sample data to the database</li> |
| <li>Create data source and connection pool on server</li> |
| <li>Test data source (ping connection pool)</li> |
| <li>Ensure that views can access data from the database |
| |
| <ul> |
| <li>Add database driver JAR to server</li> |
| <li>Create a resource reference to the data source in the application</li> |
| <li>Query the database from a JSP page</li> |
| </ul></li> |
| |
| <li>Set any necessary application-wide parameters</li> |
| <li>Code database-access and conditional logic in views that do not require user session (welcome, category)</li> |
| |
| </ul></li> |
| |
| |
| <li>Develop the business logic |
| |
| <ul> |
| <li>Set up the model |
| <ul> |
| <li>Create JPA entity classes from database tables</li> |
| <li>Create and configure persistence unit</li> |
| <li>Create EJB stateless bean facades for entity classes</li> |
| </ul></li> |
| |
| <li>Integrate EJB model with views |
| |
| <ul> |
| <li>Integrate EJB facades in controller servlet</li> |
| <li>Modify views to use data from scoped variables (instead of any JSTL <code><sql></code> queries)</li> |
| </ul></li> |
| |
| <li>Create shopping cart functionality |
| |
| <ul> |
| <li>Create Java classes to hold temporary data (<code>ShoppingCart</code>, <code>ShoppingCartItem</code>)</li> |
| <li>Integrate code for <code>HttpSession</code> object into controller servlet</li> |
| <li>Add session-related actions to controller servlet</li> |
| <li>Create shopping cart widget in page header</li> |
| <li>Integrate session-related data into views (cart, checkout)</li> |
| <li>Apply JSTL <code><c:url></code> tags to enable url-rewriting in the event that user has disabled cookies</li> |
| <li>Configure session time-out in web deployment descriptor</li> |
| <li>Add logic to controller servlet handle requests in the event of session time-out</li> |
| </ul></li> |
| |
| <li>Integrate transactional logic |
| |
| <ul> |
| <li>Create code to extract and validate user data from checkout form</li> |
| <li>Create an EJB stateless session bean to handle inserting orders and customers into database</li> |
| <li>Implement logic to query the database on newly-created orders</li> |
| <li>Implement order and customer details display in confirmation page</li> |
| </ul> |
| </li> |
| </ul></li> |
| |
| <li>Add language support |
| |
| <ul> |
| <li>Create a properties file containing messages for all text in |
| the application |
| <ul> |
| <li>default language (English)</li> |
| <li>English</li> |
| <li>Czech</li> |
| </ul></li> |
| |
| <li>Register a localization context parameter in deployment descriptor</li> |
| |
| <li>Add logic to view that sets page language based on language value |
| saved in user's session</li> |
| |
| <li>Apply <code><fmt:message></code> tags to all text contained in view</li> |
| |
| <li>Factor out English description from database (<em>optional</em>), use resource bundles instead</li> |
| </ul></li> |
| |
| <li>Create administration console |
| |
| <ul> |
| <li>Create new artifacts |
| |
| <ul> |
| <li>Views |
| |
| <ul> |
| <li>login</li> |
| <li>welcome</li> |
| <li>error</li> |
| </ul></li> |
| |
| <li>Controller servlet</li> |
| </ul></li> |
| |
| <li>Create login functionality |
| |
| <ul> |
| <li>Create interface</li> |
| <li>Add actions to controller servlet</li> |
| <li>Configure login functionality in deployment descriptor</li> |
| </ul></li> |
| |
| <li>Implement admin functionality (in welcome page) |
| |
| <ul> |
| <li>For viewing order details</li> |
| <li>For viewing customer details</li> |
| </ul> |
| </li> |
| </ul></li> |
| |
| <li>Secure the application |
| |
| <ul> |
| <li>Configure SSL connection for checkout, confirmation views, and administration console |
| |
| <ul> |
| <li>Enable SSL on server</li> |
| <li>Register security settings in deployment descriptor</li> |
| </ul></li> |
| |
| <li>Create user roles and permissions for administration console |
| |
| <ul> |
| <li>Create security roles on server</li> |
| <li>Declare security roles, constraints in deployment descriptor</li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| </ul> |
| |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Designing the Application">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <h2 id="seeAlsoDesign">See Also</h2> |
| |
| <div class="indent"> |
| <h3>Online Resources</h3> |
| |
| <ul> |
| <li><a href="http://java.sun.com/reference/blueprints/index.jsp" target="_blank">Java BluePrints</a></li> |
| <li><a href="http://java.sun.com/blueprints/patterns/catalog.html" target="_blank">J2EE Patterns Catalog</a></li> |
| <li><a href="http://bpcatalog.dev.java.net/nonav/solutions.html" target="_blank">Java BluePrints Solutions Catalog</a></li> |
| <li><a href="http://java.sun.com/blueprints/patterns/MVC-detailed.html" target="_blank">Java BluePrints: Model-View-Controller</a></li> |
| <li><a href="http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/web-tier/web-tier5.html" target="_blank">Web-Tier Application Framework Design</a></li> |
| <li><a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/tutorial/doc/bnadr.html" target="_blank">The Java EE 5 Tutorial - Chapter 3: Getting Started with Web Applications</a></li> |
| </ul> |
| |
| <h3>Technical Articles</h3> |
| |
| <ul> |
| <li><a href="http://java.sun.com/developer/technicalArticles/javaserverpages/servlets_jsp/" target="_blank">Servlets and JSP Pages Best Practices</a></li> |
| <li><a href="http://java.sun.com/developer/technicalArticles/J2EE/despat/" target="_blank">Design Patterns for Building Flexible and Maintainable J2EE Applications</a></li> |
| </ul> |
| |
| <h3>Books</h3> |
| |
| <ul> |
| <li><a href="http://volume1.coreservlets.com/" target="_blank">Core Servlets and JavaServer Pages, Volume 1: |
| Core Technologies, 2nd Edition</a></li> |
| <li><a href="http://volume2.coreservlets.com/" target="_blank">Core Servlets and JavaServer Pages, Volume 2: |
| Advanced Technologies, 2nd Edition</a></li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2>References</h2> |
| |
| <ol> |
| <li id="footnote1Design"><a href="#1Design" style="text-decoration:none">^</a> For a more extensive |
| list, see <a href="http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/web-tier/web-tier3.html#1097966" target="_blank">Designing |
| Enterprise Applications with the J2EE Platform, section 4.2.6.8: Using Custom Tags |
| to Avoid Scriptlets</a>.</li> |
| |
| <li id="footnote2Design"><a href="#2Design" style="text-decoration:none">^</a> For more information |
| on the MVC pattern, see |
| <a href="http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/app-arch/app-arch2.html#1105854" target="_blank">Designing |
| Enterprise Applications with the J2EE Platform, section 11.1.1: Model-View-Controller |
| Architecture</a>.</li> |
| </ol> |
| |
| <script type="text/javascript"> |
| <!-- |
| compactMenu('collapsableList', true, '± '); |
| --> |
| </script> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="setup-dev-environ">The NetBeans E-commerce Tutorial - Setting up the Development Environment</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><strong>Setting up the Development Environment</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#create">Creating a Web Project</a></li> |
| <li><a href="#run">Running the Web Project</a></li> |
| <li><a href="#communicate">Communicating with the Database Server</a></li> |
| <li><a href="#seeAlsoSetupDevEnviron">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>The following steps describe how to set up your development environment. In the process, |
| you'll learn about some of the primary windows of the IDE and understand how the IDE |
| uses an <a href="http://ant.apache.org/" target="_blank">Ant</a> build script to perform |
| common actions on your project. By the end of this tutorial unit, you'll have created |
| a web application project, and confirmed that you can successfully build the project, |
| deploy it to your development server, and run it from the IDE.</p> |
| |
| <p>You also learn how to connect the IDE to a MySQL database server, create database |
| instances, and connect to database instances from the IDE's Services window. In |
| this unit, you create a new database named <code>affablebean</code>, which you |
| will use throughout the tutorial.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans |
| E-commerce Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#glassFishSetupDevEnviron">GlassFish server</a></td> |
| <td class="tbltd1">v3 or Open Source Edition 3.0.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL database server</a></td> |
| <td class="tbltd1">version 5.1</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p class="notes"><strong>Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which are |
| required for the application you build in this tutorial.</li> |
| |
| <li id="glassFishSetupDevEnviron">The NetBeans IDE Java Bundle also includes the GlassFish server, |
| which you require for this tutorial. You could |
| <a href="http://glassfish.dev.java.net/public/downloadsindex.html" target="_blank">download |
| the GlassFish server independently</a>, but the version provided with the |
| NetBeans download has the added benefit of being automatically registered with |
| the IDE.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="create">Creating a Web Project</h2> |
| |
| <ol> |
| <li>Start the NetBeans IDE. If you are running the IDE for the first time, you |
| will see the IDE's Start Page. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/ide-start-page.png" |
| class="margin-around b-all" alt="NetBeans IDE Start Page" title="The NetBeans IDE Start Page"></li> |
| |
| <li>Click the New Project ( <img src="../../../../images_www/articles/73/javaee/ecommerce/common/new-project-btn.png" |
| alt="New Project icon"> ) button (Ctrl-Shift-N; ⌘-Shift-N on Mac) to create |
| a new Java web project. The New Project wizard opens to guide you through the |
| process. Under Categories choose Java Web, then under Projects choose Web |
| Application. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/new-project-wzd.png" |
| class="margin-around b-all" alt="New Project wizard" width="688px" |
| title="Create a project using the New Project wizard"></li> |
| |
| <li>Click Next.</li> |
| |
| <li>In Step 2: Name and Location, name the project <code>AffableBean</code>. In |
| this step, you can also designate the location on your computer where the project |
| will reside. By default, the IDE creates a <code>NetBeansProjects</code> folder |
| in your home directory. If you'd like to change the location, enter the path in |
| the Project Location text field.</li> |
| |
| <li>Click Next.</li> |
| |
| <li>In Step 3: Server and Settings, specify GlassFish v3 as the server to which |
| your project will be deployed during development. Since you've included GlassFish |
| v3 in your NetBeans installation, you'll see that GlassFish v3 is listed in the |
| Server drop-down field. |
| |
| <br><br> |
| <p class="tips">If you wanted to deploy to a server that isn't yet registered |
| with the IDE, you would click the Add button, and step through the Add Server |
| Instance wizard. You can view all servers registered with the IDE from the |
| Servers window (Choose Tools > Servers from the main menu).</p></li> |
| |
| <li>For Java EE Version, select Java EE 6 Web. |
| |
| <br><br> |
| The application that you create makes use of various Java EE 6 features, namely |
| servlet annotations (new in the <a href="http://jcp.org/en/jsr/summary?id=315" target="_blank">Servlet |
| 3.0 Specification</a>), and EJBs used directly in servlet containers (new in the |
| <a href="http://jcp.org/en/jsr/summary?id=318" target="_blank">EJB 3.1 Specification</a>). |
| Both Servlet 3.0 and EJB 3.1 are part of the Java EE 6 platform, therefore you |
| require an EE-6 compliant server such as GlassFish v3 to work through this tutorial. |
| For more information, see <a href="entity-session.html#specification">About Specifications |
| and Implementations</a>.</li> |
| |
| <li>Make sure that the 'Enable Contexts and Dependency Injection' option is deselected. |
| This option is specific to the Contexts and Dependency Injection (CDI) technology, |
| specified by <a href="http://jcp.org/en/jsr/detail?id=299" target="_blank">JSR-299</a>, |
| and is not used in this tutorial. For more information, see <a href="../cdi-intro.html">Getting |
| Started with Contexts and Dependency Injection and JSF 2.0</a>. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/new-project-wzd2.png" |
| class="margin-around b-all" alt="New Web Application wizard, Step 3: Server and Settings" width="688px" |
| title="Specify development server, EE version, and whether to include CDI support"> |
| |
| <br><br> |
| Note that by default the context path for the application is the name of the |
| project. This is the path at which your application can be accessed after it |
| is deployed to the server. For example, GlassFish uses 8080 as its default port |
| number, so during development you'll be able to access the project in a browser |
| window from: |
| |
| <pre class="examplecode">http://localhost:8080/AffableBean/</pre></li> |
| |
| <li>Click Finish. The IDE generates a skeleton project named <code>AffableBean</code> |
| that adheres to the <a href="http://java.sun.com/blueprints/code/projectconventions.html#99632" target="_blank">J2EE |
| Blueprints conventions for web application structure</a>. |
| |
| The IDE displays various windows in its default layout. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/ide-default-layout.png" |
| rel="lytebox" title="Default layout for a Java Web project"> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/ide-default-layout.png" |
| alt="NetBeans IDE - default layout" class="b-all margin-around" width="688px"></a></li> |
| |
| <li>Examine the IDE's default layout. Here's a brief overview of the displayed windows and tabs: |
| |
| <ul style="margin: 5px 0 0 -1.5em"> |
| <li><strong>The Editor:</strong> The editor (Ctrl-0; ⌘-0 on Mac) is the |
| central component of the IDE, and is likely where you'll spend most of your |
| time. The editor automatically adapts to the language you are working in, |
| providing documentation support, code-completion, hints and error messages |
| specific to the technology you are coding in.</li> |
| |
| <li><strong>Projects window:</strong> The Projects window (Ctrl-1; ⌘-1 on Mac) |
| is the entry point to your project sources. It provides a <em>logical view</em> |
| of important project contents, and groups files together based on their function |
| (e.g., <code>Configuration Files</code>). When right-clicking file nodes within |
| the Projects window, you can call actions common to your development tasks (i.e., |
| <code>Build</code>, <code>Clean</code>, <code>Deploy</code>, <code>Run</code>).</li> |
| |
| <li><strong>Files window:</strong> The Files window (Ctrl-2; ⌘-2 on Mac) |
| provides a directory-based view of your project. That is, it enables you to |
| view the structure of your project, as it exists in your computer's file system. |
| From this window, you can view all files pertaining to your project, including |
| the Ant build script, (<code>build.xml</code>), and files required by the IDE |
| to handle the project (contained in the <code>nbproject</code> folder). If you've |
| run your project, you can see the location of compiled Java files (<code>build</code> |
| folder). If you've explicitly built your project (by choosing Build, or Clean and |
| Build, from the project node's right-click menu in the Projects window), you can |
| view the project's distributable WAR file (contained in the <code>dist</code> |
| folder).</li> |
| |
| <li><strong>Navigator:</strong> The Navigator (Ctrl-7; ⌘-7 on Mac) provides |
| a structural overview of the file opened in the editor. For example, if an HTML |
| web page is displayed, the Navigator lists tag nodes in a way that corresponds to |
| the page's Document Object Model (DOM). If a Java class is opened in the editor, |
| the Navigator displays the properties and methods pertaining to that class. You |
| can use the Navigator to navigate to items within the editor. For example, when |
| you double-click a node in the Navigator, your cursor is taken directly to that |
| element in the editor.</li> |
| |
| <li><strong>Tasks window:</strong> The Tasks window (Ctrl-6; ⌘-6 on Mac) |
| automatically scans your code and lists lines with compile errors, quick fixes, |
| and style warnings. For Java classes, it also lists commented lines containing |
| words such as '<code>TODO</code>' or '<code>FIXME</code>'.</li> |
| |
| <li><strong>Services window:</strong> The Services window (Ctrl-5; ⌘-5 on Mac) |
| provides an interface for managing servers, web services, databases and |
| database connections, as well as other services relating to team development.</li> |
| |
| <li><strong>Output window:</strong> <em>(Not displayed)</em> The Output window (Ctrl-4; |
| ⌘-4 on Mac) automatically displays when you call an action that invokes a |
| service, generally from an outside resource such as a server, and can mirror |
| server log files. With web projects, it also enables you to view information |
| related to Ant tasks (e.g., <code>Build</code>, <code>Clean and Build</code>, |
| <code>Clean</code>).</li> |
| |
| <li><strong>Palette:</strong> <em>(Not displayed)</em> The Palette (Ctrl-Shift-8; |
| ⌘-Shift-8 on Mac) provides various handy code snippets that you can drag |
| and drop into the editor. Many of the snippets included in the Palette are also |
| accessible by invoking code completion in the editor, as will later be demonstrated.</li> |
| </ul> |
| |
| <p class="notes"><strong>Note:</strong> All of the IDE's windows can be accessed from the |
| Window menu item.</p> |
| </li> |
| </ol> |
| |
| |
| <h2 id="run">Running the Web Project</h2> |
| |
| <ol> |
| <li>Run the new <code>AffableBean</code> project. In the Projects window, you can do |
| this by right-clicking the project node and choosing Run, otherwise, click the |
| Run Project ( <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project icon"> ) button (F6; fn-F6 on Mac) in the IDE's main toolbar. |
| |
| <br><br> |
| A browser window opens to display the project's welcome page. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/hello-world.png" |
| class="margin-around b-all" alt="Project welcome page displayed in browser" |
| title="Project automatically deploys to server and displays in browser"> |
| |
| <br> |
| So what just happened? When you run a web project, the IDE invokes the <code>run</code> |
| Ant target in your project's build script. You can investigate by opening your project's |
| <code>build.xml</code> file in the editor.</li> |
| |
| <li>Switch to the Files window (Ctrl-2; ⌘-2 on Mac), expand the project node and |
| double-click the <code>build.xml</code> file contained in your project. When the |
| <code>build.xml</code> file opens in the editor, the Navigator lists all Ant targets |
| available to the script. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/navigator-ant-targets.png" |
| class="margin-around b-all" alt="Navigator displaying Ant targets for build.xml" |
| title="The Navigator lists all available Ant targets for the build.xml script"> |
| |
| <p class="tips">Normal Ant targets are displayed using the general target ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/ant-normal-icon.png" |
| alt="Normal Ant target icon"> ) icon. The <em>emphasized</em> Ant target ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/ant-emphasized-icon.png" |
| alt="Emphasized Ant target icon"> ) icon merely indicates that the target |
| includes a description, which is displayed as a tooltip (as shown in the above |
| image). For more information, see |
| <a href="http://www.oracle.com/pls/topic/lookup?ctx=nb8000&id=NBDAG366">Creating Java Projects</a> in <em>Developing Applications with NetBeans IDE</em>.</p></li> |
| |
| <li>Double-click the <code>run</code> target. The <code>build-impl.xml</code> file |
| opens in the editor and displays the target definition. |
| |
| <pre class="examplecode"><target depends="run-deploy,run-display-browser" description="Deploy to server and show in browser." name="run"/></pre> |
| |
| Why did the <code>build-impl.xml</code> file open when we clicked on a target from |
| <code>build.xml</code>? If you switch back to <code>build.xml</code> (press Ctrl-Tab) |
| and examine the file contents, you'll see the following line: |
| |
| <pre class="examplecode"><import file="nbproject/build-impl.xml"/></pre> |
| |
| <p>The project's build script is basically an empty file that imports NetBeans-defined |
| targets from <code>nbproject/build-impl.xml</code>.</p> |
| |
| <p class="alert">You can freely edit your project's standard <code>build.xml</code> |
| script by adding new targets or overriding existing NetBeans-defined targets. |
| However, you should not edit the <code>build-impl.xml</code> file.</p> |
| |
| You can see from the <code>run</code> target's definition that it depends on the |
| following targets: |
| |
| <ul style="margin: 5px 0 0 -1.5em"> |
| <li><code>run-deploy</code></li> |
| <li><code>run-display-browser</code></li> |
| </ul> |
| |
| Both of these targets in turn depend on other targets, which you can examine |
| elsewhere in the <code>build-impl.xml</code> file. But essentially, the following |
| actions take place when the <code>run</code> target is invoked: |
| |
| <ol style="margin: 5px 0 0 -1em"> |
| <li>The project gets compiled.</li> |
| <li>A WAR file is created.</li> |
| <li>The server starts (if it is not already running).</li> |
| <li>The WAR file gets deployed to the designated server.</li> |
| <li>The browser opens to display the server's URL and application's |
| context path.</li> |
| </ol> |
| |
| <p class="tips">Consult the official <a href="http://ant.apache.org/manual/index.html" target="_blank">Ant |
| Manual</a> for more information on using Ant.</p> |
| </li> |
| |
| <li>To generate a distributable WAR file for your project, choose Clean and Build Project |
| (or Clean and Build Main Project) from the IDE's Run menu.</li> |
| |
| <li>In the Files window (Ctrl-2; ⌘-2 on Mac) expand the project |
| node. The <code>dist</code> folder contains the project WAR file. |
| The <code>build</code> folder contains your compiled project. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/files-window.png" |
| class="margin-around b-all" alt="Files window" |
| title="Files window provides a directory-based view of your project"> |
| |
| <p class="notes"><strong>Note:</strong> If you <em>clean</em> the project (In the |
| Projects window, choose Clean from the project node's right-click menu), both |
| of these folders are removed.</p></li> |
| |
| <li>Switch to the Services window (Ctrl-5; ⌘-5 on Mac) and expand the Servers |
| > GlassFish Server 3 > Applications node. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/services-win-deployed-app.png" |
| class="margin-around b-all" alt="Services window - GlassFish v3" |
| title="Services window displays server status, deployed applications and resources"> |
| |
| <p class="notes"><strong>Note:</strong> "GlassFish v3" is the default server name for NetBeans 6.8 users.</p> |
| |
| The green arrow icon on the GlassFish server node ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/gf-server-running-node.png" |
| alt="GlassFish server node in Services window"> ) indicates that the server is |
| running. The Applications folder lists all deployed applications; you can see |
| that the <code>AffableBean</code> application has been successfully deployed.</li> |
| </ol> |
| |
| <p>At this stage, you've created a Java web project in the IDE, and have confirmed |
| that it can be successfully built and deployed to your development server, and |
| opened in a browser when run.</p> |
| |
| |
| <br> |
| <h2 id="communicate">Communicating with the Database Server</h2> |
| |
| <p>Once you've downloaded and installed the MySQL database server, you can connect to |
| it from the IDE. A default installation uses '<code>root</code>' and '' (an empty |
| string) as the user account and password to connect to the database server. However, |
| due to connectivity issues with GlassFish, it is recommended that you use an account |
| with a non-empty password.<sup><a href="#footnote1SetupDevEnviron" id="1SetupDevEnviron" style="text-decoration:none">[1]</a></sup> |
| The following instructions demonstrate how to run the database server |
| and change the password for the <code>root</code> account to '<code>nbuser</code>' |
| from the MySQL command-line. The '<code>root</code>' / '<code>nbuser</code>' |
| combination is used throughout the NetBeans E-commerce Tutorial. With the database |
| server running and properly configured, you register it in the IDE and create a |
| database instance.</p> |
| |
| <p class="notes"><strong>Note:</strong> The command-line instructions below assume that |
| you have added the <code>mysql</code> command to your <code>PATH</code> environment |
| variable. (If you haven't, you'll receive a '<code>mysql: command not found</code>' |
| error when entering <code>mysql</code> commands in your command-line.) |
| |
| <br><br> |
| If you haven't added <code>mysql</code> to your <code>PATH</code>, you can instead |
| call the command by entering the full path to your MySQL installation's <code>bin</code> |
| directory. For example, if the <code>mysql</code> command is located on your computer |
| at <code>/usr/local/mysql/bin</code>, you would enter the following:</p> |
| |
| <pre class="examplecode" style="width: 700px; margin-left:30px">shell> <strong>/usr/local/mysql/bin/</strong>mysql -u root</pre> |
| |
| <p style="margin-left:30px">For more information, see the offical MySQL Reference Manual:</p> |
| |
| <ul> |
| <li><a href="http://dev.mysql.com/doc/refman/5.1/en/general-installation-issues.html" |
| target="_blank">2.1. General Installation Guidance</a></li> |
| |
| <li><a href="http://dev.mysql.com/doc/refman/5.1/en/default-privileges.html" |
| target="_blank">2.13.2. Securing the Initial MySQL Accounts</a></li> |
| |
| <li><a href="http://dev.mysql.com/doc/refman/5.1/en/invoking-programs.html" |
| target="_blank">4.2.1. Invoking MySQL Programs</a></li> |
| |
| <li><a href="http://dev.mysql.com/doc/refman/5.1/en/setting-environment-variables.html" |
| target="_blank">4.2.4. Setting Environment Variables</a></li> |
| </ul> |
| |
| <br> |
| <p>Perform the following steps.</p> |
| |
| <ul> |
| <li><a href="#check">Check if the MySQL Server is Running</a></li> |
| <li><a href="#start">Start the Database Server</a></li> |
| <li><a href="#password">Change the Password</a></li> |
| <li><a href="#register">Register the Server in the IDE</a></li> |
| <li><a href="#database">Create a Database Instance</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="check">Check if the MySQL Server is Running</h3> |
| |
| <p>Before connecting to the MySQL server from the IDE, you need to make sure the |
| server is running. One way to do this is by using the |
| <a href="http://dev.mysql.com/doc/refman/5.1/en/mysqladmin.html" target="_blank"><code>mysqladmin</code></a> |
| client's <code>ping</code> command.</p> |
| |
| <ol> |
| <li>Open a command-line prompt and type in the following: |
| |
| <pre class="examplecode" style="width:660px">shell> mysqladmin ping</pre> |
| |
| If the server is running, you will see output similar to the following: |
| |
| <pre class="examplecode" style="width:660px">mysqld is alive</pre> |
| |
| If the server is not running, you'll see output similar to the following: |
| |
| <pre class="examplecode" style="width:660px"> |
| mysqladmin: connect to server at 'localhost' failed |
| error: 'Can't connect to local MySQL server through socket '/tmp/mysql.sock' |
| Check that mysqld is running and that the socket: '/tmp/mysql.sock' exists!</pre> |
| </li> |
| </ol> |
| |
| |
| <h3 id="start">Start the Database Server</h3> |
| |
| <p>In the event that your MySQL server is not running, you can start it from |
| the command-line. See <a href="http://dev.mysql.com/doc/refman/5.1/en/automatic-start.html" |
| target="_blank">2.13.1.2. Starting and Stopping MySQL Automatically</a> for a brief, |
| cross-platform overview. The following steps provide general guidance depending on your |
| operating system.</p> |
| |
| <h4>Unix-like systems:</h4> |
| |
| <p>For Unix-like systems, it is recommended to start the MySQL server by invoking |
| <a href="http://dev.mysql.com/doc/mysql-startstop-excerpt/5.1/en/mysqld-safe.html" target="_blank"><code>mysqld_safe</code></a>.</p> |
| |
| <ol> |
| <li>Open a command-line prompt and run the <code>mysqld_safe</code> command: |
| |
| <pre class="examplecode" style="width:660px">shell> sudo ./mysqld_safe</pre> |
| |
| You will see output similar to the following: |
| |
| <pre class="examplecode" style="width:660px">090906 02:14:37 mysqld_safe Starting mysqld daemon with databases from /usr/local/mysql/data</pre></li> |
| </ol> |
| |
| <h4>Windows:</h4> |
| |
| <p>The MySQL Windows installer enables you to install the database server as a Windows |
| service, whereby MySQL starts and stops automatically with the operating system. |
| If you need to start the database manually, run the |
| <a href="http://dev.mysql.com/doc/mysql-startstop-excerpt/5.1/en/mysqld.html" target="_blank"><code>mysqld</code></a> |
| command from the installation directory's <code>bin</code> folder.</p> |
| |
| <ol> |
| <li>Open a Windows console window (from the Start menu, choose Run and type <code>cmd</code> |
| in the text field). A command-line window displays.</li> |
| |
| <li>Enter this command (The indicated path assumes you have installed version 5.1 to |
| the default install location): |
| |
| <pre class="examplecode" style="width:660px">C:\> "C:\Program Files\MySQL\MySQL Server 5.1\bin\mysqld"</pre></li> |
| </ol> |
| |
| <p>For more information, refer to the official MySQL Reference Manual: |
| <a href="http://dev.mysql.com/doc/refman/5.1/en/windows-start-command-line.html" |
| target="_blank">2.4.5.5. Starting MySQL from the Windows Command Line</a>.</p> |
| |
| |
| <h3 id="password">Change the Password</h3> |
| |
| <p>To set the <code>root</code> account's password to '<code>nbuser</code>', perform |
| the following steps.</p> |
| |
| <ol> |
| <li>Open a command-line prompt and type in the following: |
| |
| <pre class="examplecode" style="width:660px"> |
| shell> mysql -u root |
| mysql> UPDATE mysql.user SET Password = PASSWORD('nbuser') WHERE User = 'root'; |
| mysql> FLUSH PRIVILEGES;</pre> |
| </li> |
| </ol> |
| |
| <p>For more information, see the official MySQL Reference Manual: |
| <a href="http://dev.mysql.com/doc/refman/5.1/en/default-privileges.html" |
| target="_blank">2.13.2. Securing the Initial MySQL Accounts</a>.</p> |
| |
| |
| <h3 id="register">Register the Server in the IDE</h3> |
| |
| <p>The IDE's Services window enables you to connect to the server, start and stop the |
| server, view database instances and the data they contain, as well as run an external |
| administration tool on the server.</p> |
| |
| <ol> |
| <li>In the Services window, right-click the Databases node and choose Register |
| MySQL Server. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/register-mysql-server.png" |
| class="margin-around b-all" alt="Services window - right-click options on Databases node" |
| title="Register a MySQL server in the IDE's Services window"> |
| |
| <br> |
| In the MySQL Server Properties dialog, under the Basic Properties tab, you |
| can see the default settings for the MySQL server installation. These are: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><strong>Server Host Name:</strong> <code>localhost</code></li> |
| <li><strong>Server Port Number:</strong> <code>3306</code></li> |
| <li><strong>Administrator User Name:</strong> <code>root</code></li> |
| <li><strong>Administrator Password:</strong> <code>nbuser</code></li> |
| </ul></li> |
| |
| <li>Select the Save Password option. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/mysql-server-properties.png" |
| class="margin-around b-all" alt="MySQL Server Properties dialog" |
| title="Specify MySQL server settings"></li> |
| |
| <li>Click OK. The IDE connects to your MySQL database server, and lists database |
| instances that are maintained by the server. If you expand the Drivers node, |
| you can also see that the IDE contains the |
| <a href="http://dev.mysql.com/doc/refman/5.1/en/connector-j.html" target="_blank">Connector/J |
| JDBC driver</a> for MySQL. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/services-win-mysql.png" |
| class="margin-around b-all" alt="Services window - MySQL Server" |
| title="Connect to a MySQL server in the Services window"> |
| |
| <br> |
| The application server (i.e., GlassFish) requires the driver to enable communication |
| between your Java code and the the MySQL database. Because the IDE already contains |
| the Connector/J driver, you do not need to download it. Furthermore, as will later |
| be demonstrated, you can specify in your server settings to enable JDBC driver |
| deployment so that the driver will be automatically deployed to GlassFish if it |
| is missing on the server. |
| |
| <br><br> |
| Steps 4-7 below are optional. You can configure the IDE to start and stop the |
| MySQL server, as well as run an external administration tool on the server.</li> |
| |
| <li>Right-click the MySQL server node and choose Properties. In the MySQL Server |
| Properties dialog, select the Admin Properties tab.</li> |
| |
| <li>In the 'Path/URL to admin tool' field, enter the path on your computer to the |
| executable file of a database administration tool, such as |
| <a href="http://dev.mysql.com/doc/administrator/en/mysql-administrator-introduction.html" target="_blank">MySQL |
| Administrator</a>. The MySQL Administrator is included in the |
| <a href="http://dev.mysql.com/downloads/gui-tools/" target="_blank">MySQL GUI |
| Tools</a> bundle.</li> |
| |
| <li>In the 'Path to start command' field, type in the path to the MySQL start command |
| (i.e., <code>mysqld</code> or <code>mysqld_safe</code>, depending on your operating |
| system. (See <a href="#start">Start the Database Server</a> above.) |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> For Unix-like systems, you may find |
| that you can only invoke the start command with root or administrative |
| privileges. To overcome this, you can create a script (using |
| <a href="http://www.nongnu.org/gksu/" target="_blank">GKSu</a> for Linux and Solaris, |
| <a href="http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man1/osascript.1.html" target="_blank">osascript</a> |
| for Mac) that will accomplish this task. For more information, see |
| <a href="http://davidvancouvering.blogspot.com/2008/09/starting-mysql-in-netbeans-as.html" target="_blank">this |
| blog post</a>.</li> |
| |
| <li>In the 'Path to stop command' field, enter the path to the MySQL stop command |
| (i.e., <code>mysqladmin shutdown</code>). Because the command requires a user account |
| with shutdown privileges, you must enter username/password credentials in the Arguments |
| field. For example: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><strong>Arguments:</strong> <code>-u root -pnbuser shutdown</code></li> |
| </ul> |
| </li> |
| </ol> |
| |
| <p>After you have set the fields listed under the Advanced Properties tab, you can:</p> |
| |
| <ul> |
| <li><strong>Start the MySQL server:</strong> Right-click the MySQL server node and choose Start.</li> |
| <li><strong>Stop the MySQL server:</strong> Right-click the MySQL server node and choose Stop.</li> |
| <li><strong>Run the external administration tool:</strong> Right-click the MySQL server node and |
| choose Run Administration Tool.</li> |
| </ul> |
| |
| |
| <h3 id="database">Create a Database Instance</h3> |
| |
| <ol> |
| <li>Create the database instance which you will use in this tutorial. To do so, |
| right-click the MySQL Server node and choose Create Database.</li> |
| |
| <li>In the dialog that displays, type in <code>affablebean</code>. Select the |
| 'Grant Full Access to' option, then select <code>root@localhost</code> from |
| the drop-down field. This enables the <code>root</code> account on the |
| <code>localhost</code> host access to the database. Later, when you create |
| a connection pool on the server, you'll need to provide the <code>root</code> |
| account and <code>nbuser</code> password as username/password credentials |
| in order to grant the server access to the database. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/create-mysql-db-dialog.png" |
| class="margin-around b-all" alt="Create MySQL Database dialog" |
| title="Right-click the server node and choose Create Database to create a new database instance"></li> |
| |
| <li>Click OK. When you do so, the database named <code>affablebean</code> is created, |
| and a connection to the database is automatically established. Connections are |
| displayed in the Services window using a connection node ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/db-connection-node.png" |
| alt="Database connection node"> ). |
| |
| <p class="notes"><strong>Note:</strong> Connection nodes are persisted in the |
| Services window. If you restart the IDE, the connection node displays with |
| a jagged line ( <img src="../../../../images_www/articles/73/javaee/ecommerce/common/connection-broken.png" |
| alt="Database connection node - disconnected"> ), indicating that the connection |
| is broken. To reconnect to a database, make sure that the database server |
| is running, then right-click the node and choose Connect.</p></li> |
| |
| <li>Expand the connection node for the <code>affablebean</code> database. The |
| connection contains the database's default schema (<code>affablebean</code>), |
| and within that are nodes for tables, views, and procedures. Currently these |
| are empty since we haven't created anything yet. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup-dev-environ/db-conn-affable-bean.png" |
| class="margin-around b-all" alt="Services window - Database connection for 'affablebean'" |
| title="Database connections contain the database's default schema and nodes for tables, views and procedures"></li> |
| </ol> |
| </div> |
| |
| <p>At this stage, you've connected to the MySQL server from the IDE and have created |
| a new database named <code>affablebean</code> which you'll use throughout the tutorial. |
| Also, you've created a Java web project in the IDE, and have confirmed that it can be |
| successfully built and deployed to your development server, and opened in a browser |
| when run. Now that your development environment is ready, you can begin drafting the |
| application's data model.</p> |
| |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Setting up the Development Environment">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <h2 id="seeAlsoSetupDevEnviron">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Resources</h3> |
| |
| <ul> |
| <li><a href="../../java/project-setup.html" target="_blank">Creating, Importing, and Configuring Java Projects</a></li> |
| <li><a href="../../../articles/mysql.html" target="_blank">MySQL and NetBeans IDE</a></li> |
| <li><a href="../../ide/mysql.html" target="_blank">Connecting to a MySQL Database</a></li> |
| <li><a href="../../web/mysql-webapp.html" target="_blank">Creating a Simple Web Application Using a MySQL Database</a></li> |
| </ul> |
| |
| <h3>External Resources</h3> |
| |
| <ul> |
| <li><a href="http://ant.apache.org/manual/index.html" target="_blank">Apache Ant User Manual</a></li> |
| <li><a href="http://ant.apache.org/manual/tutorial-HelloWorldWithAnt.html" target="_blank">Hello World with Ant</a></li> |
| <li><a href="http://dev.mysql.com/doc/refman/5.1/en/" target="_blank">MySQL 5.1 Reference Manual</a></li> |
| <li><a href="http://dev.mysql.com/doc/administrator/en/index.html" target="_blank">MySQL Administrator Reference Manual</a></li> |
| </ul> |
| |
| <h3>Books</h3> |
| |
| <ul> |
| <li><a href="https://netbeans.org/kb/articles/books.html" target="_blank">NetBeans Books</a></li> |
| <li><a href="http://www.apress.com/book/view/1590598954" target="_blank">Pro NetBeans IDE 6 Rich Client Platform Edition</a></li> |
| <li><a href="http://apress.com/book/view/1430219548" target="_blank">Beginning Java EE 6 Platform with GlassFish 3: From Novice to Professional</a></li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2>References</h2> |
| |
| <ol> |
| <li id="footnote1SetupDevEnviron"><a href="#1SetupDevEnviron" style="text-decoration:none">^</a> Using GlassFish v3, you can create |
| a connection pool to a MySQL database server using an empty password. GlassFish Open Source Edition |
| 3.0.1, included with NetBeans IDE 6.9, does not enable a connection using an empty password. See |
| <a href="http://glassfish.dev.java.net/issues/show_bug.cgi?id=12221" target="_blank">GlassFish |
| Issue 12221</a>.</li> |
| </ol> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="data-model">The NetBeans E-commerce Tutorial - Designing the Data Model</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><strong>Designing the Data Model</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#idEntities">Identifying Entities for the Data Model</a></li> |
| <li><a href="#createERDiagram">Creating an Entity-Relationship Diagram</a></li> |
| <li><a href="#forwardEngineer">Forward-Engineering to the Database</a></li> |
| <li><a href="#connectDB">Connecting to the Database from the IDE</a></li> |
| <li><a href="#seeAlsoDataModel">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>This tutorial unit focuses on data modeling, or the process of creating a conceptual |
| model of your storage system by identifying and defining the entities that your system |
| requires, and their relationships to one another. The data model should contain all |
| the logical and physical design parameters required to generate a script using the Data |
| Definition Language (DDL), which can then be used to create a database.<sup><a href="#footnote1DataModel" |
| id="1DataModel" style="text-decoration:none">[1]</a></sup></p> |
| |
| <p>In this unit, you work primarily with <a href="http://wb.mysql.com/" target="_blank">MySQL |
| Workbench</a>, a graphical tool that enables you to create data models, reverse-engineer |
| SQL scripts into visual representations, forward-engineer data models into database |
| schemata, and synchronize models with a running MySQL database server.</p> |
| |
| <p>You begin by creating an entity-relationship diagram to represent the data model for |
| the <code>AffableBean</code> application. When you have completed identifying and |
| defining all entities and the relationships that bind them, you use Workbench to |
| forward-engineer and run a DDL script that converts the data model into a database |
| schema. Finally, you connect to the new schema from the NetBeans IDE.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans E-commerce |
| Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:both;"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans |
| IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL database server</a></td> |
| <td class="tbltd1">version 5.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/workbench/" target="_blank">MySQL Workbench</a></td> |
| <td class="tbltd1">version 5.1 or 5.2</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><strong class="notes">Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which are |
| required for the application you build in this tutorial.</li> |
| |
| <li>You can download the complete DDL script that MySQL Workbench generates from |
| the entity-relationship diagram you create in this tutorial: |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252Faffablebean_schema_creation.sql">affablebean_schema_creation.sql</a>.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="idEntities">Identifying Entities for the Data Model</h2> |
| |
| <p>In the real world, you may not have the luxury of designing the data model for your |
| application. For example, your task may be to develop an application on top of an |
| existing database system. Provided you do not have a data model to base your application |
| on, creating one should be one of the first design steps you take before embarking on |
| development. Creating a data model involves identifying the objects, or <em>entities</em>, |
| required by your system and defining the relationships between them.</p> |
| |
| <p id="nounList">To begin identifying the entities we need for the data model, |
| re-examine the use-case presented in <a href="design.html#mockups">Designing |
| the Application</a>. Search for commonly-occurring nouns. For example:</p> |
| |
| <div class="indent"> |
| <div class="feedback-box margin-around float-left" style="width:723px"> |
| |
| <h3>Use-Case</h3> |
| |
| <p><strong>Customer</strong> visits the welcome page and selects a product |
| <strong>category</strong>. <strong>Customer</strong> browses <strong>products</strong> |
| within the selected category page, then adds a <strong>product</strong> to |
| his or her <strong>shopping cart</strong>. <strong>Customer</strong> continues |
| shopping and selects a different <strong>category</strong>. <strong>Customer</strong> |
| adds several <strong>products</strong> from this <strong>category</strong> to |
| <strong>shopping cart</strong>. <strong>Customer</strong> selects 'view cart' |
| option and updates quantities for cart <strong>products</strong> in the cart |
| page. <strong>Customer</strong> verifies shopping cart contents and proceeds |
| to checkout. In the checkout page, <strong>customer</strong> views the cost of |
| the <strong>order</strong> and other information, fills in personal data, then |
| submits his or her details. The <strong>order</strong> is processed and |
| <strong>customer</strong> is taken to a confirmation page. The confirmation |
| page provides a unique reference number for tracking the customer <strong>order</strong>, |
| as well as a summary of the <strong>order</strong>.</p> |
| </div> |
| </div> |
| |
| <br style="clear:both"> |
| <br> |
| |
| <p>The text highlighted above in <strong>bold</strong> indicates the candidates that we |
| can consider for the data model. Upon closer inspection, you may deduce that the |
| shopping cart does not need to be included, since the data it provides (i.e., products |
| and their quantities) is equally offered by a customer order once it is processed. In |
| fact, as will be demonstrated in Unit 8, <a href="#manage-sessions">Managing Sessions</a>, |
| the shopping cart merely serves as a mechanism that retains a user session temporarily |
| while the customer shops online. We can therefore settle on the following list:</p> |
| |
| <ul class="toc"> |
| <li><strong>customer</strong></li> |
| <li><strong>category</strong></li> |
| <li><strong>product</strong></li> |
| <li><strong>order</strong></li> |
| </ul> |
| |
| <p>With these four entities, we can begin constructing an entity-relationship diagram (ERD).</p> |
| |
| <p class="notes"><strong>Note:</strong> In this tutorial, we create a database schema from |
| the ERD, then use the IDE's EclipseLink support to generate JPA entity classes from the |
| existing database. (EclipseLink and the Java Persistence API (JPA) are covered in Unit |
| 7, <a href="#entity-session">Adding Entity Classes and Session Beans</a>.) This |
| approach is described as <em>bottom up</em> development. An equally viable alternative |
| is the <em>top down</em> approach.</p> |
| |
| <ul> |
| <li><strong>Top down:</strong> In <em>top down</em> development, you start with |
| an existing Java implementation of the domain model, and have complete freedom |
| with respect to the design of the database schema. You must create mapping |
| metadata (i.e., annotations used in JPA entity classes), and can optionally |
| use a persistence tool to automatically generate the schema.</li> |
| |
| <li><strong>Bottom up:</strong> <em>Bottom up</em> development begins with an |
| existing database schema. In this case, the easiest way to proceed is to use |
| forward-engineering tools to extract metadata from the schema and generate |
| annotated Java source code (JPA entity classes).</li> |
| </ul> |
| |
| <p>For more information on top down and bottom up design strategies, see |
| <a href="http://en.wikipedia.org/wiki/Data_modeling#Modeling_methodologies" target="_blank">Data |
| modeling: Modeling methodologies</a> [Wikipedia].</p> |
| |
| |
| <br> |
| <h2 id="createERDiagram">Creating an Entity-Relationship Diagram</h2> |
| |
| <p>Start by running MySQL Workbench. In this exercise, you use Workbench to design an |
| entity-relationship diagram for the <code>AffableBean</code> application.</p> |
| |
| <p class="notes"><strong>Note:</strong> The following instructions work for MySQL Workbench |
| versions 5.1 <em>and</em> 5.2. The images used in this tutorial are taken from version 5.2. |
| There are slight differences in the graphical interface between versions, however the |
| functionality remains consistent. Because version 5.2 incorporates a query editor (previously |
| MySQL Query Browser), as well as a server administration interface (previously MySQL |
| Administrator), you are presented with the Home screen when opening the application |
| (shown below).</p> |
| |
| <div class="indent"> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/data-model/workbench-home.png" |
| rel="lytebox" title="In Workbench 5.2, the Home screen serves as a central interface to |
| the data modeling tool, an SQL editor, and an administration tool"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/workbench-home.png" |
| class="margin-around b-all" style="width: 728px" alt="MySQL Workbench 5.2 - Home screen" |
| title="Click to enlarge"></a> |
| </div> |
| |
| <p>If you are working in Workbench 5.2, click <strong>Create New EER Model</strong> beneath |
| the Data Modeling heading in the Home screen.</p> |
| |
| <ul> |
| <li><a href="#createSchema">Creating the <code>affablebean</code> Schema</a></li> |
| <li><a href="#createEntities">Creating Entities</a></li> |
| <li><a href="#addProperties">Adding Entity Properties</a></li> |
| <li><a href="#identifyRelationships">Identifying Relationships</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="createSchema">Creating the <code>affablebean</code> Schema</h3> |
| |
| <ol> |
| <li>In the default interface, begin by creating a new schema which will be used with |
| the <code>AffableBean</code> application. Click the plus ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/plus-icon.png" |
| class="b-all" alt="Plus icon"> ) icon located to the right of the <strong>Physical |
| Schemata</strong> heading. |
| |
| <br><br> |
| A new panel opens in the bottom region of the interface, enabling you |
| to specify settings for the new schema. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/data-model/workbench.png" |
| rel="lytebox" title="Use Workbench to create a new database schema"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/workbench.png" |
| class="margin-around b-all" style="width: 688px" alt="New schema panel displays in bottom region of interface" |
| title="Click to enlarge"></a></li> |
| |
| <li>Enter the following settings for the new schema: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><strong>Schema Name:</strong> <code>affablebean</code></li> |
| <li><strong>Default Collation:</strong> <code>utf8 - utf8_unicode_ci</code></li> |
| <li><strong>Comments:</strong> <code>Schema used with the AffableBean application</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/affablebean-schema.png" |
| class="margin-around b-all" style="width: 688px" alt="Settings for 'affablebean' schema" |
| title="Enter settings for 'affablebean' schema"> |
| |
| <br> |
| The new schema is created, and becomes listed under the Catalog tab in the right region |
| of the Workbench interface. |
| |
| <br><br> |
| <p class="tips">For an explanation of character sets and collations, see the MySQL |
| Server Manual: <a href="http://dev.mysql.com/doc/refman/5.1/en/charset-general.html" target="_blank">9.1.1. |
| Character Sets and Collations in General</a>.</p></li> |
| </ol> |
| |
| |
| <h3 id="createEntities">Creating Entities</h3> |
| |
| <p>Start by creating a new entity-relationship diagram in MySQL Workbench. You can |
| drag-and-drop entity tables onto the canvas.</p> |
| |
| <ol> |
| <li>Under the EER Diagrams heading in WorkBench, double-click the Add |
| Diagram ( <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/add-diagram-btn.png" |
| alt="Add Diagram icon"> ) icon. A new EER Diagram opens displaying an empty canvas. |
| |
| <br><br> |
| <span class="tips">'EER' stands for Enhanced Entity-Relationship.</span> |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/data-model/workbench-empty-canvas.png" |
| rel="lytebox" title="Use Workbench to create a new database schema"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/workbench-empty-canvas.png" |
| class="margin-around b-all" style="width: 688px" alt="New EER Diagram displayed an empty canvas" |
| title="Click Add Diagram to create a new, empty canvas"></a></li> |
| |
| <li>Click the New Table ( <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/wb-new-table-icon.png" |
| alt="New Table icon"> ) icon located in the left margin, then hover your mouse onto the canvas |
| and click again. A new table displays on the canvas. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/wb-new-entity-table.png" |
| class="margin-around b-all" alt="New entity table displayed on canvas" |
| title="Click the New Table icon to drag empty tables (entities) onto the canvas"></li> |
| |
| <li>Double-click the table. The Table editor opens in the bottom region of the interface, allowing |
| you to configure settings for the table. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> The terms 'table' and 'entity' are nearly synonymous in this tutorial |
| unit. From the point of view of a database schema, you are creating tables. From a data modeling |
| perspective, you are creating entities. Likewise, the columns that you later create for each |
| table correspond to entity <em>properties</em>.</p></li> |
| |
| <li>In the Table editor, rename the table to one of the nouns you identified from the use-case above. |
| Optionally add a comment describing the purpose of the table. For example: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><strong>Name:</strong> <code>customer</code></li> |
| <li><strong>Engine:</strong> <code>InnoDB</code></li> |
| <li><strong>Comments:</strong> <code>maintains customer details</code></li> |
| </ul> |
| |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/data-model/wb-customer-table.png" rel="lytebox" |
| title="Changes made in the Table editor are immediately updated elsewhere in the Workbench interface"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/wb-customer-table.png" |
| class="margin-around b-all" alt="Customer table displayed on canvas" style="width:688px" |
| title="Click to enlarge"></a> |
| |
| <p class="tips">The <a href="http://www.innodb.com/" target="_blank">InnoDB</a> engine |
| provides foreign key support, which is utilized in this tutorial. Later, under |
| <a href="#forwardEngineer">Forward-Engineering to the Database</a>, you set the |
| default storage engine used in Workbench to InnoDB.</p></li> |
| |
| <li>Under the <strong>Catalog</strong> tab in the left region of WorkBench (right region for |
| version 5.1), expand the <code>affablebean</code> > <code>Tables</code> node. The |
| <strong>customer</strong> table now displays. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/wb-catalog-tab.png" |
| class="margin-around b-all" alt="Catalog tab displaying new customer table" |
| title="Catalog tab automatically refreshes to display any changes to the schema"> |
| |
| <p>More importantly, note that the new <code>customer</code> table is now included in the |
| <code>affablebean</code> schema. Because the <code>affablebean</code> schema was selected |
| when you created the new EER diagram, any changes you make to the diagram are automatically |
| bound to the schema.</p></li> |
| |
| <li>Repeat steps 2 - 4 above to add tables to the canvas for the remaining <a href="#nounList">nouns |
| you identified in the use-case above</a>. Before naming your tables however, there is one important |
| consideration which you should take into account. Certain keywords hold special meaning for the |
| SQL dialect used by the MySQL server. Unfortunately, '<code>order</code>' is one of them. (For |
| example, '<code>order</code>' can be used in an <code>ORDER BY</code> statement.) Therefore, |
| instead of naming your table '<code>order</code>', name it '<code>customer_order</code>' instead. |
| At this stage, don't worry about arranging the tables on the canvas in any special order. |
| |
| <br><br> |
| <p class="tips">For a list of reserved words used by the MySQL server, refer to the official manual: |
| <a href="http://dev.mysql.com/doc/mysqld-version-reference/en/mysqld-version-reference-reservedwords-5-1.html" target="_blank">2.2. |
| Reserved Words in MySQL 5.1</a>.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/wb-entity-tables.png" |
| class="margin-around b-all" alt="All tables displayed on canvas" |
| title="Create all tables for affablebean schema"></li> |
| </ol> |
| |
| |
| <h3 id="addProperties">Adding Entity Properties</h3> |
| |
| <p>Now that you've added entities to the canvas, you need to specify their properties. |
| Entity properties correspond to the columns defined in a database table. For example, |
| consider the <code>customer</code> entity. In regard to the <code>AffableBean</code> |
| application, what aspects of a customer would need to be persisted to the database? |
| These would likely be all of the information gathered in the <a href="design.html#checkout">checkout |
| page</a>'s customer details form, as well as some association to the processed order.</p> |
| |
| <p>When adding properties, you need to determine the most appropriate data type for each |
| property. MySQL supports a number of data types in several categories: numeric types, |
| date and time types, and string (character) types. Refer to the official manual for |
| a summary of data types within each category: |
| <a href="http://dev.mysql.com/doc/refman/5.1/en/data-type-overview.html" target="_blank">10.1. |
| Data Type Overview</a>. In this tutorial, the data types have been chosen for you. |
| Choosing the appropriate data type plays a significant role in optimizing storage |
| on your database server. For more information see:</p> |
| |
| <ul style="margin: 0 0 0 -.7em"> |
| <li><a href="http://dev.mysql.com/doc/refman/5.1/en/storage-requirements.html" target="_blank">10.5. Data Type Storage Requirements</a></li> |
| <li><a href="http://dev.mysql.com/doc/refman/5.1/en/choosing-types.html" target="_blank">10.6. Choosing the Right Type for a Column</a></li> |
| </ul> |
| |
| <p>The following steps describe how you can use MySQL Workbench to add properties to an |
| existing entity in your ERD. As with most of the initial design steps, determining |
| the entity properties would call for careful consideration of the business problem |
| that needs to be solved, and could require hours of analysis as well as numerous |
| consultations with the client.</p> |
| |
| <ol> |
| <li>Double-click the <code>customer</code> table heading to bring up the Table editor |
| in WorkBench.</li> |
| |
| <li>In the Table editor click the Columns tab, then click inside the displayed table |
| to edit the first column. Enter the following details: |
| |
| <table class="margin-around"> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Column</th> |
| <th class="tblheader" scope="col">Datatype</th> |
| <th class="tblheader" scope="col">PK (Primary Key)</th> |
| <th class="tblheader" scope="col">NN (Not Null)</th> |
| <th class="tblheader" scope="col">UN (Unsigned)</th> |
| <th class="tblheader" scope="col">AI (Autoincrement)</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>id</code></td> |
| <td class="tbltd1"><code>INT</code></td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/customer-id-column.png" |
| class="margin-around b-all" style="width:688px" alt="Customer entity's id column specified" |
| title="Click to edit table columns in the Table editor"></li> |
| |
| <li>Continue working in the <code>customer</code> table by adding the following |
| <code>VARCHAR</code> columns. These columns should be self-explanatory, and |
| represent data that would need to be captured for the Affable Bean business |
| to process a customer order and send a shipment of groceries to the customer |
| address. |
| |
| <br> |
| <table class="margin-around"> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Column</th> |
| <th class="tblheader" scope="col">Datatype</th> |
| <th class="tblheader" scope="col">NN (Not Null)</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>name</code></td> |
| <td class="tbltd1"><code>VARCHAR(45)</code></td> |
| <td class="tbltd1">✓</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>email</code></td> |
| <td class="tbltd1"><code>VARCHAR(45)</code></td> |
| <td class="tbltd1">✓</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>phone</code></td> |
| <td class="tbltd1"><code>VARCHAR(45)</code></td> |
| <td class="tbltd1">✓</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>address</code></td> |
| <td class="tbltd1"><code>VARCHAR(45)</code></td> |
| <td class="tbltd1">✓</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>city_region</code></td> |
| <td class="tbltd1"><code>VARCHAR(2)</code></td> |
| <td class="tbltd1">✓</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>cc_number</code></td> |
| <td class="tbltd1"><code>VARCHAR(19)</code></td> |
| <td class="tbltd1">✓</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <br> |
| <span class="tips">For an explanation of the <code>VARCHAR</code> |
| data type, see the MySQL Reference Manual: |
| <a href="http://dev.mysql.com/doc/refman/5.1/en/char.html" target="_blank">10.4.1. |
| The CHAR and VARCHAR Types</a>.</span> |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/customer-varchar-columns.png" |
| class="margin-around b-all" alt="Customer entity's varchar columns specified" |
| title="Edit inline to add columns to customer table"></li> |
| |
| <li>With the <code>customer</code> table selected on the canvas, choose |
| Arrange > Reset Object Size to resize the table so that all columns |
| are visible on the canvas. Also click the Indexes row so that any table |
| indexes are also visible. (This includes primary and foreign keys, which |
| becomes useful when you begin creating relationships between tables later |
| in the exercise.) |
| |
| <br><br> |
| When you finish, the <code>customer</code> entity looks as follows. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/customer-table.png" |
| class="margin-around" alt="'customer' table displayed on EER canvas with columns" |
| title="'customer' table on EER canvas displays columns"></li> |
| |
| <li>Follow the steps outlined above to create columns for the remaining |
| tables. |
| |
| <h4>category</h4> |
| |
| <table class="margin-around"> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Column</th> |
| <th class="tblheader" scope="col">Datatype</th> |
| <th class="tblheader" scope="col">PK</th> |
| <th class="tblheader" scope="col">NN</th> |
| <th class="tblheader" scope="col">UN</th> |
| <th class="tblheader" scope="col">AI</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>id</code></td> |
| <td class="tbltd1"><code>TINYINT</code></td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>name</code></td> |
| <td class="tbltd1"><code>VARCHAR(45)</code></td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <h4>customer_order</h4> |
| |
| <table class="margin-around"> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Column</th> |
| <th class="tblheader" scope="col">Datatype</th> |
| <th class="tblheader" scope="col">PK</th> |
| <th class="tblheader" scope="col">NN</th> |
| <th class="tblheader" scope="col">UN</th> |
| <th class="tblheader" scope="col">AI</th> |
| <th class="tblheader" scope="col">Default</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>id</code></td> |
| <td class="tbltd1"><code>INT</code></td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1"> </td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>amount</code></td> |
| <td class="tbltd1"><code>DECIMAL(6,2)</code></td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>date_created</code></td> |
| <td class="tbltd1"><code>TIMESTAMP</code></td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"><code>CURRENT_TIMESTAMP</code></td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>confirmation_number</code></td> |
| <td class="tbltd1"><code>INT</code></td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"><code> </code></td> |
| </tr> |
| </tbody> |
| </table> |
| |
| |
| <h4>product</h4> |
| |
| <table class="margin-around"> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Column</th> |
| <th class="tblheader" scope="col">Datatype</th> |
| <th class="tblheader" scope="col">PK</th> |
| <th class="tblheader" scope="col">NN</th> |
| <th class="tblheader" scope="col">UN</th> |
| <th class="tblheader" scope="col">AI</th> |
| <th class="tblheader" scope="col">Default</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>id</code></td> |
| <td class="tbltd1"><code>INT</code></td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1"> </td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>name</code></td> |
| <td class="tbltd1"><code>VARCHAR(45)</code></td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>price</code></td> |
| <td class="tbltd1"><code>DECIMAL(5,2)</code></td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>description</code></td> |
| <td class="tbltd1"><code>TINYTEXT</code></td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>last_update</code></td> |
| <td class="tbltd1"><code>TIMESTAMP</code></td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"> </td> |
| <td class="tbltd1"><code>CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP</code></td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p class="tips">For details on the <code>TIMESTAMP</code> data type, see the MySQL Reference Manual: |
| <a href="http://dev.mysql.com/doc/refman/5.1/en/timestamp.html" target="_blank">10.3.1.1. TIMESTAMP Properties</a>.</p> |
| |
| <br> |
| When you finish, your canvas will look similar to the following. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/affablebean-tables.png" |
| class="margin-around b-all" alt="'customer', 'category', 'product', and 'order' tables displayed on EER canvas" |
| title="Use the Table editor to add columns to all tables on canvas"></li> |
| </ol> |
| |
| |
| <h3 id="identifyRelationships">Identifying Relationships</h3> |
| |
| <p>So far, the entity-relationship diagram contains several entities, but lacks |
| any relationships between them. The data model that we are creating must |
| also indicate whether objects are aware of (i.e., contain references to) one |
| another. If one object contains a reference to another object, this is known |
| as a <em>unidirectional</em> relationship. Likewise, if both objects refer to |
| each other, this is called a <em>bidirectional</em> relationship.</p> |
| |
| <p>References correlate to foreign keys in the database schema. You will note |
| that, as you begin linking tables together, foreign keys are added as new |
| columns in the tables being linked.</p> |
| |
| <p>Two other pieces of information are also commonly relayed in an ERD: |
| <em>cardinality</em> (i.e., multiplicity) and <em>ordinality</em> (i.e., |
| optionality). These are discussed below, as you begin adding relationships |
| to entities on the canvas. In order to complete the ERD, you essentially |
| need to create two <em>one-to-many</em> relationships, and one |
| <em>many-to-many</em> relationship. Details follow.</p> |
| |
| <ul> |
| <li><a href="#oneToMany">Creating One-To-Many Relationships</a></li> |
| <li><a href="#manyToMany">Creating Many-To-Many Relationships</a></li> |
| </ul> |
| |
| <h4 id="oneToMany">Creating One-To-Many Relationships</h4> |
| |
| <p>Examine the four objects currently on the canvas while considering the |
| business problem. You can deduce the following two <em>one-to-many</em> |
| relationships:</p> |
| |
| <ul> |
| <li>A category must contain one or more products</li> |
| <li>A customer must have placed one or more orders</li> |
| </ul> |
| |
| <p>Incorporate these two relationships into the ERD. You can download a copy |
| of the MySQL Workbench project that contains the four entities required |
| for the following steps: |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252Faffablebean.mwb">affablebean.mwb</a>.</p> |
| |
| <ol> |
| <li>In the left margin, click the 1:n Non-Identifying Relationship ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/one-many-btn.png" |
| class="b-all" alt="1:n Non-Identifying Relationship button"> ) button. |
| This enables you to create a <em>one-to-many</em> relationship.</li> |
| |
| <li>Click the <code>product</code> table, then click the <code>category</code> |
| table. The first table you click will contain the foreign key reference |
| to the second table. Here, we want the <code>product</code> table to |
| contain a reference to <code>category</code>. In the image below, you |
| see that a new column, <code>category_id</code>, has been added to the |
| <code>product</code> table, and that a foreign key index, |
| <code>fk_product_category</code> has been added to the table's indexes. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/product-category-relationship.png" |
| class="margin-around b-all" alt="'Product-category relationship displayed on EER canvas" |
| title="A one-to-many relationship is defined between the category and product objects"> |
| |
| <br><br> |
| Since foreign keys must be of the same data type as the columns they reference, |
| notice that <code>category_id</code> is of type <code>TINYINT</code>, similar to |
| the <code>category</code> table's primary key. |
| |
| <br><br> |
| <span class="tips">The entity-relationship diagram in this tutorial uses |
| <a href="http://en.wikipedia.org/wiki/Entity-relationship_model#Crow.27s_Foot_Notation" target="_blank">Crow's |
| Foot</a> notation. You can alter the relationship notation in WorkBench by |
| choosing Model > Relationship Notation.</span></li> |
| |
| <li>Double-click the relationship (i.e., click the dashed line between the two |
| entities). The Relationship editor opens in the bottom region of the interface.</li> |
| |
| <li>Change the default caption to '<code>belongs to</code>'. In other words, |
| "product x belongs to category y." Note that this is a <em>unidirectional</em> |
| relationship: A <code>product</code> object contains a reference to the |
| category it belongs to, but the related <code>category</code> object does |
| not contain any references to the products it contains.</li> |
| |
| <li>Click the Foreign Key tab in the Relationship editor. You see the following display. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/foreign-key-tab.png" |
| class="margin-around b-all" alt="'Relationship editor - Foreign Key tab" |
| title="Use the Foreign Key tab to modify a relationship's ordinality and cardinality"> |
| |
| <br> |
| Under the Foreign key tab, you can modify a relationship's: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><strong>cardinality:</strong> whether the relationship between two objects |
| is <em>one-to-one</em> or <em>one-to-many</em>.</li> |
| |
| <li><strong>ordinality:</strong> whether a reference between entities must |
| exist in order to maintain the integrity of the model. (Toggle the Mandatory |
| checkbox for either side.)</li> |
| |
| <li><strong>type:</strong> (i.e., <em>identifying</em> or <em>non-identifying</em>). |
| A non-identifying relationship, such as this one, refers to the fact |
| that the child object (<code>product</code>) can be identified independently |
| of the parent (<code>category</code>). An identifying relationship |
| means that the child cannot be uniquely identified without the parent. |
| An example of this is demonstrated later, when you create a many-to-many |
| relationship between the <code>product</code> and <code>order</code> tables.</li> |
| </ul></li> |
| |
| <li>Click the 1:n Non-Identifying Relationship ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/one-many-btn.png" |
| class="b-all" alt="1:n Non-Identifying Relationship button"> ) button. In the following |
| steps, you create a <em>one-to-many</em> relationship between the <code>customer</code> |
| and <code>customer_order</code> objects.</li> |
| |
| <li>Click the <code>order</code> table first (this table will contain the foreign key), |
| then click the <code>customer</code> table. A relationship is formed between the two |
| tables.</li> |
| |
| <li>Click the link between the two tables, and in the Relationship editor that displays, |
| change the default caption to '<code>is placed by</code>'. The relationship now |
| reads, "customer order x is placed by customer y." |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/order-customer-relationship.png" |
| class="margin-around b-all" alt="'Order-customer relationship displayed on EER canvas" |
| title="A one-to-many relationship is defined between the customer and order objects"> |
| |
| <br><br> |
| <p class="tips">You can click and drag tables on the canvas into whatever position |
| makes the most sense for your model. In the image above, the <code>order</code> |
| table has been moved to the left of <code>customer</code>.</p> |
| </li> |
| </ol> |
| |
| |
| <h4 id="manyToMany">Creating Many-To-Many Relationships</h4> |
| |
| <p><em>Many-to-many</em> relationships occur when both sides of a relationship can have |
| numerous references to related objects. For example, imagine the Affable Bean business |
| offered products that could be listed under multiple categories, such as cherry ice |
| cream, sausage rolls, or avocado soufflé. The data model would have to account |
| for this by including a <em>many-to-many</em> relationship between <code>product</code> |
| and <code>category</code>, since a category contains multiple products, and a product |
| can belong to multiple categories.</p> |
| |
| <p>In order to implement a <em>many-to-many</em> relationship in a database, it is necessary |
| to break the relationship down into two <em>one-to-many</em> relationships. In doing so, |
| a third table is created containing the primary keys of the two original tables. The |
| <code>product</code> - <code>category</code> relationship described above might look as |
| follows in the data model.</p> |
| |
| <div class="indent"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/many-to-many.png" |
| class="margin-around b-all" alt="'Product-category many-to-many relationship displayed on EER canvas" |
| title="A many-to-many relationship is depicted as two one-to-many relationships"> |
| </div> |
| |
| <p>Now, consider how the application will persist customer orders. The <code>customer_order</code> |
| entity already contains necessary properties, such as the date it is created, its confirmation |
| number, amount, and a reference to the customer who placed it. However, there currently is no |
| indication of the products contained in the order, nor their quantities. You can resolve this |
| by creating a <em>many-to-many</em> relationship between <code>customer_order</code> and |
| <code>product</code>. This way, to determine which products are contained in a given order, |
| the application's business logic can query the new table that arises from the many-to-many |
| relationship, and search for all records that match an <code>order_id</code>. Because customers |
| can specify quantities for products in their shopping carts, we can also add a <code>quantity</code> |
| column to the table.</p> |
| |
| <ol> |
| <li>In the left margin, click the n:m Identifying Relationship ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/many-many-btn.png" |
| class="b-all" alt="n:m Identifying Relationship button"> ) button. |
| This enables you to create a <em>many-to-many</em> relationship.</li> |
| |
| <li>Click the <code>customer_order</code> table, then click the <code>product</code> |
| table. A new table appears, named <code>customer_order_has_product</code>. |
| |
| <br><br> |
| <p class="tips">Recall that an <em>identifying relationship</em> means that |
| the child cannot be uniquely identified without the parent. Identifying |
| relationships are indicated on the Workbench canvas by a solid line linking |
| two tables. Here, the <code>customer_order_has_product</code> table forms |
| an identifying relationship with its two parent tables, <code>customer_order</code> |
| and <code>product</code>. A record contained in the <code>customer_order_has_product</code> |
| table requires references from both tables in order to exist.</p></li> |
| |
| <li>Arrange the tables according to the following image. The <em>many-to-many</em> |
| relationship is highlighted below. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/many-to-many-order-product.png" |
| class="margin-around b-all" alt="ERD containing a many-to-many relationship" |
| title="The 'customer_order_has_product' table contains two foreign keys to the order and product tables"> |
| |
| <br> |
| The new <code>customer_order_has_product</code> table contains two foreign |
| keys, <code>fk_customer_order_has_product_customer_order</code> and |
| <code>fk_customer_order_has_product_product</code>, which reference the |
| primary keys of the <code>customer_order</code> and <code>product</code> |
| tables, respectively. These two foreign keys form a composite primary key |
| for the <code>customer_order_has_product</code> table.</li> |
| |
| <li>Change the name of the new <code>customer_order_has_product</code> table to |
| '<code>ordered_product</code>'. Double-click the <code>customer_order_has_product</code> |
| table to open the Table editor. Enter <code>ordered_product</code> into the Name |
| field.</li> |
| |
| <li>Rename the foreign key indexes to correspond to the new table name. In the |
| <code>ordered_product</code>'s Table editor, click the Foreign Keys tab. Then, |
| click into both foreign key entries and replace '<code>customer_order_has_product</code>' |
| with '<code>ordered_product</code>'. When you finish, the two entries should read: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><code>fk_<strong>ordered_product</strong>_customer_order</code></li> |
| <li><code>fk_<strong>ordered_product</strong>_product</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/ordered-product-foreign-key.png" |
| title="Rename the foreign key indexes under the Foreign Keys tab in the Table editor" |
| class="margin-around b-all" alt="Foreign Keys tab in Table editor"></li> |
| |
| <li>Double-click the lines between the two objects and delete the default captions |
| in the Relationship editor.</li> |
| |
| <li>Create a <code>quantity</code> column in the <code>ordered_product</code> |
| table. To do so, click the Columns tab in the <code>ordered_product</code>'s |
| Table editor. Enter the following details. |
| |
| <table class="margin-around"> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Column</th> |
| <th class="tblheader" scope="col">Datatype</th> |
| <th class="tblheader" scope="col">NN (Not Null)</th> |
| <th class="tblheader" scope="col">UN (Unsigned)</th> |
| <th class="tblheader" scope="col">Default</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>quantity</code></td> |
| <td class="tbltd1"><code>SMALLINT</code></td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1">✓</td> |
| <td class="tbltd1"><code>1</code></td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/quantity-column.png" |
| class="margin-around b-all" alt="Table editor - 'order_has_product' table" |
| title="Add a 'quantity' column to the 'order_has_product' table"> |
| </li> |
| </ol> |
| |
| <p>You have now completed the ERD (entity-relationship diagram). This diagram |
| represents the data model for the <code>AffableBean</code> application. |
| As will later be demonstrated, the JPA entity classes that you create will |
| be derived from the entities existing in the data model.</p> |
| |
| <div class="indent"> |
| <div class="indent"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/affablebean-erd.png" |
| class="margin-around b-all" alt="Complete AffableBean ERD" |
| title="ERD for the AffableBean application"> |
| </div> |
| </div> |
| |
| <p class="tips">Choose View > Toggle Grid to disable the canvas grid. |
| You can also create notes for your diagram using the New Text Object ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/text-object-btn.png" |
| alt="New Text Object button"> ) button in the left margin.</p> |
| </div> |
| |
| |
| <br> |
| <h2 id="forwardEngineer">Forward-Engineering to the Database</h2> |
| |
| <p>To incorporate the data model you created into the MySQL database, you can employ |
| WorkBench to forward-engineer the diagram into an SQL script (more precisely, |
| a DDL script) to generate the schema. The wizard that you use also enables you |
| to immediately run the script on your database server.</p> |
| |
| <p><strong>Important:</strong> Make sure your MySQL database server is running. |
| Steps describing how to setup and run the database are provided in |
| <a href="setup-dev-environ.html#communicate">Setting up the Development |
| Environment: Communicating with the Database Server</a>.</p> |
| |
| <ol> |
| <li>Set the default storage engine used in Workbench to InnoDB. Choose Tools > |
| Options (MySQLWorkbench > Preferences on Mac) to open the Workbench |
| Preferences window. Click the MySQL tab, then select InnoDB as the default |
| storage engine. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/inno-db.png" |
| class="margin-around b-all" alt="Workbench Preferences window - MySQL tab" |
| title="Set the default storage engine to InnoDB" style="width:688px"> |
| |
| <br> |
| The <a href="http://www.innodb.com/" target="_blank">InnoDB</a> engine provides |
| foreign key support, which is utilized in this tutorial.</li> |
| |
| <li>Click OK to exit the Preferences window.</li> |
| |
| <li>Choose Database > Forward Engineer from the main menu.</li> |
| |
| <li>In the first panel of the Forward Engineer to Database wizard, select |
| '<code>DROP Objects Before Each CREATE Object</code>', and '<code>Generate |
| DROP SCHEMA</code>'. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/forward-engineer-wzd.png" |
| class="margin-around b-all" style="width:688px" alt="Forward Engineer wizard" |
| title="Enable DROP options to be generated in the SQL script"> |
| |
| <br> |
| These <code>DROP</code> options are convenient for prototyping - if you need |
| to make changes to the schema or schema tables, the script will first delete |
| (i.e., <em>drop</em>) these items before recreating them. (If you attempt to |
| create items on the MySQL server that already exist, the server will flag an |
| error.)</li> |
| |
| <li>Click Continue. In Select Objects to Forward Engineer panel, note that the |
| Export MySQL Table Objects option is selected by default. Click the Show |
| Filter button and note that all five tables in the <code>affablebean</code> |
| schema are included.</li> |
| |
| <li>Click Continue. In the Review SQL Script panel, you can examine the SQL script |
| that has been generated based on the data model. Optionally, click Save to |
| File to save the script to a location on your computer. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> In examining the script, you may notice |
| that the following variables are set at the top of the file:</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:660px"> |
| SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; |
| SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; |
| SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL';</pre> |
| |
| |
| <p>For an explanation of what these variables are, and their purpose in the script, |
| see the official Workbench manual: |
| <a href="http://dev.mysql.com/doc/workbench/en/workbench-faq.html" target="_blank">Chapter |
| 11. MySQL Workbench FAQ</a>.</p></div></li> |
| |
| <li>Click Continue. In the Connection Options panel, set the parameters for |
| connecting to the running MySQL server. |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><strong>Hostname:</strong> <code>127.0.0.1</code> (<em>or <code>localhost</code></em>)</li> |
| <li><strong>Port:</strong> <code>3306</code></li> |
| <li><strong>Username:</strong> <code>root</code></li> |
| <li><strong>Password:</strong> <code>nbuser</code></li> |
| </ul> |
| |
| (The parameters you set should correspond to those from <a href="setup-dev-environ.html#communicate">Setting up the Development Environment: |
| Communicating with the Database Server</a>.)</li> |
| |
| <li>Click Execute. In the final panel of the wizard, you receive confirmation |
| that the wizard was able to connect to and execute the script successfully.</li> |
| |
| <li>Click Close to exit the wizard.</li> |
| </ol> |
| |
| <p>The <code>affablebean</code> schema is now created and exists on your MySQL server. |
| In the next step, you connect to the schema, or <em>database</em>, from the IDE. At |
| this stage you may ask, "What's the difference between a schema and a database?" |
| In fact, the MySQL command <code>CREATE SCHEMA</code> is a synonym for <code>CREATE |
| DATABASE</code>. (See <a href="http://dev.mysql.com/doc/refman/5.1/en/create-database.html" target="_blank">12.1.10. |
| CREATE DATABASE Syntax</a>.) Think of a schema as a blueprint that defines the contents |
| of the database, including tables, relationships, views, etc. A database implements the |
| schema by containing data in a way that adheres to the structure of the schema. This is |
| similar to the object-oriented world of Java classes and objects. A class defines an object. |
| When a program runs however, objects (i.e., class instances) are created, managed, and |
| eventually destroyed as the program runs its course.</p> |
| |
| |
| <br> |
| <h2 id="connectDB">Connecting to the Database from the IDE</h2> |
| |
| <p>Now that the <code>affablebean</code> schema exists on your MySQL server, ensure |
| that you can view the tables you created in the ERD from the IDE's Services window.</p> |
| |
| <p><strong>Important:</strong> Make sure that you have followed the steps outlined in |
| <a href="setup-dev-environ.html#communicate">Setting up the Development Environment: |
| Communicating with the Database Server</a>. This heading describes how to run the |
| MySQL database server, register it with the IDE, create a database instance, and |
| form a connection to the instance from the IDE.</p> |
| |
| <ol> |
| <li>In the IDE, open the Services window (Ctrl-5; ⌘-5 on Mac) and locate |
| the database connection node ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/db-connection-node.png" |
| alt="Database connection node"> ) for the <code>affablebean</code> database |
| instance you created in the <a href="setup-dev-environ.html#communicate">previous |
| tutorial unit</a>.</li> |
| |
| <li>Refresh the connection to the <code>affablebean</code> database. To do so, |
| right-click the connection node and choose Refresh.</li> |
| |
| <li>Expand the Tables node. You can now see the five tables defined by the schema.</li> |
| |
| <li>Expand any of the table nodes. Each table contains the columns and indexes |
| that you created when working in MySQL Workbench. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/data-model/services-window-schema.png" |
| class="margin-around b-all" alt="Forward Engineer wizard" |
| title="Update the database connection to view schema tables"></li> |
| </ol> |
| |
| <p>The IDE is now connected to a database that uses the schema you created for the |
| <code>AffableBean</code> application. From the IDE, you can now view any table |
| data you create in the database, as well as directly modify, add and delete data. |
| You will explore some of these options later, in <a href="#connect-db">Connecting |
| the Application to the Database</a>, after you've added sample data to the database.</p> |
| |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Designing the Data Model">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <h2 id="seeAlsoDataModel">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Resources</h3> |
| |
| <ul> |
| <li><a href="../../../articles/mysql.html" target="_blank">MySQL and NetBeans IDE</a></li> |
| <li><a href="../../ide/mysql.html" target="_blank">Connecting to a MySQL Database</a></li> |
| <li><a href="../../web/mysql-webapp.html" target="_blank">Creating a Simple Web Application Using a MySQL Database</a></li> |
| <li><a href="../../ide/database-improvements-screencast.html" target="_blank">Screencast: Database Support in NetBeans IDE</a></li> |
| </ul> |
| |
| <h3>MySQL & Data Modeling Resources</h3> |
| |
| <ul> |
| <li><a href="http://wb.mysql.com/" target="_blank">MySQL Workbench Blog</a></li> |
| <li><a href="http://forums.mysql.com/index.php?151" target="_blank">MySQL Workbench Forum</a></li> |
| <li><a href="http://dev.mysql.com/librarian/" target="_blank">The MySQL Community Librarian</a></li> |
| <li><a href="http://dev.mysql.com/doc/workbench/en/index.html" target="_blank">MySQL Workbench Reference Manual</a></li> |
| <li><a href="http://dev.mysql.com/doc/refman/5.1/en/" target="_blank">MySQL 5.1 Reference Manual</a></li> |
| <li><a href="http://en.wikipedia.org/wiki/Innodb" target="_blank">InnoDB</a> [Wikipedia]</li> |
| <li><a href="http://en.wikipedia.org/wiki/Database_model" target="_blank">Database Model</a> [Wikipedia]</li> |
| <li><a href="http://en.wikipedia.org/wiki/Data_modeling" target="_blank">Data Modeling</a> [Wikipedia]</li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2>References</h2> |
| |
| <ol> |
| <li id="footnote1DataModel"><a href="#1DataModel" style="text-decoration:none">^</a> Data Definition |
| Language (DDL) is a subset of the SQL language and includes statements such as |
| <code>CREATE TABLE</code>, <code>DROP</code>, and <code>ALTER</code>. Other subsets |
| include Data Manipulation Language (DML), and Data Control Language (DCL). For |
| more information, see <a href="http://en.wikipedia.org/wiki/Data_Definition_Language" target="_blank">Data |
| Definition Language</a> [Wikipedia].</li> |
| </ol> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="page-views-controller">The NetBeans E-commerce Tutorial - Preparing the Page Views and Controller Servlet</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><strong>Preparing the Page Views and Controller Servlet</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#createProjectFiles">Creating Project Files</a></li> |
| <li><a href="#implementHTML">Implementing HTML and CSS content</a></li> |
| <li><a href="#view">Placing JSP Pages in WEB-INF</a></li> |
| <li><a href="#jspf">Creating a Header and Footer</a></li> |
| <li><a href="#dd">Adding a Directive to the Deployment Descriptor</a></li> |
| <li><a href="#controller">Creating the Controller Servlet</a></li> |
| <li><a href="#implement">Implementing the Controller Servlet</a></li> |
| <li><a href="#seeAlsoPageViewsController">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>This tutorial unit demonstrates how to create project files in the IDE, and |
| introduces you to some of the facilities available for HTML and CSS development. |
| After creating necessary project files, you begin organizing the front-end of |
| the application. That is, you'll place JSP files in their proper locations |
| within the project structure, create a header and footer which will be applied |
| to all views, and set up the controller servlet to handle incoming requests.</p> |
| |
| <p>In this unit, you also create a web deployment descriptor (<code>web.xml</code> file) |
| for the application. You can use the deployment descriptor to specify configuration |
| information which is read by the server during deployment. Although the |
| <a href="http://jcp.org/en/jsr/detail?id=315" target="_blank">Servlet 3.0 Specification</a>, |
| included in Java EE 6, enables you to use class annotations in place of XML, you may |
| still require the deployment descriptor to configure certain elements of your application. |
| Specifically, in this unit you add directives for the header and footer and specify |
| which files they will be applied to.</p> |
| |
| <p>One of the goals of this tutorial unit is to create JSP pages that correspond to the |
| views specified in the application design. Referring back to the <a href="design.html#mockups">page |
| mockups</a> and <a href="design.html#business">process flow diagram</a>, you begin |
| implementing page layouts according to the mockups by creating <em>placeholders</em> |
| for all visual and functional components. This unit provides a guide for implementing |
| the layout of the welcome page. You can apply the outlined steps to create the other |
| pages on your own, or <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot1.zip">download |
| project snapshot 1</a>, which provides completed layouts for all pages.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans E-commerce |
| Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#glassFishPageViewsController">GlassFish server</a></td> |
| <td class="tbltd1">v3 or Open Source Edition 3.0.1</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><strong class="notes">Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which are |
| required for the application you build in this tutorial.</li> |
| |
| <li id="glassFishPageViewsController">The NetBeans IDE Java Bundle also includes the GlassFish |
| server, which you require for this tutorial. You could |
| <a href="http://glassfish.dev.java.net/public/downloadsindex.html" target="_blank">download |
| the GlassFish server independently</a>, but the version provided with the |
| NetBeans download has the added benefit of being automatically registered with |
| the IDE.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="createProjectFiles">Creating Project Files</h2> |
| |
| <p>To create new files for your project, access the IDE's File wizard. You can click |
| the New File ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/new-file-btn.png" |
| alt="New File button"> ) button, press Ctrl-N (⌘-N on Mac), or in the |
| Projects window, right-click the folder node that will contain the new file, |
| and choose New > [file-type]. In the following sub-sections, create JSP |
| pages and a stylesheet for the project.</p> |
| |
| <ul> |
| <li><a href="#jsp">Creating JSP Pages</a></li> |
| <li><a href="#css">Creating a Stylesheet</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="jsp">Creating JSP Pages</h3> |
| |
| <p>Begin working in the project by creating JSP pages that correspond to the views |
| displayed in the <a href="design.html#business">process flow diagram</a>.</p> |
| |
| <p>The <code>index.jsp</code> page that was generated by the IDE will become the |
| project's welcome page. Create JSP pages for the four remaining views and, for |
| now, place them in the project's webroot with <code>index.jsp</code>.</p> |
| |
| <ol> |
| <li>Click the New File ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/new-file-btn.png" |
| alt="New File button"> ) button to open the File wizard.</li> |
| |
| <li>Select the Web category, then select JSP and click Next.</li> |
| |
| <li>Name the file '<code>category</code>'. Note that the Location field |
| is set to <code>Web Pages</code>, indicating that the file will be created |
| in the project's webroot. This corresponds to the project's <code>web</code> |
| folder, which you can later verify in the IDE's Files window.</li> |
| |
| <li>Click Finish. The IDE generates the new JSP page and opens it in the editor.</li> |
| |
| <li>Repeat steps 1 - 4 above to create the remaining <code>cart.jsp</code>, |
| <code>checkout.jsp</code>, <code>confirmation.jsp</code> pages. |
| |
| <br><br> |
| When you finish, your Projects window will look as follows: |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/projects-win-views.png" |
| class="margin-around b-all" alt="Projects window displaying 'view' folder and JSP pages" |
| title="Views are contained in the 'WEB-INF/view/' folder"> |
| </li> |
| </ol> |
| |
| |
| <h3 id="css">Creating a Stylesheet</h3> |
| |
| <p>Create a CSS file to contain all styles specific to the application.</p> |
| |
| <ol> |
| <li>In the Projects window, right-click the Web Pages node and choose New > Folder.</li> |
| |
| <li>In the New Folder wizard, name the folder '<code>css</code>' and click Finish.</li> |
| |
| <li>Right-click the new <code>css</code> folder and choose New > Cascading |
| Style Sheet. (If the Cascading Style Sheet item is not listed, choose Other. |
| In the File wizard, select the Web category, then select Cascading Style Sheet |
| and choose Next.)</li> |
| |
| <li>Name the stylesheet <code>affablebean</code>, then click Finish. |
| |
| <br><br> |
| When you finish, you'll see the <code>affablebean.css</code> file displayed |
| in your Projects window. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/projects-win-css.png" |
| class="margin-around b-all" alt="Projects window displaying 'affablebean.css' stylesheet" |
| title="Projects window displays new 'css' folder and stylesheet"></li> |
| </ol> |
| </div> |
| |
| |
| <br> |
| <h2 id="implementHTML">Implementing HTML and CSS content</h2> |
| |
| <p>The purpose of this section is to design the page views so that they begin to |
| mirror the provided <a href="design.html#mockups">page mockups</a>. As such, |
| they'll serve as a scaffolding which you can use to insert dynamic content during |
| later stages of project development. To do so, you'll utilize the IDE's HTML |
| and CSS editors, along with several CSS support windows.</p> |
| |
| <p class="notes"><strong>Browser compatibility note:</strong> This tutorial uses |
| Firefox 3 and <em>does not</em> guarantee that page view markup is compatible |
| with other modern browsers. Naturally, when working with front-end web technologies |
| (HTML, CSS, JavaScript) you would need take measures to ensure that your web |
| pages render properly in the browsers and browser versions that you expect visitors |
| to your site will be using (typically Internet Explorer, Firefox, Safari, Chrome, |
| and Opera). When working in the IDE, you can set the browser you want your application |
| to open in. Choose Tools > Options (NetBeans > Preferences on Mac), and under |
| the General tab in the Options window, select the browser you want to use from |
| the Web Browser drop-down. The IDE detects browsers installed to their default |
| locations. If a browser installed on your computer is not displayed, click the |
| Edit button and register the browser manually.</p> |
| |
| <p>Preparing the display of your web pages is usually an iterative process which |
| you would fine-tune with regular feedback from the customer. The following steps |
| are designed to introduce you to the facilities provided by the IDE, and |
| demonstrate how to get started using the <a href="design.html#index">welcome |
| page mockup</a> as an example.</p> |
| |
| <ol> |
| <li>In the Projects window, double-click <code>index.jsp</code> to open it in the |
| editor.</li> |
| |
| <li>Begin by creating <code><div></code> tags for the main areas of the page. |
| You can create five tags altogether: four for main areas (header, footer, |
| left column, and right column), and the fifth to contain the others. Remove |
| any content within the <code><body></code> tags and replace with the |
| following. (New code is shown in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <body> |
| <strong><div id="main"> |
| <div id="header"> |
| header |
| </div> |
| |
| <div id="indexLeftColumn"> |
| left column |
| </div> |
| |
| <div id="indexRightColumn"> |
| right column |
| </div> |
| |
| <div id="footer"> |
| footer |
| </div> |
| </div></strong> |
| </body></pre></li> |
| |
| <li>Add a reference to the stylesheet in the page's head, and change the title text. |
| |
| <pre class="examplecode"> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <strong><link rel="stylesheet" type="text/css" href="css/affablebean.css"></strong> |
| <title><strong>The Affable Bean</strong></title> |
| </head></pre></li> |
| |
| <li>Open the <code>affablebean.css</code> stylesheet in the editor. Begin creating |
| style rules for the <code><div></code> IDs you just created. |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>Use the <code>width</code> and <code>height</code> properties to create |
| space for each area.</li> |
| |
| <li>Use the <code>background</code> property to discern the areas when you |
| view the page.</li> |
| |
| <li>In order to horizontally center the four areas in the page, you can include |
| <code>margin: 20px auto</code> to the <code>body</code> rule. (<code>20px</code> |
| applies to the top and bottom; <code>auto</code> creates equal spacing to |
| the left and right.) Then include <code>float: left</code> to the left and |
| right columns.</li> |
| |
| <li>The footer requires <code>clear: left</code> so that its top border displays |
| after the bottom borders of any left-floating areas above it (i.e., the left |
| and right columns).</li> |
| </ul> |
| |
| <pre class="examplecode"> |
| body { |
| font-family: Arial, Helvetica, sans-serif; |
| width: 850px; |
| text-align: center; |
| margin: 20px auto; |
| } |
| |
| #main { background: #eee } |
| |
| #header { |
| height: 250px; |
| background: #aaa; |
| } |
| |
| #footer { |
| height: 60px; |
| clear: left; |
| background: #aaa; |
| } |
| |
| #indexLeftColumn { |
| height: 400px; |
| width: 350px; |
| float: left; |
| background: #ccc; |
| } |
| |
| #indexRightColumn { |
| height: 400px; |
| width: 500px; |
| float: left; |
| background: #eee; |
| }</pre></li> |
| |
| <li>Click the Run Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) button in the IDE's main toolbar. Project files that contain |
| changes are automatically saved, any Java code in the project compiles, the project is |
| packaged and deployed to GlassFish, and your browser opens to display the current state |
| of the welcome page. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/index-page.png" |
| class="margin-around b-all" alt="Welcome page displayed in browser" style="width:688px" |
| title="Run the project to view the current state of pages"></li> |
| |
| <li>Now, begin creating placeholders for page components within each of the four visible areas. |
| Start with the header. Reviewing the <a href="design.html#index">welcome page mockup</a>, the |
| header should contain the following components: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>logo</li> |
| <li>logo text</li> |
| <li>shopping cart widget</li> |
| <li>language toggle</li> |
| </ul> |
| |
| Make the following changes to the <code>index.jsp</code> file. (New code shown |
| in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <div id="header"> |
| <strong><div id="widgetBar"> |
| |
| <div class="headerWidget"> |
| [ language toggle ] |
| </div> |
| |
| <div class="headerWidget"> |
| [ shopping cart widget ] |
| </div> |
| |
| </div> |
| |
| <a href="#"> |
| <img src="#" id="logo" alt="Affable Bean logo"> |
| </a> |
| |
| <img src="#" id="logoText" alt="the affable bean"></strong> |
| </div></pre> |
| |
| In the above code, you use a <code><div id="widgetBar"></code> |
| element to contain the the language toggle and shopping cart widget. |
| |
| <br><br> |
| <div class="feedback-box float-left" style="width: 683px;"> |
| |
| <h3>NetBeans HTML Editor Support</h3> |
| |
| <p>When you work in the editor, take advantage of the IDE's HTML support. |
| Aside from typical syntax highlighting that lets you differentiate |
| between tags, attributes, attribute values, and text, there are plenty |
| of other features.</p> |
| |
| <p>When typing tags and attributes in the editor, you can invoke code-completion |
| and documentation support by pressing Ctrl-Space. The IDE presents a list |
| of suggestions which you can choose from, as well as a documentation window |
| that defines the selected item and provides code examples.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/documentation-popup.png" |
| class="margin-around b-all" title="Press Ctrl-Space to view code completion and documentation windows" |
| alt="Code completion and documentation windows displayed in editor"/> |
| |
| <p>The IDE detects errors in your code and provides you with warnings, error |
| messages, and in some cases, suggestions. Warning messages are displayed |
| in yellow, while errors are shown in red. You can hover your pointer over |
| a designated area to view the message in a tooltip.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/html-hint.png" |
| class="margin-around b-all" title="Hover your pointer to view a tooltip warning" |
| alt="HTML warning displayed in editor"/> |
| |
| <p>You can also take advantage of numerous keyboard shortcuts. Choose Help > |
| Keyboard Shortcuts Card from the main menu.</p> |
| </div> |
| <br style="clear: both;"/></li> |
| |
| <li>In the stylesheet, create rules for the new IDs and classes. Add the following rules |
| beneath the <code>header</code> rule. (New code shown in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| #header { |
| height: 250px; |
| background: #aaa; |
| } |
| |
| <strong>#logo { |
| height: 155px; |
| width: 155px; |
| float: left; |
| margin-left: 30px; |
| margin-top: -20px; |
| } |
| |
| #logoText { |
| float: left; |
| margin: 20px 0 0 70px; |
| /* font styles apply to text within alt tags */ |
| font-family: 'American Typewriter', Courier, monospace; |
| font-size: 50px; |
| color: #333; |
| } |
| |
| #widgetBar { |
| height: 50px; |
| width: 850px; |
| float: right; |
| background: #ccc; |
| } |
| |
| .headerWidget { |
| width: 194px; |
| margin: 20px 2px; |
| font-size: small; |
| float: right; |
| line-height: 25px; |
| background: #aaa; |
| }</strong></pre> |
| |
| For the <code>logo</code> rule, you apply <code>margin-left</code> and |
| <code>margin-top</code> properties to position the component on the page. |
| |
| <br><br> |
| If there are properties in the above code that you are unfamiliar with, |
| position your cursor on the given property and press Ctrl-Space to invoke |
| a pop-up window that provides documentation support. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/css-doc-support.png" |
| class="margin-around b-all" alt="Documentation window for CSS support" |
| title="Press Ctrl-Space on a CSS property to invoke documentation support"> |
| |
| <br> |
| <p class="tips">To see how a property is affecting your page, you can comment |
| it out, then refresh the page in the browser. To comment out code, position |
| your cursor on a line, or highlight a block of code, then press Ctrl-/ |
| (⌘-/ on Mac).</p></li> |
| |
| <li>Save (Ctrl-S; ⌘-S on Mac) the <code>index.jsp</code> and <code>affablebean.css</code> |
| files, then switch to your browser and refresh the page to view its current state. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> The IDE's 'Deploy on Save' facility is automatically |
| activated for Java web projects. This means that every time you save a file, the file is |
| automatically compiled (i.e., if it is a Java class or JSP page) and the project is newly |
| packaged and deployed to your server. Therefore, when you make HTML or CSS changes, you |
| don't need to explicitly rerun the project to view the updated version in a browser. Simply |
| save your file(s), then switch to the browser and refresh the page.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/index-page2.png" |
| class="margin-around b-all" alt="Welcome page displayed in browser" style="width:688px" |
| title="Placeholders for header are visible when running project"> |
| |
| <br> |
| By following the previous steps, you are probably able to see a pattern emerging. |
| For each area on the page, you perform three steps. |
| |
| <ol style="list-style:lower-alpha; margin-top:5px"> |
| <li>Create the structure in HTML.</li> |
| <li>Create a set of styles to define the appearance.</li> |
| <li>View the page to examine the results of your changes.</li> |
| </ol> |
| |
| Following these three steps, let's implement the components in the remaining areas.</li> |
| |
| <li>Create placeholders for components in the right column. According to the |
| <a href="design.html#index">welcome page mockup</a>, the right column contains |
| four evenly-spaced boxes. |
| |
| <br><br> |
| Create the structure for the four boxes. Insert the following code between |
| the <code><div id="indexRightColumn"></code> tags. (New code shown |
| in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <div id="indexRightColumn"> |
| <strong><div class="categoryBox"> |
| <a href="#"> |
| <span class="categoryLabelText">dairy</span> |
| </a> |
| </div> |
| <div class="categoryBox"> |
| <a href="#"> |
| <span class="categoryLabelText">meats</span> |
| </a> |
| </div> |
| <div class="categoryBox"> |
| <a href="#"> |
| <span class="categoryLabelText">bakery</span> |
| </a> |
| </div> |
| <div class="categoryBox"> |
| <a href="#"> |
| <span class="categoryLabelText">fruit & veg</span> |
| </a> |
| </div></strong> |
| </div></pre></li> |
| |
| <li>Add style rules to <code>affablebean.css</code> for the new <code>categoryBox</code> |
| and <code>categoryLabelText</code> classes. (New code shown in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| #indexRightColumn { |
| height: 400px; |
| width: 500px; |
| float: left; |
| background: #eee; |
| } |
| |
| <strong>.categoryBox { |
| height: 176px; |
| width: 212px; |
| margin: 21px 14px 6px; |
| float: inherit; |
| background: #ccc; |
| } |
| |
| .categoryLabelText { |
| line-height: 150%; |
| font-size: x-large; |
| }</strong></pre> |
| |
| <div class="feedback-box float-left" style="width: 683px;"> |
| |
| <h3>NetBeans CSS Support</h3> |
| |
| <p>When working in stylesheets, there are two windows that can be |
| particularly helpful. The CSS Preview enables you to view style |
| rules as they are rendered in a browser. To open the CSS Preview, |
| choose Window > Other > CSS Preview from the main menu. |
| When you place your cursor within a style rule in the editor, |
| the CSS Preview automatically refreshes to display sample text |
| according to the properties defined in the rule.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/css-preview.png" |
| class="margin-around b-all" alt="CSS Preview" |
| title="Use the CSS Preview to view rendered style rules"> |
| |
| <p>The CSS Style Builder is useful if you do not like to code style |
| rules by hand. To open the CSS Style Builder, choose Window > |
| Other > CSS Style Builder from the main menu. Using this interface, |
| you can construct rules by choosing properties and values from a |
| graphical interface.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/style-builder.png" |
| class="margin-around b-all" alt="CSS Style Builder" |
| title="Use the CSS Style Builder to construct style rules"> |
| |
| <p>Like the CSS Preview, the Style Builder is synchronized with the editor. |
| When you make a selection in the Style Builder, the style rule is |
| automatically updated in the editor. Likewise, when you type changes |
| into the editor, the selections in the Style Builder are instantly |
| updated.</p> |
| </div> |
| <br style="clear: both;"/></li> |
| |
| <li>Save (Ctrl-S; ⌘-S on Mac) the <code>index.jsp</code> and <code>affablebean.css</code> |
| files, then switch to your browser and refresh the page to view its current state. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/index-page3.png" |
| class="margin-around b-all" alt="Welcome page displayed in browser" style="width:688px" |
| title="Placeholders for header and right-column are visible when running project"> |
| |
| <li>The left column and footer only require placeholders for static text, so let's |
| implement both simultaneously. |
| |
| <br><br> |
| Insert the following code between the <code><div id="indexLefttColumn"></code> |
| and <code><div id="footer"></code> tags. (New code shown in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <div id="indexLeftColumn"> |
| <strong><div id="welcomeText"> |
| <p>[ welcome text ]</p> |
| </div></strong> |
| </div> |
| |
| ... |
| |
| <div id="footer"> |
| <strong><hr> |
| <p id="footerText">[ footer text ]</p></strong> |
| </div></pre></li> |
| |
| <li>Make changes to the <code>affablebean.css</code> stylesheet. It's not necessary |
| to account for all new IDs and classes - you can fine-tune the appearance at a |
| later point when you receive text and images from the customer. |
| |
| <br><br> |
| The horizontal rule (<code><hr></code>) tag runs the full length of its |
| containing element (<code><div id="footer"</code>). Therefore, |
| to shorten it in accordance with the mockup image, you can adjust the width of |
| <code><div id="footer"></code>. (New code shown in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| #footer { |
| height: 60px; |
| <strong>width: 350px;</strong> |
| clear: left; |
| background: #aaa; |
| } |
| |
| <strong>hr { |
| border: 0; |
| background-color: #333; |
| height: 1px; |
| margin: 0 25px; |
| width: 300px; |
| }</strong></pre></li> |
| |
| <li>Save (Ctrl-S; ⌘-S on Mac) the <code>index.jsp</code> and <code>affablebean.css</code> |
| files, then switch to your browser and refresh the page to view its current state. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/index-page4.png" |
| class="margin-around b-all" alt="Welcome page displayed in browser" style="width:688px" |
| title="Placeholders for left column and footer are visible" id="welcome-page"> |
| |
| <br> |
| The welcome page is complete. You've created all necessary placeholders for |
| components that will exist on the page. |
| </li> |
| </ol> |
| |
| <p>You've now completed the initial design of the application's welcome page. All |
| placeholders for page components exist. Later in the tutorial, when you begin |
| to apply dynamic logic to the page views, you can simply plug JSTL and EL |
| expressions into these placeholders.</p> |
| |
| <p>The task remains for you to implement the initial design for the other pages |
| based on the <a href="design.html#mockups">mockups</a>. To accomplish this, |
| follow the pattern outlined above, namely:</p> |
| |
| <ol style="margin: 5px 0 0 -.7em"> |
| <li>Create <code><div></code> tags for the main page areas.</li> |
| <li>Iterate through each area and perform three steps: |
| |
| <ol style="margin: 5px 0 0 -1.4em; list-style-type: lower-alpha"> |
| <li>Create the structure in HTML.</li> |
| <li>Create a set of styles to define the appearance.</li> |
| <li>View the page to examine the results of your changes.</li> |
| </ol></li> |
| </ol> |
| |
| <p>Be sure to take advantage of the HTML and CSS support that the IDE provides for you. |
| Some <a href="#tipsTricks">tips and tricks</a> are outlined below. If you just want |
| to grab the code for the remaining pages and proceed with the tutorial, you can |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot1.zip">download |
| snapshot 1 of the <code>AffableBean</code> project</a>. Images of initial mockup |
| implementations for the remaining pages are included here.</p> |
| |
| <div class="indent"> |
| <h4 id="categoryPage">category page</h4> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/category-page.png" |
| class="margin-around b-all" alt="Category page displayed in browser" style="width:708px" |
| title="Placeholders implemented for category page"> |
| <br><br> |
| |
| <h4 id="cartPage">cart page</h4> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/cart-page.png" |
| class="margin-around b-all" alt="Cart page displayed in browser" style="width:708px" |
| title="Placeholders implemented for cart page"> |
| <br><br> |
| |
| <h4 id="checkoutPage">checkout page</h4> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/checkout-page.png" |
| class="margin-around b-all" alt="Checkout page displayed in browser" style="width:708px" |
| title="Placeholders implemented for checkout page"> |
| <br><br> |
| |
| <h4>confirmation page</h4> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/confirmation-page.png" |
| class="margin-around b-all" alt="Confirmation page displayed in browser" style="width:708px" |
| title="Placeholders implemented for checkout page"> |
| <br><br> |
| |
| <p class="notes"><strong>Note:</strong> The background colors for each page area only |
| serve to help you position elements while developing the application. Eventually, |
| you'll want to remove them from the stylesheet and apply a background color more |
| suitable for the application. You can do this by adjusting the background rule for |
| the <code>main</code> class:</p> |
| |
| <div class="indent"> |
| <pre class="examplecode">#main { background: #f7f7e9 }</pre> |
| </div> |
| |
| |
| <h3 id="tipsTricks">Tips and Tricks</h3> |
| |
| <p>The IDE's editor provides many facilities that help you to work more efficiently. |
| If you familiarize yourself with keyboard shortcuts and buttons in the editor |
| toolbar, you can increase your productivity. The following list of tips applies |
| to the editor for HTML and CSS files. To view more keyboard shortcuts, open the |
| IDE's Keyboard Shortcuts Card by choosing Help > Keyboard Shortcuts Card from |
| the main menu.</p> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><strong>Code completion:</strong> When you type in tags and attributes, suggestions |
| for code completion automatically appear in a pop-up box. Pressing Enter completes |
| the suggested tag.</li> |
| |
| <li><strong>Format your code:</strong> Right-click in the editor and choose Format.</li> |
| |
| <li><strong>Toggle line numbers:</strong> Right-click in the left margin and choose |
| Show Line Numbers.</li> |
| |
| <li><strong>Find occurrences:</strong> Highlight a block of text, and press Ctrl-F |
| (⌘-F on Mac). All matches become highlighted in the editor. To toggle |
| highlighting, press the Toggle Highlight Search ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/toggle-highlight.png" |
| alt="Toggle Highlight Search button" class="b-all"> ) button (Ctrl-Shift-H) |
| in the editor's toolbar.</li> |
| |
| <li><strong>Create a bookmark:</strong> Press the Toggle Bookmark ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/toggle-bookmark.png" |
| alt="Toggle Bookmark button" class="b-all"> ) button (Ctrl-Shift-M) to |
| create a bookmark in the editor's left margin. Wherever you are in the file, |
| you can then jump to the bookmark by pressing the Previous/Next Bookmark |
| buttons in the editors's toolbar.</li> |
| |
| <li><strong>Copy a code snippet up or down:</strong> Highlight a code snippet, |
| then press Ctrl-Shift-Up/Down.</li> |
| |
| <li><strong>Highlight opening and closing tags:</strong> Place your cursor on either |
| the opening or closing tag, and both are highlighted in yellow.</li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2 id="view">Placing JSP Pages in WEB-INF</h2> |
| |
| <p>Looking back at the <a href="design.html#mockups">page mockups</a> that were created, |
| you can see that the <a href="design.html#index">welcome page</a> should look the same |
| whenever it is requested, for whomever requests it. That is, the content that displays |
| on the welcome page is not determined by a user's <em>session</em>. (Sessions are |
| discussed in Unit 8, <a href="#manage-sessions">Managing Sessions</a>.) Notice |
| however that all other pages do need some form of user-specific information to display |
| properly. For example, the <a href="design.html#category">category page</a> requires |
| that the user select a category in order to display, and the <a href="design.html#cart">cart |
| page</a> needs to know all items currently held in a shopper's cart. These pages will |
| not render properly if the server isn't able to associate user-specific information with |
| an incoming request. Therefore, we do not want these pages to be accessed directly from |
| a browser's address bar. The project's <code>WEB-INF</code> folder can be used for this |
| purpose: any resources contained in the <code>WEB-INF</code> folder are not directly |
| accessible from a browser.</p> |
| |
| <p>Create a new folder named <code>view</code>, and place it in the <code>WEB-INF</code> |
| folder. Then move all JSP pages other than the welcome page into this new folder.</p> |
| |
| <ol> |
| <li>In the Projects window, right-click the WEB-INF node and choose New > Folder.</li> |
| |
| <li>In the New Folder wizard, name the folder <code>view</code> and click Finish. |
| Notice that a new folder node appears in the Projects window.</li> |
| |
| <li>Move the <code>category.jsp</code>, <code>cart.jsp</code>, <code>checkout.jsp</code>, |
| and <code>confirmation.jsp</code> pages into the <code>view</code> folder. |
| |
| <br><br> |
| You can do this by clicking on <code>cart.jsp</code> to select it, then Shift-clicking |
| on <code>confirmation.jsp</code>. This selects the four files. Then, with the four |
| files selected, click and drag them into the <code>WEB-INF/view</code> folder. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/view-folder.png" |
| class="margin-around b-all" alt="Projects window displaying JSP pages being dragged into 'view' folder" |
| title="Click and drag the JSP pages into the 'WEB-INF/view/' folder"></li> |
| </ol> |
| |
| <p>To demonstrate that these pages are no longer accessible from a browser, click the |
| Run Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) button to run the project. When the application displays in |
| your browser, enter the full path to any of these files in the address bar. For example, |
| type in:</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:700px">http://localhost:8080/AffableBean/WEB-INF/view/category.jsp</pre> |
| </div> |
| |
| <p>You receive an HTTP Status 404 message, indicating that the resource is not available.</p> |
| |
| |
| <br> |
| <h2 id="jspf">Creating a Header and Footer</h2> |
| |
| <p>Looking at the <a href="design.html#mockups">page mockups</a>, it is easy to see |
| that all of the five views share identical content; at the top, they contain the |
| company logo, a language toggle, and other widgets associated with shopping cart |
| functionality. At the bottom, they contain some text with Privacy Policy and |
| Contact links. Rather than including this code in each page source file, we can |
| factor it out into two JSP fragments: a header and a footer. We'll then include |
| the fragment files into page views whenever they need to be rendered.</p> |
| |
| <p>For these fragments, let's create a new folder named <code>jspf</code>, and place |
| it within <code>WEB-INF</code>.</p> |
| |
| <ol> |
| <li>In the Projects window, right-click the WEB-INF node and choose New > Folder.</li> |
| |
| <li>In the New Folder wizard, name the folder <code>jspf</code> and click Finish. |
| |
| <br><br> |
| <p class="tips">Menu items provided by the IDE are often context-sensitive. |
| For example, because you right-clicked the WEB-INF node, when the New Folder |
| wizard displayed, <code>web/WEB-INF</code> was automatically entered in the |
| Parent Folder field. Likewise, when you right-click a node in the Projects |
| window and choose New, the list of file types is partially determined by |
| your previous selections.</p> |
| </li> |
| |
| <li>Create two JSP segments: <code>header.jspf</code> and <code>footer.jspf</code>. |
| To do so, right-click the newly created <code>jspf</code> folder and choose New |
| > JSP. In the New JSP wizard, enter the file name, and under Options, select |
| the Create as a JSP Segment option, then click Finish. |
| |
| <br><br> |
| When you finish, you'll see <code>header.jspf</code> and <code>footer.jspf</code> |
| displayed in your Projects window: |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/projects-win-jspf.png" |
| class="margin-around b-all" alt="Projects window displaying JSP fragments" |
| title="Header and footer JSP fragments are displayed in the project"> |
| |
| <br><br> |
| Now, you can copy the header code from any of the JSP pages and paste it into the |
| <code>header.jspf</code> file. Likewise, you can copy the footer code from any of |
| the JSP pages and paste it into the <code>footer.jspf</code> file. When you finish |
| this task, you can remove the header and footer code from all of the JSP pages.</li> |
| |
| <li>Copy the header code from any of the JSP pages and paste it into the |
| <code>header.jspf</code> file. The header should include the page doctype |
| and the opening <code><html></code>, <code><head></code>, and |
| <code><body></code> tags through to the closing tag for the |
| <code><div id="header"></code> element. Be sure to include |
| placeholders for the shopping cart widget, language toggle, and 'proceed to |
| checkout' button used along the top of page views. After you paste code into |
| <code>header.jspf</code>, the file will look as follows. |
| |
| <pre class="examplecode"> |
| <%@page contentType="text/html" pageEncoding="UTF-8"%> |
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
| "http://www.w3.org/TR/html4/loose.dtd"> |
| |
| <html> |
| <head> |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| <link rel="stylesheet" type="text/css" href="css/affablebean.css"> |
| <title>The Affable Bean</title> |
| </head> |
| <body> |
| <div id="main"> |
| <div id="header"> |
| <div id="widgetBar"> |
| |
| <div class="headerWidget"> |
| [ language toggle ] |
| </div> |
| |
| <div class="headerWidget"> |
| [ checkout button ] |
| </div> |
| |
| <div class="headerWidget"> |
| [ shopping cart widget ] |
| </div> |
| |
| </div> |
| |
| <a href="#"> |
| <img src="#" id="logo" alt="Affable Bean logo"> |
| </a> |
| |
| <img src="#" id="logoText" alt="the affable bean"> |
| </div></pre></li> |
| |
| <li>Copy the footer code from any of the JSP pages and paste it into the <code>footer.jspf</code> |
| file. The footer code should include the <code><div id="footer"></code> |
| element, through to the closing <code><html></code> tag. After you paste code into |
| <code>footer.jspf</code>, the file will look as follows. |
| |
| <pre class="examplecode"> |
| <div id="footer"> |
| <hr> |
| <p id="footerText">[ footer text ]</p> |
| </div> |
| </div> |
| </body> |
| </html></pre></li> |
| |
| <li>Remove the header and footer code from all five JSP pages (<code>index.jsp</code>, |
| <code>category.jsp</code>, <code>cart.jsp</code>, <code>checkout.jsp</code>, |
| and <code>confirmation.jsp</code>).</li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="dd">Adding a Directive to the Deployment Descriptor</h2> |
| |
| <p>So far, you've placed views in their proper location and have factored out |
| common header and footer code into the <code>header.jspf</code> and |
| <code>footer.jspf</code> files. The application still needs to know which |
| pages the header and footer files will be applied to. You could add |
| <code><jsp:include></code> tags to each of the page views. Doing so |
| however would just reintroduce the code repetition which we've just made |
| efforts to eliminate. An alternative solution would be to create a <code>web.xml</code> |
| deployment descriptor, and add a JSP Property Group directive to specify |
| which page views the header and footer fragments should apply to.</p> |
| |
| <ol> |
| <li>Press Ctrl-N (⌘-N on Mac) to open the New File wizard. Select the Web |
| category, then under File Types, select Standard Deployment Descriptor (web.xml).</li> |
| |
| <li>Click Next. Note that the file is named <code>web.xml</code>, and that the |
| wizard will place it in the project's <code>WEB-INF</code> directory upon completion.</li> |
| |
| <li>Click Finish. The <code>web.xml</code> file is created and added to the project. |
| The IDE's graphical interface for the deployment descriptor opens in the editor. |
| |
| <br><br> |
| The interface is categorized by the areas that can be configured in a web application. |
| These areas are displayed as tabs in the editor toolbar, and include topics such |
| as Servlets, Filters, References, and Security. The XML tab displays the entire |
| source code for the file. Any changes you make in the graphical interface will |
| cause immediate updates to the deployment descriptor's source code, which you |
| can verify by switching to the XML tab. This is demonstrated in the following steps.</li> |
| |
| <li>Click the Pages tab, then click the Add JSP Property Group button. The |
| Add JSP Property Group dialog opens.</li> |
| |
| <li>Type in '<code>header and footer settings</code>' for the Description field. |
| Leave Display Name blank. Both the Display Name and Description fields are |
| optional.</li> |
| |
| <li>For URL Patterns, specify the paths to the five views. Type in |
| '<code>/index.jsp</code>' and '<code>/WEB-INF/view/*</code>'. Separate the |
| two paths with a comma. (The '<code>*</code>' is a wildcard that represents |
| all files within the given folder.) |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/add-jsp-prop-group-dialog.png" |
| class="margin-around b-all" alt="Add JSP Property Group dialog" |
| title="Use the Add JSP Property Group dialog to specify <jsp-config> tags in the deployment descriptor"></li> |
| |
| <li>Click OK. An entry is added to the JSP Properties Groups category in the Pages tab.</li> |
| |
| <li>Switch back to the XML tab. Notice that the following code has been added to |
| the deployment descriptor. |
| |
| <pre class="examplecode"> |
| <jsp-config> |
| <jsp-property-group> |
| <description>header and footer settings</description> |
| <url-pattern>/index.jsp</url-pattern> |
| <url-pattern>/WEB-INF/view/*</url-pattern> |
| </jsp-property-group> |
| </jsp-config></pre> |
| |
| <p class="notes"><strong>Note:</strong> You may need to add carriage returns |
| to the code so that it displays on multiple lines. You can right-click in |
| the editor and choose Format (Alt-Shift-F; Ctrl-Shift-F on Mac) to have the |
| code properly indented.</p></li> |
| |
| <li>Switch to the Pages tab again, and in the Include Preludes and Include Codas |
| fields, enter the paths to the <code>header.jspf</code> and <code>footer.jspf</code> |
| files, respectively. You can click the Browse button and navigate to the files |
| in the provided dialog. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/jsp-prop-groups.png" |
| title="Enter paths to the header and footer in the JSP Property Group" rel="lytebox"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/jsp-prop-groups-small.png" |
| class="margin-around b-all" alt="JSP Property Group shown under Pages tab of web.xml" title="Click to enlarge"></a></li> |
| |
| <li>Switch back to the XML tab. Note that the following code has been added. |
| (Changes in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <jsp-config> |
| <jsp-property-group> |
| <description>header and footer settings</description> |
| <url-pattern>/index.jsp</url-pattern> |
| <url-pattern>/WEB-INF/view/*</url-pattern> |
| <strong><include-prelude>/WEB-INF/jspf/header.jspf</include-prelude> |
| <include-coda>/WEB-INF/jspf/footer.jspf</include-coda></strong> |
| </jsp-property-group> |
| </jsp-config></pre> |
| |
| The above directive specifies that for all files found within the |
| given <code>url-pattern</code>s, the <code>header.jspf</code> file |
| will be prepended, and the <code>footer.jspf</code> file appended. |
| |
| <br><br> |
| <p class="tips">To view the definitions of the above tags, as well as |
| all tags available to you in the web deployment descriptor, consult the |
| <a href="http://jcp.org/en/jsr/detail?id=315" target="_blank">Servlet |
| Specification</a>.</p></li> |
| |
| <li>Run the application again (press F6; fn-F6 on Mac). You've already removed |
| the header and footer code from the <code>index.jsp</code> file, so you can |
| determine whether it is automatically being added when the file is requested. |
| |
| <br><br> |
| You will see that the <a href="#welcome-page">welcome page displays as it |
| did previously</a>, with header and footer content included.</li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="controller">Creating the Controller Servlet</h2> |
| |
| <p>The controller servlet handles incoming requests by initiating any actions |
| needed to generate the model for the request, then forwarding the request |
| to the appropriate view. For a visual representation, refer back to the |
| <a href="design.html#mvcDiagram">MVC diagram for the AffableBean project</a>.</p> |
| |
| <p>The IDE provides a Servlet wizard that enables you to define the servlet component |
| in a web application either by including the <code>@WebServlet</code> annotation |
| in the generated class, or by adding the necessary directives to the deployment |
| descriptor. In the following steps, you create the <code>ControllerServlet</code> |
| and define it in the application context using the |
| <a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/annotation/WebServlet.html" target="_blank"><code>@WebServlet</code></a> |
| annotation.</p> |
| |
| <ol> |
| <li>In the Projects window, right-click the <code>AffableBean</code> project |
| node and choose New > Servlet.</li> |
| |
| <li>In the wizard, type <code>ControllerServlet</code> in the Class Name field.</li> |
| |
| <li>In the Package field, type <code>controller</code>. (The new package is |
| automatically created when you complete the wizard.) |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/servlet-wizard.png" |
| class="margin-around b-all" alt="Servlet wizard" |
| title="Use the Servlet wizard to create servlets for your project"></li> |
| |
| <li>Click Next. Step 3 of the wizard lets you configure the servlet. Of primary |
| importance are the URL patterns that you need to specify. The patterns identify |
| the URLs that invoke the servlet. For example, if you enter '<code>/category</code>', |
| you are directing the servlet to handle a request that appears as follows. |
| |
| <pre class="examplecode">http://localhost/AffableBean<strong>/category</strong></pre> |
| |
| The URL patterns should correspond to the views and actions that a user can initiate. |
| Looking at the <a href="design.html#index">welcome page mockup</a>, a user should |
| be able to select a category. We can therefore associate the <code>/category</code> |
| URL with the action of clicking on a category image. Likewise, in the |
| <a href="design.html#category">category page</a>, users should be able to |
| add an item to the shopping cart. We can therefore specify <code>/addToCart</code>.</li> |
| |
| <li>In the URL Pattern(s) field, type in '<code>/category, /addToCart, /viewCart</code>'. |
| Patterns are separated by commas. You can add more patterns directly in the servlet |
| class once it's created. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/servlet-wizard2.png" |
| class="margin-around b-all" alt="Servlet wizard, Step 3: Configure Servlet Deployment" |
| title="Configure servlet deployment directly in the wizard"></li> |
| |
| <li>Click Finish. The IDE generates the <code>ControllerServlet</code> and opens it |
| in the editor. The servlet and URL patterns are included in the <code>@WebServlet</code> |
| annotation that appears above the class signature. |
| |
| <pre class="examplecode"> |
| <strong>@WebServlet(name="ControllerServlet", urlPatterns={"/category", "/addToCart", "/viewCart"})</strong> |
| public class ControllerServlet extends HttpServlet {</pre> |
| |
| In the previous step, if you had chosen the '<code>Add information to deployment |
| descriptor (web.xml)</code>' option in the wizard, the following markup would have |
| been generated in the application's <code>web.xml</code> file instead. |
| |
| <pre class="examplecode"> |
| <servlet> |
| <servlet-name>ControllerServlet</servlet-name> |
| <servlet-class>controller.ControllerServlet</servlet-class> |
| </servlet> |
| <servlet-mapping> |
| <servlet-name>ControllerServlet</servlet-name> |
| <url-pattern>/category</url-pattern> |
| </servlet-mapping> |
| <servlet-mapping> |
| <servlet-name>ControllerServlet</servlet-name> |
| <url-pattern>/addToCart</url-pattern> |
| </servlet-mapping> |
| <servlet-mapping> |
| <servlet-name>ControllerServlet</servlet-name> |
| <url-pattern>/viewCart</url-pattern> |
| </servlet-mapping></pre></li> |
| |
| <li>Add other URL patterns directly to the <code>@WebServlet</code> annotation's |
| <code>urlPatterns</code> element. The application requires more URL patterns |
| for other actions and views. You can type in the following patterns: |
| |
| <ul class="toc" style="margin: 5px 0 0 -1em"> |
| <li><code>/updateCart</code></li> |
| <li><code>/checkout</code></li> |
| <li><code>/purchase</code></li> |
| <li><code>/chooseLanguage</code></li> |
| </ul> |
| |
| Be sure to separate each pattern with a comma. You can also reformat the |
| annotation as follows: |
| |
| <pre class="examplecode"> |
| @WebServlet(name="ControllerServlet", |
| urlPatterns = {"/category", |
| "/addToCart", |
| "/viewCart"<strong>, |
| "/updateCart", |
| "/checkout", |
| "/purchase", |
| "/chooseLanguage"</strong>})</pre></li> |
| |
| <li>Finally, include the <code>loadOnStartup</code> element so that the servlet |
| is instantiated and initialized when the application is deployed. A value of <code>0</code> |
| or greater will cause this to happen (<code>-1</code> is the default). |
| |
| <pre class="examplecode"> |
| @WebServlet(name="ControllerServlet", |
| <strong>loadOnStartup = 1,</strong> |
| urlPatterns = {"/category", |
| "/addToCart", |
| "/viewCart", |
| "/updateCart", |
| "/checkout", |
| "/purchase", |
| "/chooseLanguage"})</pre></li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="implement">Implementing the Controller Servlet</h2> |
| |
| <p>As previously stated, the controller servlet handles incoming requests by initiating |
| any actions needed to generate the model for the request, then forwarding the request |
| to the appropriate view. For a visual representation, refer back to the |
| <a href="design.html#mvcDiagram">MVC diagram for the AffableBean project</a>.</p> |
| |
| <p>Looking at the generated code for the new <code>ControllerServlet</code>, you |
| can see that the IDE's servlet template employs a <code>processRequest</code> |
| method which is called by both <code>doGet</code> and <code>doPost</code> |
| methods. (You may need to expand the code fold by clicking the plus icon ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/code-fold-icon.png" |
| alt="Code fold icon"> ) in the editor's left margin to view these methods.) Because |
| this application differentiates between <code>doGet</code> and <code>doPost</code>, |
| you'll add code directly to these methods and remove the <code>processRequest</code> |
| method altogether.</p> |
| |
| <div class="indent"> |
| <div class="feedback-box float-left" style="width: 703px;"> |
| |
| <h3>Modifying File Templates with the IDE's Template Manager</h3> |
| |
| <p>The IDE provides you with a basic template for any new file you create. |
| If the template is not optimal for your work patterns, you can alter it |
| using the IDE's Template Manager. The IDE provides a template for virtually |
| any file type.</p> |
| |
| <p>For example, to modify the servlet template:</p> |
| |
| <ol> |
| <li>Open the Template Manager by choosing Tools > Templates from |
| the main menu.</li> |
| |
| <li>Expand the Web category, then select the Servlet template. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/template-manager.png" |
| class="margin-around b-all" title="Access and modify file templates via the Template Manager" |
| alt="Template Manager"/></li> |
| |
| <li>Click the Open in Editor button.</li> |
| |
| <li>Modify the template in the editor. The next time you create a new |
| servlet (e.g., using the Servlet wizard), the new version will be |
| applied.</li> |
| </ol> |
| </div> |
| </div> |
| <br style="clear: both;"/> |
| |
| <br> |
| <p>Now that you've mapped URL patterns to the servlet using the <code>@WebServlet</code> |
| annotation, set up the <code>ControllerServlet</code> to handle these patterns. Also, |
| instantiate a <code>RequestDispatcher</code> to forward the requested pattern to the |
| appropriate view.</p> |
| |
| <ol> |
| <li>Replace the <code>ControllerServlet</code> class template code with |
| the following code. |
| |
| <pre class="examplecode"> |
| public class ControllerServlet extends HttpServlet { |
| |
| /** |
| * Handles the HTTP <code>GET</code> method. |
| * @param request servlet request |
| * @param response servlet response |
| * @throws ServletException if a servlet-specific error occurs |
| * @throws IOException if an I/O error occurs |
| */ |
| @Override |
| protected void doGet(HttpServletRequest request, HttpServletResponse response) |
| throws ServletException, IOException { |
| |
| String userPath = request.getServletPath(); |
| |
| // if category page is requested |
| if (userPath.equals("/category")) { |
| // TODO: Implement category request |
| |
| // if cart page is requested |
| } else if (userPath.equals("/viewCart")) { |
| // TODO: Implement cart page request |
| |
| userPath = "/cart"; |
| |
| // if checkout page is requested |
| } else if (userPath.equals("/checkout")) { |
| // TODO: Implement checkout page request |
| |
| // if user switches language |
| } else if (userPath.equals("/chooseLanguage")) { |
| // TODO: Implement language request |
| |
| } |
| |
| // use RequestDispatcher to forward request internally |
| String url = "/WEB-INF/view" + userPath + ".jsp"; |
| |
| try { |
| request.getRequestDispatcher(url).forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| } |
| |
| /** |
| * Handles the HTTP <code>POST</code> method. |
| * @param request servlet request |
| * @param response servlet response |
| * @throws ServletException if a servlet-specific error occurs |
| * @throws IOException if an I/O error occurs |
| */ |
| @Override |
| protected void doPost(HttpServletRequest request, HttpServletResponse response) |
| throws ServletException, IOException { |
| |
| String userPath = request.getServletPath(); |
| |
| // if addToCart action is called |
| if (userPath.equals("/addToCart")) { |
| // TODO: Implement add product to cart action |
| |
| // if updateCart action is called |
| } else if (userPath.equals("/updateCart")) { |
| // TODO: Implement update cart action |
| |
| // if purchase action is called |
| } else if (userPath.equals("/purchase")) { |
| // TODO: Implement purchase action |
| |
| userPath = "/confirmation"; |
| } |
| |
| // use RequestDispatcher to forward request internally |
| String url = "/WEB-INF/view" + userPath + ".jsp"; |
| |
| try { |
| request.getRequestDispatcher(url).forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| } |
| |
| }</pre> |
| |
| As you continue through the tutorial, you'll return to the <code>ControllerServlet</code> |
| and implement each of the mapped URL patterns individually.</li> |
| |
| <li>Examine the code above. There are several points to note: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li>The servlet uses a <code>userPath</code> instance variable to get the |
| requested URL pattern from the client: |
| |
| <pre class="examplecode" style="width: 640px">String userPath = request.getServletPath();</pre> |
| |
| <code>userPath</code> is used by both <code>doGet</code> and <code>doPost</code> |
| methods.</li> |
| |
| <li>URL patterns associated primarily with page requests are managed by the |
| <code>doGet</code> method. For example, <code>/category</code>, |
| <code>/viewCart</code>, and <code>/checkout</code> result in the display |
| of the category, cart, and checkout pages.) </li> |
| |
| <li>URL patterns associated with form submits and the transport of |
| sensitive user data (e.g., <code>/addToCart</code>, <code>/updateCart</code>, |
| and <code>/purchase</code>) are managed by the <code>doPost</code> |
| method.</li> |
| |
| <li>For both <code>doGet</code> and <code>doPost</code> methods, the path |
| to the appropriate view is formed using a <code>url</code> string: |
| |
| <pre class="examplecode" style="width: 640px">String url = "/WEB-INF/view" + userPath + ".jsp";</pre> |
| </li> |
| |
| <li>The <code>RequestDispatcher</code> is obtained from the <code>HttpServletRequest</code> |
| and applies the <code>url</code> to forward the request: |
| |
| <pre class="examplecode" style="width: 640px">request.getRequestDispatcher(url).forward(request, response);</pre> |
| </li> |
| |
| <li><code>TODO</code> notes have been used to denote work that still needs |
| to be done. For example: |
| |
| <pre class="examplecode" style="width: 640px">// if category page is requested |
| if (userPath.equals("/category")) { |
| // TODO: Implement category request</pre> |
| |
| Applying <code>TODO</code> notes in your code is a useful way to keep track |
| of tasks that you need to complete. You can use the IDE's Tasks window |
| (Ctrl-6; ⌘-6 on Mac) to view all TODO notes, as well as any syntax or |
| compile errors contained in your project. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/page-views-controller/tasks-window.png" |
| class="margin-around b-all" title="Keep track of implementation tasks with the IDE's Tasks window" |
| alt="Tasks window"/> |
| |
| <br> |
| <p class="tips">You can control the keywords that display in the Tasks window. |
| Open the Options window (Tools > Options; NetBeans > Preferences on Mac), |
| then choose Miscellaneous > Tasks.</p></li> |
| </ul> |
| </li> |
| |
| <li>Run the project (press F6; fn-F6 on Mac) and test to see whether the <code>ControllerServlet</code> |
| is forwarding requests to the appropriate views. |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li>Type in <code>http://localhost:8080/AffableBean/category</code> in the browser's |
| address bar. The application's <a href="#categoryPage">category page</a> |
| displays.</li> |
| |
| <li>Type in <code>http://localhost:8080/AffableBean/viewCart</code> in the browser's |
| address bar. The application's <a href="#cartPage">cart page</a> displays.</li> |
| |
| <li>Type in <code>http://localhost:8080/AffableBean/checkout</code> in the browser's |
| address bar. The application's <a href="#checkoutPage">checkout page</a> |
| displays.</li> |
| </ul> |
| |
| <p class="notes"><strong>Note:</strong> Entering <code>http://localhost:8080/AffableBean/purchase</code> |
| in the browser's address bar does not allow you to view the <a href="#confirmationPage">confirmation |
| page</a>. Naturally, this is because the <code>/purchase</code> URL pattern is handled |
| by the servlet's <code>doPost</code> method, and requests sent from the browser's address |
| bar are typically sent using the HTTP GET method.</p></li> |
| </ol> |
| |
| <p>At this stage, you've created JSP pages that contain placeholders for functional components. |
| You've also set up the front-end structure of the application. JSP pages now reside within |
| the <code>WEB-INF</code> folder, header and footer code has been factored out into separate |
| files, your deployment descriptor is properly configured, and you've set up the |
| <code>ControllerServlet</code> to handle incoming requests. In the next tutorial unit, you |
| take measures to enable connectivity between the application and the database.</p> |
| |
| <p>If you'd like to compare your work with the sample solution for this unit, you can |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot2.zip">download |
| snapshot 2 of the AffableBean project</a>.</p> |
| |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Preparing the Page Views and Controller Servlet">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <h2 id="seeAlsoPageViewsController">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Tutorials</h3> |
| |
| <ul> |
| <li><a href="../javaee-intro.html" target="_blank">Introduction to Java EE Technology</a></li> |
| <li><a href="../javaee-gettingstarted.html" target="_blank">Getting Started with Java EE Applications</a></li> |
| <li><a href="../../web/quickstart-webapps.html" target="_blank">Introduction to Developing Web Applications</a></li> |
| <li><a href="../../web/mysql-webapp.html" target="_blank">Creating a Simple Web Application Using a MySQL Database</a></li> |
| <li><a href="../../../../community/media.html" target="_blank">Video Tutorials and Demos for NetBeans IDE</a></li> |
| <li><a href="https://netbeans.org/projects/www/downloads/download/shortcuts.pdf">Keyboard Shortcuts & Code Templates Card</a></li> |
| <li><a href="../../../trails/java-ee.html" target="_blank">Java EE & Java Web Learning Trail</a></li> |
| </ul> |
| |
| <h3>NetBeans Books</h3> |
| |
| <ul> |
| <li><a href="https://netbeans.org/kb/articles/netbeans-tips-and-tricks-book.html" target="_blank">100 NetBeans IDE Tips and Tricks</a></li> |
| <li><a href="http://www.apress.com/book/view/1590598954" target="_blank">Pro NetBeans IDE 6 Rich Client Platform Edition</a></li> |
| <li><a href="http://apress.com/book/view/1430219548" target="_blank">Beginning Java EE 6 Platform with GlassFish 3: From Novice to Professional</a></li> |
| <li><a href="https://netbeans.org/kb/articles/books.html" target="_blank">More books about NetBeans IDE</a></li> |
| </ul> |
| |
| <h3>External Resources</h3> |
| |
| <ul> |
| <li><a href="http://jcp.org/en/jsr/detail?id=315" target="_blank">Servlet 3.0 Specification</a></li> |
| <li><a href="https://developer.mozilla.org/en/Common_CSS_Questions" target="_blank">Common CSS Questions</a></li> |
| <li><a href="http://quirksmode.org/compatibility.html" target="_blank">Browser Compatibility Master Table</a></li> |
| <li><a href="http://refcardz.dzone.com/refcardz/netbeans-ide-67-update" target="_blank">DZone Refcard for NetBeans Java Editor</a></li> |
| </ul> |
| </div> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="connect-db">The NetBeans E-commerce Tutorial - Connecting the Application to the Database</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><strong>Connecting the Application to the Database</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#sampleData">Adding Sample Data to the Database</a></li> |
| <li><a href="#createConnPoolDataSource">Creating a Connection Pool and Data Source</a></li> |
| <li><a href="#testConnPoolDataSource">Testing the Connection Pool and Data Source</a></li> |
| <li><a href="#param">Setting Context Parameters</a></li> |
| <li><a href="#jstl">Working with JSTL</a></li> |
| <li><a href="#troubleshoot">Troubleshooting</a></li> |
| <li><a href="#seeAlsoConnectDb">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>This tutorial unit focuses on communication between the database and the application. |
| You begin by adding sample data to the database and explore some of the features |
| provided by the IDE's SQL editor. You set up a data source and connection pool on |
| the GlassFish server, and proceed by creating a JSP page that tests the data source |
| by performing a simple query on the database.</p> |
| |
| <p>This unit also addresses how the application retrieves and displays images necessary |
| for web presentation, and how to set context parameters and retrieve their values from |
| web pages. Once you are certain the data source is working correctly, you apply JSTL's |
| <code>core</code> and <code>sql</code> tag libraries to retrieve and display category |
| and product images for the <a href="design.html#index">index</a> and |
| <a href="design.html#category">category</a> pages.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans E-commerce |
| Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left;"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#glassFishConnectDb">GlassFish server</a></td> |
| <td class="tbltd1">v3 or Open Source Edition 3.0.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL database server</a></td> |
| <td class="tbltd1">version 5.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot2.zip">AffableBean |
| project</a></td> |
| <td class="tbltd1">snapshot 2</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252Fimg.zip">website images</a></td> |
| <td class="tbltd1">n/a</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><strong class="notes">Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which |
| are required for the application you build in this tutorial.</li> |
| |
| <li id="glassFishConnectDb">The NetBeans IDE Java Bundle also includes the GlassFish server, |
| which you require for this tutorial. You could |
| <a href="http://glassfish.dev.java.net/public/downloadsindex.html" target="_blank">download |
| the GlassFish server independently</a>, but the version provided with the |
| NetBeans download has the added benefit of being automatically registered |
| with the IDE.</li> |
| |
| <li>You can follow this tutorial unit without having completed previous units. To |
| do so, perform the following three steps: |
| |
| <ol style="margin: 5px 0 0 -1.5em"> |
| <li><strong>Set up your MySQL database server.</strong> Follow the steps |
| outlined in: <a href="setup-dev-environ.html#communicate">Communicating |
| with the Database Server</a>.</li> |
| |
| <li><strong>Create the <code>affablebean</code> schema on the database server.</strong> |
| |
| <ol style="list-style-type: lower-alpha; margin-top: 5px; margin-left: -1.5em"> |
| <li>Click on <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252Faffablebean_schema_creation.sql">affablebean_schema_creation.sql</a> |
| and copy (Ctrl-C; ⌘-C on Mac) the entire contents of the file.</li> |
| |
| <li>Open the IDE's SQL editor. In the Services window (Ctrl-5; ⌘-5 on Mac), |
| right-click the <code>affablebean</code> database connection ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/db-connection-node.png" |
| alt="Database connection node"> ) node and choose Execute Command. The |
| IDE's SQL editor opens.</li> |
| |
| <li>Paste (Ctrl-V; ⌘-V on Mac) the entire contents of the <code>affablebean.sql</code> |
| file into the editor.</li> |
| |
| <li>Click the Run SQL ( <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-sql-btn.png" |
| alt="Run SQL button"> ) button in the editor's toolbar. The script runs on your |
| MySQL server. Tables are generated for the <code>affablebean</code> database.</li> |
| </ol></li> |
| |
| <li>Open the <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot2.zip">project |
| snapshot</a> in the IDE. In the IDE, press Ctrl-Shift-O (⌘-Shift-O on Mac) and |
| navigate to the location on your computer where you unzipped the downloaded file.</li> |
| </ol> |
| </li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="sampleData">Adding Sample Data to the Database</h2> |
| |
| <p>Begin by adding sample data to the <code>category</code> and <code>product</code> |
| tables. You can do this using the IDE's SQL editor, which allows you to interact |
| directly with the database using native SQL. The IDE's SQL support also includes |
| a GUI editor that enables you to add, remove, modify and delete table records.</p> |
| |
| <ul> |
| <li><a href="#category">category table</a></li> |
| <li><a href="#product">product table</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="category">category table</h3> |
| |
| <ol> |
| <li>In the Services window (Ctrl-5; ⌘-5 on Mac), right-click the |
| <code>category</code> table ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/db-table-node.png" |
| alt="database table node"> ) node and choose View Data. The SQL |
| editor opens and displays with a GUI representation of the <code>category</code> |
| table in the lower region. Note that the table is empty, as no data has |
| yet been added. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/category-table-empty.png" |
| class="margin-around b-all" alt="Empty category table displayed in SQL editor" |
| title="Use the SQL editor to view table data in the IDE"> |
| |
| <br> |
| Also, note that the native SQL query used to generate the GUI representation |
| is displayed in the upper region of the editor: '<code>select * from category</code>'.</li> |
| |
| <li>Delete '<code>select * from category</code>' and enter the following SQL statement: |
| |
| <pre class="examplecode">INSERT INTO `category` (`name`) VALUES ('dairy'),('meats'),('bakery'),('fruit & veg');</pre> |
| |
| This statement inserts four new records, each with a unique entry for the |
| '<code>name</code>' column. Because the <code>id</code> column was specified |
| as <code>AUTO_INCREMENT</code> when you created the schema, you do not need |
| to worry about supplying a value.</li> |
| |
| <li>Click the Run SQL ( <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-sql-btn.png" |
| alt="Run SQL button"> ) button in the editor's toolbar. The SQL statement is |
| executed.</li> |
| |
| <li>To confirm that the data has been added, run the '<code>select * from category</code>' |
| query again. To do so, you can use the SQL History window. Click the SQL History ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/sql-history-btn.png" |
| alt="SQL History button"> ) button in the editor's toolbar and double-click |
| the '<code>select * from category</code>' entry. The SQL History window lists |
| all SQL statements that you recently executed in the IDE.</li> |
| </ol> |
| |
| <br> |
| <p class="tips">Watch the screencast below to see how you can follow the above steps. |
| When typing in the editor, be sure to take advantage of the IDE's code completion |
| and suggestion facilities.</p> |
| |
| <br> |
| <script src="/images_www/js/mediaplayer-5.9/jwplayer.js" type="text/javascript"></script> |
| |
| <div id="player" > |
| <center> |
| <div id="flashContent"></div> |
| </center> |
| </div> |
| <script type="text/javascript"> |
| $(function(){ |
| var targetFile='http://bits.netbeans.org/media/nb-sql-editor.flv'; |
| jwplayer('flashContent').setup({ |
| 'id': 'flashContentId', |
| 'width': '530', |
| 'height': '340', |
| 'autostart': 'false', |
| 'file': targetFile, |
| 'controlbar':{position:'bottom'}, |
| 'modes': [ |
| {type: 'html5'}, |
| {type: 'flash', src: '/images_www/js/mediaplayer-5.9/player.swf'}, |
| {type: 'download'} |
| ] |
| }); |
| }); |
| </script> |
| |
| <br><br> |
| <h3 id="product">product table</h3> |
| |
| <ol> |
| <li>Right-click the <code>product</code> table ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/db-table-node.png" |
| alt="database table node"> ) node and choose Execute Command. Choosing the Execute |
| Command menu option in the Services window opens the SQL editor in the IDE.</li> |
| |
| <li>Copy and paste the following <code>INSERT</code> statements into the editor. |
| |
| <pre class="examplecode"> |
| -- |
| -- Sample data for table `product` |
| -- |
| |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('milk', 1.70, 'semi skimmed (1L)', 1); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('cheese', 2.39, 'mild cheddar (330g)', 1); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('butter', 1.09, 'unsalted (250g)', 1); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('free range eggs', 1.76, 'medium-sized (6 eggs)', 1); |
| |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('organic meat patties', 2.29, 'rolled in fresh herbs<br>2 patties (250g)', 2); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('parma ham', 3.49, 'matured, organic (70g)', 2); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('chicken leg', 2.59, 'free range (250g)', 2); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('sausages', 3.55, 'reduced fat, pork<br>3 sausages (350g)', 2); |
| |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('sunflower seed loaf', 1.89, '600g', 3); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('sesame seed bagel', 1.19, '4 bagels', 3); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('pumpkin seed bun', 1.15, '4 buns', 3); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('chocolate cookies', 2.39, 'contain peanuts<br>(3 cookies)', 3); |
| |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('corn on the cob', 1.59, '2 pieces', 4); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('red currants', 2.49, '150g', 4); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('broccoli', 1.29, '500g', 4); |
| INSERT INTO `product` (`name`, price, description, category_id) VALUES ('seedless watermelon', 1.49, '250g', 4); |
| </pre> |
| |
| Examine the above code and note the following points: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li>By examining the |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252Faffablebean_schema_creation.sql"><code>affablebean</code> |
| schema generation script</a>, you'll note that the <code>product</code> |
| table contains a non-nullable, automatically incremental primary key. |
| Whenever you insert a new record into the table (and don't explicitly |
| set the value of the primary key), the SQL engine sets it for you. |
| Also, note that the <code>product</code> table's <code>last_update</code> |
| column applies <code>CURRENT_TIMESTAMP</code> as its default value. |
| The SQL engine will therefore provide the current date and time for |
| this field when a record is created. |
| |
| <br><br> |
| Looking at this another way, if you were to create an <code>INSERT</code> |
| statement that didn't indicate which columns would be affected by the |
| insertion action, you would need to account for all columns. In this |
| case, you could enter a <code>NULL</code> value to enable the SQL engine |
| to automatically handle fields that have default values specified. For |
| example, the following statement elicits the same result as the first |
| line of the above code: |
| |
| <pre class="examplecode" style="width:662px">INSERT INTO `product` VALUES (NULL, 'milk', 1.70, 'semi skimmed (1L)', NULL, 1);</pre> |
| |
| After running the statement, you'll see that the record contains an |
| automatically incremented primary key, and the <code>last_update</code> |
| column lists the current date and time.</li> |
| |
| <li>The value for the final column, '<code>category_id</code>', must |
| correspond to a value contained in the <code>category</code> table's |
| <code>id</code> column. Because you have already added four records |
| to the <code>category</code> table, the <code>product</code> records |
| you are inserting reference one of these four records. If you try to |
| insert a <code>product</code> record that references a <code>category_id</code> |
| that doesn't exist, a foreign key constraint fails.</li> |
| </ul></li> |
| |
| <li>Click the Run SQL ( <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-sql-btn.png" |
| alt="Run SQL button"> ) button in the editor's toolbar. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> View the Output window (Ctrl-4; ⌘-4 |
| on Mac) to see a log file containing results of the execution.</p></li> |
| |
| <li>Right-click the <code>product</code> table ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/db-table-node.png" |
| alt="database table node"> ) node and choose View Data. You can see 16 new records |
| listed in the table. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/product-table.png" |
| class="margin-around b-all" alt="16 new records displayed in SQL editor's 'product' table" |
| title="Choose View Data from a table node's right-click menu to verify sample data" |
| style="width:688px"> |
| |
| |
| <br> |
| <div class="feedback-box float-left" style="width: 683px;"> |
| |
| <h3>NetBeans GUI Support for Database Tables</h3> |
| |
| <p>In the Services window, when you right-click a table ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/db-table-node.png" |
| alt="database table node"> ) node and choose View Data, the IDE displays |
| a visual representation of the table and the data it contains (as depicted |
| in the image above). You can also use this GUI support to add, modify, and |
| delete table data.</p> |
| |
| <ul> |
| <li><strong>Add new records:</strong> To add new records, click the Insert |
| Record ( <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/insert-record-btn.png" |
| alt="Insert Record button"> ) button. An Insert Records dialog window |
| displays, enabling you to enter new records. When you click OK, the |
| new data is committed to the database, and the GUI representation of |
| the table is automatically updated. |
| |
| <br><br> |
| <p class="tips">Click the Show SQL button within the dialog window |
| to view the SQL statement(s) that will be applied upon initiating the |
| action.</p></li> |
| |
| <li><strong>Modify records:</strong> You can make edits to existing records |
| by double-clicking directly in table cells and modifying field entries. |
| Modified entries display as <span style="color: #259125">green text</span>. |
| When you are finished editing data, click the Commit Record |
| ( <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/commit-record-btn.png" |
| alt="Commit Record button"> ) button to commit changes to the actual database. |
| (Similarly, click the Cancel Edits |
| ( <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/cancel-edits-btn.png" |
| alt="Cancel Edits button"> ) button to cancel any edits you have made.</li> |
| |
| <li><strong>Delete individual records:</strong> Click a row in the table, |
| then click the Delete Selected Record ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/delete-selected-record-btn.png" |
| alt="Delete Selected Record button"> ) button. You can also delete |
| multiple rows simultaneously by holding Ctrl (⌘ on Mac) while |
| clicking to select rows.</li> |
| |
| <li><strong>Delete all records:</strong> Deleting all records within a |
| table is referred to as '<em>truncating</em>' the table. Click the |
| Truncate Table ( <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/truncate-table-btn.png" |
| alt="Truncate Table button"> ) button to delete all records contained |
| in the displayed table.</li> |
| </ul> |
| |
| <p>If the displayed data needs to be resynchronized with the actual database, |
| you can click the Refresh Records ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/refresh-records-btn.png" |
| alt="Refresh Records button"> ) button. Note that much of the above-described |
| functionality can also be accessed from the right-click menu within the GUI |
| editor.</p> |
| </div> |
| |
| <div style="clear:left"></div> |
| </li> |
| </ol> |
| </div> |
| |
| |
| <br> |
| <h2 id="createConnPoolDataSource">Creating a Connection Pool and Data Source</h2> |
| |
| <p>From this point onward, you establish connectivity between the MySQL database and the |
| <code>affablebean</code> application through the GlassFish server which it is deployed |
| to. This communication is made possible with the Java Database Connectivity |
| (<a href="http://java.sun.com/products/jdbc/overview.html" target="_blank">JDBC</a>) API. |
| The JDBC API is an integration library contained in the JDK (refer back to the component |
| diagram displayed in the tutorial <a href="intro.html#platform">Introduction</a>). Although |
| this tutorial does not work directly with JDBC programming, the application that we are |
| building does utilize the JDBC API whenever communication is required between the SQL and |
| Java languages. For example, you start by creating a <em>connection pool</em> on the |
| GlassFish server. In order for the server to communicate directly with the the MySQL |
| database, it requires the <a href="http://www.mysql.com/downloads/connector/j/" target="_blank">Connector/J</a> |
| JDBC driver which converts JDBC calls directly into a MySQL-specific protocol. Later in |
| this tutorial unit, when you apply JSTL's |
| <a href="http://download.oracle.com/docs/cd/E17802_01/products/products/jsp/jstl/1.1/docs/tlddocs/sql/query.html" target="_blank"><code><sql:query></code></a> |
| tags to query the <code>affablebean</code> database, the tags are translated into JDBC |
| <a href="http://download-llnw.oracle.com/javase/6/docs/api/java/sql/Statement.html" target="_blank"><code>Statement</code></a>s.</p> |
| |
| <p>A connection pool contains a group of reusable connections for a particular database. |
| Because creating each new physical connection is time-consuming, the server maintains |
| a pool of available connections to increase performance. When an application requests |
| a connection, it obtains one from the pool. When an application closes a connection, |
| the connection is returned to the pool. Connection pools use a JDBC driver to create |
| physical database connections.</p> |
| |
| <p>A data source (a.k.a. a JDBC resource) provides applications with the means of connecting |
| to a database. Applications get a database connection from a connection pool by looking |
| up a data source using the Java Naming and Directory Interface |
| (<a href="http://www.oracle.com/technetwork/java/overview-142035.html" target="_blank">JNDI</a>) |
| and then requesting a connection. The connection pool associated with the data source |
| provides the connection for the application.</p> |
| |
| <p>In order to enable the application access to the <code>affablebean</code> database, |
| you need to create a connection pool and a data source that uses the connection pool. |
| Use the NetBeans GlassFish JDBC Resource wizard to accomplish this.</p> |
| |
| <p class="notes"><strong>Note:</strong> You can also create connection pools and data |
| sources directly on the GlassFish server using the GlassFish Administration Console. |
| However, creating these resources in this manner requires that you manually enter |
| database connection details (i.e., username, password and URL). The benefit of using |
| the NetBeans wizard is that it extracts any connection details directly from an |
| existing database connection, thus eliminating potential connectivity problems.</p> |
| |
| <p class="tips">To access the console from the IDE, in the Services window right-click |
| the Servers > GlassFish node and choose View Admin Console. The default username / password |
| is: <code>admin</code> / <code>adminadmin</code>. If you'd like to set up the connection |
| pool and data source using the GlassFish Administration console, follow steps 3-15 of |
| the <a href="#setup">NetBeans E-commerce Tutorial Setup Instructions</a>. The setup |
| instructions are provided for later tutorial units.</p> |
| |
| <ol> |
| <li>Click the New File ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/new-file-btn.png" |
| alt="New File button"> ) button in the IDE's toolbar. (Alternatively, press Ctrl-N; |
| ⌘-N on Mac.)</li> |
| |
| <li>Select the <strong>GlassFish</strong> category, then select <strong>JDBC Resource</strong> |
| and click Next.</li> |
| |
| <li>In Step 2 of the JDBC Resource wizard, select the <code>Create New JDBC Connection Pool</code> |
| option. When you do so, three new steps are added to the wizard, enabling you to specify |
| connection pool settings.</li> |
| |
| <li>Enter details to set up the data source: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><strong>JNDI Name:</strong> <code>jdbc/affablebean</code> |
| |
| <br><span class="tips" style="line-height: 25px">By convention, the JNDI name for |
| a JDBC resource begins with the '<code>jdbc/</code>' string.</span></li> |
| |
| <li><strong>Object Type:</strong> <code>user</code></li> |
| |
| <li><strong>Enabled:</strong> <code>true</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/jdbc-resource-gen-attributes.png" |
| class="margin-around b-all" style="width:688px" alt="JDBC Resource wizard - General Attributes" |
| title="Create a new connection pool and data source using the JDBC Resource wizard"> |
| </li> |
| |
| <li>Click Next. In Step 3, Additional Properties, you do not need to specify any additional |
| configuration information for the data source.</li> |
| |
| <li>Click Next. In Step 4, Choose Database Connection, type in <code>AffableBeanPool</code> |
| as the JDBC connection pool name. Also, ensure that the <code>Extract from Existing |
| Connection</code> option is selected, and that the <code>jdbc:mysql://localhost:3306/affablebean</code> |
| connection is listed.</li> |
| |
| <li>Click Next. In Step 5, Add Connection Pool Properties, specify the following details: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><strong>Datasource Classname:</strong> <code>com.mysql.jdbc.jdbc2.optional.MysqlDataSource</code></li> |
| <li><strong>Resource Type:</strong> <code>javax.sql.ConnectionPoolDataSource</code></li> |
| <li><strong>Description:</strong> <em>(Optional)</em> <code>Connects to the affablebean database</code></li> |
| </ul> |
| |
| Also, note that the wizard extracts and displays properties from the existing connection. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/jdbc-resource-conn-pool.png" |
| class="margin-around b-all" style="width:688px" alt="JDBC Resource wizard - Add Connection Pool" |
| title="Create a new connection pool and data source using the JDBC Resource wizard"></li> |
| |
| <li>Click Finish. The wizard generates a <code>sun-resources.xml</code> file for the |
| project that contains all information required to set up the connection pool and |
| data source on GlassFish. The <code>sun-resources.xml</code> file is a deployment |
| descriptor specific to the GlassFish application server. When the project next gets |
| deployed, the server will read in any configuration data contained in |
| <code>sun-resources.xml</code>, and set up the connection pool and data source |
| accordingly. Note that once the connection pool and data source exist on the server, |
| your project no longer requires the <code>sun-resources.xml</code> file.</li> |
| |
| <li>In the Projects window (Ctrl-1; ⌘-1 on Mac), expand the Server Resources node |
| and double-click the <code>sun-resources.xml</code> file to open it in the editor. |
| Here you see the XML configuration required to set up the connection pool and data |
| source. (Code below is formatted for readability.) |
| |
| <pre class="examplecode"> |
| <resources> |
| <jdbc-resource enabled="true" |
| jndi-name="jdbc/affablebean" |
| object-type="user" |
| pool-name="AffableBeanPool"> |
| </jdbc-resource> |
| |
| <jdbc-connection-pool allow-non-component-callers="false" |
| associate-with-thread="false" |
| connection-creation-retry-attempts="0" |
| connection-creation-retry-interval-in-seconds="10" |
| connection-leak-reclaim="false" |
| connection-leak-timeout-in-seconds="0" |
| connection-validation-method="auto-commit" |
| datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" |
| fail-all-connections="false" |
| idle-timeout-in-seconds="300" |
| is-connection-validation-required="false" |
| is-isolation-level-guaranteed="true" |
| lazy-connection-association="false" |
| lazy-connection-enlistment="false" |
| match-connections="false" |
| max-connection-usage-count="0" |
| max-pool-size="32" |
| max-wait-time-in-millis="60000" |
| name="AffableBeanPool" |
| non-transactional-connections="false" |
| pool-resize-quantity="2" |
| res-type="javax.sql.ConnectionPoolDataSource" |
| statement-timeout-in-seconds="-1" |
| steady-pool-size="8" |
| validate-atmost-once-period-in-seconds="0" |
| wrap-jdbc-objects="false"> |
| |
| <description>Connects to the affablebean database</description> |
| <property name="URL" value="jdbc:mysql://localhost:3306/affablebean"/> |
| <property name="User" value="root"/> |
| <property name="Password" value="nbuser"/> |
| </jdbc-connection-pool> |
| </resources></pre> |
| </li> |
| |
| <li>In the Projects window (Ctrl-1; ⌘-1 on Mac), right-click the <code>AffableBean</code> |
| project node and choose Deploy. The GlassFish server reads configuration data from |
| the <code>sun-resources.xml</code> file and creates the <code>AffableBeanPool</code> |
| connection pool, and <code>jdbc/affablebean</code> data source.</li> |
| |
| <li>In the Services window, expand the Servers > GlassFish > Resources > JDBC node. |
| Here you can locate the <code>jdbc/affablebean</code> data source listed under JDBC |
| Resources, and the <code>AffableBeanPool</code> connection pool listed under Connection |
| Pools. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/gf-server-jdbc-resources.png" |
| class="margin-around b-all" alt="Services window - GlassFish JDBC Resources" |
| title="View data sources and connection pools registered on the server"> |
| |
| <br> |
| <p class="tips">Right-click data source and connection pool nodes to view and |
| make changes to their properties. You can associate a data source with any |
| connection pool registered on the server. You can edit property values for |
| connection pools, and unregister both data sources and connection pools from |
| the server.</p></li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="testConnPoolDataSource">Testing the Connection Pool and Data Source</h2> |
| |
| <p>Start by making sure the GlassFish server can successfully connect to the MySQL database. |
| You can do this by pinging the <code>AffableBeanPool</code> connection pool in the GlassFish |
| Administration Console.</p> |
| |
| <p>Then proceed by adding a reference in your project to the data source you created on |
| the server. To do so, you create a <code><resource-ref></code> entry in the |
| application's <code>web.xml</code> deployment descriptor.</p> |
| |
| <p>Finally, use the IDE's editor support for the <a href="http://java.sun.com/products/jsp/jstl/" target="_blank">JSTL</a> |
| <code>sql</code> tag library, and create a JSP page that queries the database and |
| outputs data in a table on a web page.</p> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#ping">Pinging the Connection Pool</a></li> |
| <li><a href="#resourceReference">Creating a Resource Reference to the Data Source</a></li> |
| <li><a href="#query">Querying the Database from a JSP Page</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="ping">Pinging the Connection Pool</h3> |
| |
| <ol> |
| <li>Ensure that the GlassFish server is already running. In the Services window (Ctrl-5; |
| ⌘-5 on Mac), expand the Servers node. Note the small green arrow next to the |
| GlassFish icon ( <img src="../../../../images_www/articles/73/javaee/ecommerce/common/gf-server-running-node.png" |
| alt="GlassFish server node in Services window"> ). |
| |
| <br><br> |
| (If the server is not running, right-click the server node and choose Start.)</li> |
| |
| |
| <li>Right-click the server node and choose View Admin Console. The GlassFish Administration |
| Console opens in a browser.</li> |
| |
| <li>Log into the administration console. The default username / password is: <code>admin</code> |
| / <code>adminadmin</code>.</li> |
| |
| <li>In the console's tree on the left, expand the Resources > JDBC > Connection Pools |
| nodes, then click <code>AffableBeanPool</code>. In the main window, the Edit Connection |
| Pool interface displays for the selected connection pool.</li> |
| |
| <li>Click the Ping button. If the ping succeeds, the GlassFish server has a working connection to |
| the <code>affablebean</code> database on the MySQL server. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/ping-succeeded.png" |
| class="margin-around b-all" alt="GlassFish Administration Console - Edit Connection Pool" |
| title="Ping the connection pool to determine whether it has a physical connection to the database"> |
| |
| <br> |
| (If the ping fails, see suggestions in the <a href="#troubleshoot">Troubleshooting</a> section |
| below.)</li> |
| </ol> |
| |
| |
| <h3 id="resourceReference">Creating a Resource Reference to the Data Source</h3> |
| |
| <ol> |
| <li>In the Projects window, expand the Configuration Files folder and double-click |
| <code>web.xml</code>. A graphical interface for the file displays in the IDE's |
| main window.</li> |
| |
| <li>Click the References tab located along the top of the editor. Expand the Resource |
| References heading, then click Add. The Add Resource Reference dialog opens.</li> |
| |
| <li>Enter the following details into the dialog: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><strong>Resource Name:</strong> <code>jdbc/affablebean</code></li> |
| <li><strong>Resource Type:</strong> <code>javax.sql.ConnectionPoolDataSource</code></li> |
| <li><strong>Authentication:</strong> <code>Container</code></li> |
| <li><strong>Sharing Scope:</strong> <code>Shareable</code></li> |
| <li><strong>Description:</strong> <em>(Optional)</em> <code>Connects to database for AffableBean application</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/add-resource-ref-dialog.png" |
| alt="Add Resource Reference dialog" class="margin-around b-all" |
| title="Specify resource properties in the Add Resource Reference dialog"></li> |
| |
| <li>Click OK. The new resource is added under the Resource References heading. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/resource-reference.png" |
| title="Create a reference to the data source for the application" style="width: 688px" |
| alt="Resource reference to jdbc/affablebean data source listed in the deployment descriptor" |
| class="margin-around b-all"> |
| |
| <br> |
| To verify that the resource is now added to the <code>web.xml</code> file, |
| click the XML tab located along the top of the editor. Notice that the |
| following <code><resource-ref></code> tags are now included: |
| |
| <pre class="examplecode"> |
| <resource-ref> |
| <description>Connects to database for AffableBean application</description> |
| <res-ref-name>jdbc/affablebean</res-ref-name> |
| <res-type>javax.sql.ConnectionPoolDataSource</res-type> |
| <res-auth>Container</res-auth> |
| <res-sharing-scope>Shareable</res-sharing-scope> |
| </resource-ref></pre> |
| </li> |
| </ol> |
| |
| |
| <h3 id="query">Querying the Database from a JSP Page</h3> |
| |
| <ol> |
| <li>Create a new JSP page to test the data source. Click the New File ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/new-file-btn.png" |
| alt="New File button"> ) button. (Alternatively, press Ctrl-N; ⌘-N on Mac.)</li> |
| |
| <li>Select the Web category, then select the JSP file type and click Next.</li> |
| |
| <li>Enter '<code>testDataSource</code>' as the file name. In the Folder field, type |
| in '<code>test</code>'. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/new-jsp-wzd.png" |
| class="margin-around b-all" style="width:688px" alt="JSP wizard" |
| title="Enter details to name and place a new JSP page into the project"> |
| |
| <br> |
| <p class="tips">The project does not yet have a folder named '<code>test</code>' within |
| the Web Pages location (i.e., within the <code>web</code> folder). By entering '<code>test</code>' |
| into the Folder field, you have the IDE create the folder upon completing the wizard.</p></li> |
| |
| <li>Click finish. The IDE generates a new <code>testDataSource.jsp</code> file, and places |
| it into the new <code>test</code> folder within the project.</li> |
| |
| <li>In the new <code>testDataSource.jsp</code> file, in the editor, place your cursor at |
| the end of the line containing the <code><h1></code> tags (line 17). Press Return, |
| then press Ctrl-Space to invoke code suggestions. Choose DB Report from the list of |
| options. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/db-report.png" |
| class="margin-around b-all" alt="Code suggestions displayed in editor" |
| title="Press Ctrl-Space in editor to invoke code suggestions"> |
| |
| |
| <br> |
| <p class="tips">If line numbers do not display, right-click in the left margin of the |
| editor and choose Show Line Numbers.</p></li> |
| |
| <li>In the Insert DB Report dialog, specify the data source and modify the SQL query |
| to be executed: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><strong>Data Source:</strong> <code>jdbc/affablebean</code></li> |
| <li><strong>Query Statement:</strong> <code>SELECT * FROM category, product WHERE category.id = product.category_id</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/insert-db-report.png" |
| class="margin-around b-all" alt="Insert DB Report dialog" |
| title="Specify the data source and SQL query to be executed"></li> |
| |
| <li>Click OK. The dialog adds the <code>taglib</code> directives for the JSTL |
| <code>core</code> and <code>sql</code> libraries to the top of the file: |
| |
| <pre class="examplecode"> |
| <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> |
| <%@taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%></pre> |
| |
| The dialog also generates template code to display the query results in an |
| HTML table: |
| |
| <pre class="examplecode"> |
| <sql:query var="result" dataSource="jdbc/affablebean"> |
| SELECT * FROM category, product |
| WHERE category.id = product.category_id |
| </sql:query> |
| |
| <table border="1"> |
| <!-- column headers --> |
| <tr> |
| <c:forEach var="columnName" items="${result.columnNames}"> |
| <th><c:out value="${columnName}"/></th> |
| </c:forEach> |
| </tr> |
| <!-- column data --> |
| <c:forEach var="row" items="${result.rowsByIndex}"> |
| <tr> |
| <c:forEach var="column" items="${row}"> |
| <td><c:out value="${column}"/></td> |
| </c:forEach> |
| </tr> |
| </c:forEach> |
| </table></pre></li> |
| |
| <li>Before running the file in a browser, make sure you have enabled the JDBC driver |
| deployment option in NetBeans' GlassFish support. Choose Tools > Servers to |
| open the Servers window. In the left column, select the GlassFish server you are |
| deploying to. In the main column, ensure that the 'Enable JDBC Driver Deployment' |
| option is selected, then click Close. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/servers-window.png" |
| class="margin-around b-all" style="width:688px" alt="Servers window" |
| title="Ensure that the Enable JDBC Driver Deployment option is selected"> |
| |
| <br> |
| For Java applications that connect to a database, the server requires a JDBC |
| driver to be able to create a communication bridge between the SQL and Java |
| languages. In the case of MySQL, you use the <a href="http://www.mysql.com/downloads/connector/j/" target="_blank">Connector/J</a> |
| JDBC driver. Ordinarily you would need to manually place the driver JAR file |
| into the server's <code>lib</code> directory. With the 'Enable JDBC Driver |
| Deployment' option selected, the server performs a check to see whether a |
| driver is needed, and if so, the IDE deploys the driver to the server.</li> |
| |
| <li>Right-click in the editor and choose Run File (Shift-F6; fn-Shift-F6 on Mac). |
| The <code>testDataSource.jsp</code> file is compiled into a servlet, deployed |
| to the server, then runs in a browser.</li> |
| |
| <li>Open the Output window (Ctrl-4; ⌘-4 on Mac) and click the 'AffableBean (run)' |
| tab. The output indicates that the driver JAR file (<code>mysql-connector-java-5.1.6-bin.jar</code>) |
| is deployed. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/output-window-mysql-driver.png" |
| class="margin-around b-all" style="width:688px" alt="Output window listing MySQL driver deployment" |
| title="When JDBC Driver Deployment is enabled, the IDE deploys the MySQL driver to GlassFish when required"></li> |
| |
| <li>Examine <code>testDataSource.jsp</code> in the browser. You see an HTML table |
| listing data contained in the <code>category</code> and <code>product</code> tables. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/test-data-source.png" |
| class="margin-around b-all" style="width:688px" alt="Browser display of testDataSource.jsp" |
| title="The JSP page contains data extracted from the 'affablebean' database"> |
| |
| <br> |
| (If you receive a server error, see suggestions in the <a href="#troubleshoot">Troubleshooting</a> |
| section below.)</li> |
| </ol> |
| </div> |
| |
| <p>At this stage, we have set up a working data source and connection pool on the server, and |
| demonstrated that the application can access data contained in the <code>affablebean</code> |
| database.</p> |
| |
| |
| <br> |
| <h2 id="param">Setting Context Parameters</h2> |
| |
| <p>This section demonstrates how to configure context parameters for the application, |
| and how to access parameter values from JSP pages. The owner of an application may want |
| to be able to change certain settings without the need to make intrusive changes to |
| source code. Context parameters enable you application-wide access to parameter |
| values, and provide a convenient way to change parameter values from a single location, |
| should the need arise.</p> |
| |
| <p>Setting up context parameters can be accomplished in two steps:</p> |
| |
| <ol style="margin-top: 0"> |
| <li>Listing parameter names and values in the web deployment descriptor</li> |
| <li>Calling the parameters in JSP pages using the <code>initParam</code> object</li> |
| </ol> |
| |
| <p>The JSP Expression Language (EL) defines <em>implicit objects</em>, which <code>initParam</code> |
| is an example of. When working in JSP pages, you can utilize implicit objects |
| using dot notation and placing expressions within EL delimiters (<code>${...}</code>). |
| For example, if you have an initialization parameter named <code>myParam</code>, |
| you can access it from a JSP page with the expression <code>${initParam.myParam}</code>.</p> |
| |
| <p class="tips">For more information on the JSP Expression Language and implicit objects, |
| see the Java EE 5 Tutorial: |
| <a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/tutorial/doc/bnahq.html" target="_blank">JavaServer |
| Pages Technology > Unified Expression Language</a>.</p> |
| |
| <p>By way of demonstration, you create context parameters for the image paths to |
| category and product images used in the <code>AffableBean</code> project. Begin |
| by adding the provided image resources to the project, then perform the two steps |
| outlined above.</p> |
| |
| <ol> |
| <li>Download the <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252Fimg.zip">website |
| sample images</a>, and unzip the file to a location on your computer. The unzipped |
| file is an <code>img</code> folder that contains all of the image resources required |
| for the <code>AffableBean</code> application.</li> |
| |
| <li>Import the <code>img</code> folder into the <code>AffableBean</code> project. |
| Copy (Ctrl-C; ⌘-C on Mac) the <code>img</code> folder, then in the IDE's |
| Projects window, paste (Ctrl-V; ⌘-V on Mac) the folder into the project's |
| Web Pages node. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/projects-win-img-folder.png" |
| class="margin-around b-all" alt="'img' folder displayed in Projects window" |
| title="Import the 'img' folder into the AffableBean project"> |
| |
| <br> |
| The <code>categories</code> and <code>products</code> folders contain the |
| images that will be displayed in the <a href="design.html#index">index</a> and |
| <a href="design.html#category">category</a> pages, respectively.</li> |
| |
| <li>Open the project's web deployment descriptor. In the Projects window, expand |
| the Configuration Files node and double-click <code>web.xml</code>.</li> |
| |
| <li>Click the General tab, then expand Context Parameters and click the Add button.</li> |
| |
| <li>In the Add Context Parameter dialog, enter the following details: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>Parameter Name:</strong> <code>productImagePath</code></li> |
| <li><strong>Parameter Value:</strong> <code>img/products/</code></li> |
| <li><strong>Description:</strong> <em>(Optional)</em> |
| <code>The relative path to product images</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/add-context-param-dialog.png" |
| class="margin-around b-all" alt="Add Context Parameter dialog" |
| title="Add initialization parameters using the Add Context Parameter dialog"></li> |
| |
| <li>Click OK.</li> |
| |
| <li>Click the Add button again and enter the following details: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>Parameter Name:</strong> <code>categoryImagePath</code></li> |
| <li><strong>Parameter Value:</strong> <code>img/categories/</code></li> |
| <li><strong>Description:</strong> <em>(Optional)</em> |
| <code>The relative path to category images</code></li> |
| </ul></li> |
| |
| <li>Click OK. The two context parameters are now listed: |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/context-parameters.png" |
| class="margin-around b-all" alt="web.xml - context parameters" |
| title="Context parameters display in the web.xml interface"></li> |
| |
| <li>Click the XML tab to view the XML content that has been added to the deployment |
| descriptor. The following <code><context-param></code> entries have been |
| added: |
| |
| <pre class="examplecode"> |
| <context-param> |
| <description>The relative path to product images</description> |
| <param-name>productImagePath</param-name> |
| <param-value>img/products/</param-value> |
| </context-param> |
| <context-param> |
| <description>The relative path to category images</description> |
| <param-name>categoryImagePath</param-name> |
| <param-value>img/categories/</param-value> |
| </context-param></pre></li> |
| |
| <li>To test whether the values for the context parameters are accessible to web |
| pages, open any of the project's web pages in the editor and enter EL |
| expressions using the <code>initParam</code> implicit object. For example, |
| open <code>index.jsp</code> and enter the following (New code in <strong>bold</strong>): |
| |
| <pre class="examplecode"> |
| <div id="indexLeftColumn"> |
| <div id="welcomeText"> |
| <p>[ welcome text ]</p> |
| |
| <strong><!-- test to access context parameters --> |
| categoryImagePath: ${initParam.categoryImagePath} |
| productImagePath: ${initParam.productImagePath}</strong> |
| </div> |
| </div></pre></li> |
| |
| <li>Run the project. Click the Run Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) button. The project's index page opens in the browser, |
| and you see the values for the <code>categoryImagePath</code> and <code>productImagePath</code> |
| context parameters displayed in the page. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/context-params-browser.png" |
| class="margin-around b-all" alt="Context parameter values displayed in browser" |
| title="Use 'initParam' with JSP EL delimiters to display context parameter values"> |
| </li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="jstl">Working with JSTL</h2> |
| |
| <p>So far in this tutorial unit, you've established how to access data from the |
| <code>affablebean</code> database, add image resources to the project, and |
| have set up several context parameters. In this final section, you combine |
| these achievements to plug the product and category images into the application. |
| In order to do so effectively, you need to begin taking advantage of the JavaServer |
| Pages Standard Tag Library (JSTL).</p> |
| |
| <p>Note that you do not have to worry about adding the JSTL JAR file (<code>jstl-impl.jar</code>) |
| to your project's classpath because it already exists. When you created the |
| <code>AffableBean</code> project and selected GlassFish as your development server, |
| the libraries contained in the server were automatically added to your project's |
| classpath. You can verify this in the Projects window by expanding the <code>AffableBean</code> |
| project's Libraries > GlassFish Server 3 node to view all of the libraries |
| provided by the server. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/gf-libraries.png" |
| class="margin-around b-all" alt="GlassFish libraries listed in Projects window" |
| title="GlassFish libraries are available to your project"> |
| |
| <br> |
| The <code>jstl-impl.jar</code> file is GlassFish' implementation of JSTL, version 1.2.</p> |
| |
| <p class="tips">You can also download the GlassFish JSTL JAR file separately from: |
| <a href="http://jstl.dev.java.net/download.html" target="_blank">http://jstl.dev.java.net/download.html</a></p> |
| |
| <p>Before embarking upon an exercise involving JSTL, one implementation detail |
| needs to first be clarified. Examine the files contained in the <code>categories</code> |
| and <code>products</code> folders and note that the names of the provided |
| image files match the names of the category and product entries found in the |
| database. This enables us to leverage the database data to dynamically call |
| image files within the page. So for example, if the web page needs to access |
| the image for the broccoli product entry, you can make this happen using the |
| following statement.</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:700px">${initParam.productImagePath}broccoli.png</pre> |
| </div> |
| |
| <p>After implementing a JSTL |
| <code><a href="http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/c/forEach.html" target="_blank">forEach</a></code> |
| loop, you'll be able to replace the hard-coded name of the product with an EL |
| expression that dynamically extracts the name of the product from the database, |
| and inserts it into the page.</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:700px">${initParam.productImagePath}${product.name}.png</pre> |
| </div> |
| |
| <p>Begin by integrating the category images into the index page, then work within the |
| category page so that data pertaining to the selected category is dynamically handled.</p> |
| |
| <ul> |
| <li><a href="#indexJSTL">index page</a></li> |
| <li><a href="#categoryJSTL">category page</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id=indexJSTL">index page</h3> |
| |
| <ol> |
| <li>In the Projects window, double-click the <code>index.jsp</code> node to open |
| it in the editor. (If already opened, press Ctrl-Tab to select it in the editor.)</li> |
| |
| <li>At the top of the file, before the first <code><div></code> tag, place your |
| cursor on a blank line, then type '<code>db</code>' and press Ctrl-Space. In the |
| code-completion pop-up window that displays, choose DB Query. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/db-query.png" |
| class="margin-around b-all" alt="DB completion items displayed in editor" |
| title="Type 'db', then press Ctrl-Space to invoke code completion suggestions"></li> |
| |
| <li>In the Insert DB Query dialog, enter the following details: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>Variable Name:</strong> <code>categories</code></li> |
| <li><strong>Scope:</strong> <code>page</code></li> |
| <li><strong>Data Source:</strong> <code>jdbc/affablebean</code></li> |
| <li><strong>Query Statement:</strong> <code>SELECT * FROM category</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/insert-db-query.png" |
| class="margin-around b-all" alt="Insert DB query dialog" |
| title="Specify query details to create an SQL query using JSTL <sql:query> tags"></li> |
| |
| <li>Click OK. The dialog generates an SQL query using JSTL <code><sql:query></code> tags. |
| Also, note that the required reference to the <code>sql</code> <code>taglib</code> directive |
| has been automatically inserted at the top of the page. (Changes displayed in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <strong><%@taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%></strong> |
| <%-- |
| Document : index |
| Created on : Sep 5, 2009, 4:32:42 PM |
| Author : nbuser |
| --%> |
| |
| <strong><sql:query var="categories" dataSource="jdbc/affablebean"> |
| SELECT * FROM category |
| </sql:query></strong> |
| |
| <div id="indexLeftColumn"> |
| <div id="welcomeText"> |
| <p>[ welcome text ]</p> |
| </pre> |
| |
| The SQL query creates a result set which is stored in the <code>categories</code> |
| variable. You can then access the result set using EL syntax, e.g., <code>${categories}</code> |
| (demonstrated below).</li> |
| |
| <li>Place your cursor at the end of '<code><div id="indexRightColumn"></code>' |
| (line 22), hit return, type '<code>jstl</code>' then press Ctrl-Space and choose |
| JSTL For Each. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/jstl-for-each.png" |
| class="margin-around b-all" alt="JSTL completion items displayed in editor" |
| title="Type 'jstl', then press Ctrl-Space to invoke code completion suggestions"></li> |
| |
| <li>In the Insert JSTL For Each dialog, enter the following details: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><strong>Collection:</strong> <code>${categories.rows}</code></li> |
| <li><strong>Current Item of the Iteration:</strong> <code>category</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/insert-jstl-for-each.png" |
| class="margin-around b-all" style="width:625px" alt="Insert JSTL For Each dialog" |
| title="Specify details to create a 'for each' loop using JSTL <c:forEach> tags"></li> |
| |
| <li>Click OK. The dialog sets up syntax for a JSTL <code>forEach</code> loop using <code><c:forEach></code> |
| tags. Also, note that the required reference to the <code>core</code> <code>taglib</code> |
| directive has been automatically inserted at the top of the page. (Changes displayed in |
| <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <strong><%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%></strong> |
| <%@taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%> |
| |
| ... |
| |
| <div id="indexRightColumn"> |
| <strong><c:forEach var="category" items="categories.rows"> |
| </c:forEach></strong> |
| <div class="categoryBox"></pre> |
| |
| <br> |
| <p class="tips">If you are wondering what '<code>rows</code>' refers to in the |
| generated code, recall that the <code>categories</code> variable represents a |
| result set. More specifically, <code>categories</code> refers to an object that |
| implements the |
| <code><a href="http://java.sun.com/products/jsp/jstl/1.1/docs/api/javax/servlet/jsp/jstl/sql/Result.html" target="_blank">javax.servlet.jsp.jstl.sql.Result</a></code> |
| interface. This object provides properties for accessing the rows, column names, |
| and size of the query’s result set. When using dot notation as in the above |
| example, '<code>categories.rows</code>' is translated in Java to |
| '<code>categories.getRows()</code>'.</p></li> |
| |
| <li>Integrate the <code><c:forEach></code> tags into the page. You can nest |
| the <code><div class="categoryBox"></code> tags within the |
| <code>forEach</code> loop so that HTML markup is generated for each of the four |
| categories. Use EL syntax to extract the <code>category</code> table's <code>id</code> |
| and <code>name</code> column values for each of the four records. Make sure to |
| delete the other <code><div class="categoryBox"></code> tags which |
| exist outside the <code>forEach</code> loop. When you finish, the complete |
| <code>index.jsp</code> file will look as follows. (<code><c:forEach></code> |
| tags and contents are displayed in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> |
| <%@taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%> |
| <%-- |
| Document : index |
| Created on : Sep 5, 2009, 4:32:42 PM |
| Author : nbuser |
| --%> |
| |
| <sql:query var="categories" dataSource="jdbc/affablebean"> |
| SELECT * FROM category |
| </sql:query> |
| |
| <div id="indexLeftColumn"> |
| <div id="welcomeText"> |
| <p>[ welcome text ]</p> |
| |
| <!-- test to access context parameters --> |
| categoryImagePath: ${initParam.categoryImagePath} |
| productImagePath: ${initParam.productImagePath} |
| </div> |
| </div> |
| |
| <strong><div id="indexRightColumn"> |
| <c:forEach var="category" items="${categories.rows}"> |
| <div class="categoryBox"> |
| <a href="category?${category.id}"> |
| |
| <span class="categoryLabelText">${category.name}</span> |
| |
| <img src="${initParam.categoryImagePath}${category.name}.jpg" |
| alt="${category.name}"> |
| </a> |
| </div> |
| </c:forEach> |
| </div></strong></pre></li> |
| |
| <li>Click the Run Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) button. The project's index page opens in the browser, |
| and you see the names and images of the four categories. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/index-category-images.png" |
| class="margin-around b-all" style="width:688px" alt="Category images displayed in index page in browser" |
| title="'for each' loop extracts details from the database and utilizes them in the page"></li> |
| |
| <li>Click any of the four images in the browser. The category page displays. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/category-page.png" |
| class="margin-around b-all" style="width:688px" alt="Category page in browser" |
| title="Category images from index page link to category page"> |
| |
| <br> |
| To understand how linking takes place between the index and category pages, |
| reexamine the HTML anchor tags within the <code>forEach</code> loop: |
| |
| <pre class="examplecode"><a href="category?${category.id}"></pre> |
| |
| When a user clicks the image link in the browser, a request for '<code>category</code>' |
| is sent to the application's context root on the server. In your development environment, |
| the URL is: |
| |
| <pre class="examplecode">http://localhost:8080/AffableBean/category</pre> |
| |
| which can be explained as follows: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><code>http://localhost:8080</code>: The default location of the GlassFish server on your computer</li> |
| <li><code>/AffableBean</code>: The context root of your deployed application</li> |
| <li><code>/category</code>: The path to the request</li> |
| </ul> |
| |
| Recall that in <a href="page-views-controller.html#controller">Preparing the Page |
| Views and Controller Servlet</a>, you mapped a request for '<code>/category</code>' |
| to the <code>ControllerServlet</code>. Currently, the <code>ControllerServlet</code> |
| internally forwards the request to <code>/WEB-INF/view/category.jsp</code>, which |
| is why the category page displays upon clicking an image link. |
| |
| <br><br> |
| <p class="tips">You can verify the application's context root by expanding the Configuration |
| Files node in the Projects window, and opening the <code>sun-web.xml</code> file. The |
| <code>sun-web.xml</code> file is a deployment descriptor specific to GlassFish.</p> |
| |
| <br> |
| Also, note that a question mark (<code>?</code>) and category ID are appended to |
| the requested URL. |
| |
| <pre class="examplecode"><a href="category<strong>?${category.id}</strong>"></pre> |
| |
| This forms the <em>query string</em>. As is demonstrated in the next section, |
| you can apply <code>(pageContext.request.queryString}</code> to extract the value |
| of the query string from the request. You can then use the category ID from the |
| query string to determine which category details need to be included in the |
| response.</li> |
| </ol> |
| |
| <h3 id="categoryJSTL">category page</h3> |
| |
| <p>Three aspects of the category page need to be handled dynamically. The left column |
| must indicate which category is selected, the table heading must display the name |
| of the selected category, and the table must list product details pertaining to |
| the selected category. In order to implement these aspects using JSTL, you can |
| follow a simple, 2-step pattern:</p> |
| |
| <ol style="margin: 5px 0 0 -1em"> |
| <li>Retrieve data from the database using the JSTL <code>sql</code> tag library.</li> |
| <li>Display the data using the JSTL <code>core</code> library and EL syntax.</li> |
| </ol> |
| |
| <p>Tackle each of the three tasks individually.</p> |
| |
| <h4>Display selected category in left column</h4> |
| |
| <ol> |
| <li>In the Projects window, double-click the <code>category.jsp</code> node to open |
| it in the editor. (If already opened, press Ctrl-Tab to select it in the editor.)</li> |
| |
| <li>Add the following SQL query to the top of the file. |
| |
| <pre class="examplecode"> |
| <sql:query var="categories" dataSource="jdbc/affablebean"> |
| SELECT * FROM category |
| </sql:query></pre> |
| |
| Either use the Insert DB Query dialog as <a href="#categoryIndex">described above</a>, |
| or use the editor's code suggestion and completion facilities by pressing Ctrl-Space |
| while typing.</li> |
| |
| <li>Between the <code><div id="categoryLeftColumn"></code> tags, |
| replace the existing static placeholder content with the following |
| <code><c:forEach></code> loop. |
| |
| <pre class="examplecode"> |
| <div id="categoryLeftColumn"> |
| |
| <strong><c:forEach var="category" items="${categories.rows}"> |
| |
| <c:choose> |
| <c:when test="${category.id == pageContext.request.queryString}"> |
| <div class="categoryButton" id="selectedCategory"> |
| <span class="categoryText"> |
| ${category.name} |
| </span> |
| </div> |
| </c:when> |
| <c:otherwise> |
| <a href="category?${category.id}" class="categoryButton"> |
| <div class="categoryText"> |
| ${category.name} |
| </div> |
| </a> |
| </c:otherwise> |
| </c:choose> |
| |
| </c:forEach></strong> |
| |
| </div></pre> |
| |
| In the above snippet, you access the request's query string using |
| '<code>pageContext.request.queryString</code>'. <code>pageContext</code> |
| is another <a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/tutorial/doc/bnahq.html#bnaij" target="_blank">implicit |
| object</a> defined by the JSP Expression Language. The EL expression uses the |
| <code><a href="http://java.sun.com/webservices/docs/1.6/api/javax/servlet/jsp/PageContext.html" target="_blank">PageContext</a></code> |
| to access the current request (an <code><a href="http://java.sun.com/webservices/docs/1.6/api/javax/servlet/http/HttpServletRequest.html" target="_blank">HttpServletRequest</a></code> |
| object). From <code>HttpServletRequest</code>, the <code>getQueryString()</code> |
| method is called to obtain the value of the request's query string.</li> |
| |
| <li>Make sure to add the JSTL <code>core</code> and <code>sql</code> <code>taglib</code> |
| directives to the top of the page. (This is done automatically when using the |
| editor's code suggestion and completion facilities.) |
| |
| <pre class="examplecode"> |
| <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> |
| <%@taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql"%></pre></li> |
| |
| <li>Run the project. In the browser, navigate to the category page and click |
| the category buttons in the left column. Each time you click, the page refreshes |
| highlighting the selected category. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/category-page-bakery.png" |
| class="margin-around b-all" style="width:688px" alt="Category page with bakery category selected" |
| title="Select categories by clicking category buttons in the left column"> |
| |
| <br> |
| Also, note that the ID of the selected category is displayed in the page's URL. |
| (In the above image, the bakery category is selected, and '<code>3</code>' is |
| appended to the URL in the browser's navigation toolbar.) |
| |
| <br><br> |
| <p class="tips">Your servlet container (i.e., GlassFish) converts JSP pages |
| into servlets before running them as part of a project. You can view the |
| generated servlet for a JSP page by right-clicking the page node in the |
| Projects window and choosing View Servlet. Of course, you first need to |
| run the project so that the servlet is generated. Taking the <code>index.jsp</code> |
| file as an example, when you choose View Servlet, the IDE displays a read-only |
| copy of the generated servlet, <code>index_jsp.java</code>, in the editor. |
| The servlet exists on the server at: |
| <code><em><gf-install-dir></em>/glassfish/domains/domain1/generated/jsp/AffableBean/org/apache/jsp/index_jsp.java</code>.</p></li> |
| </ol> |
| |
| <div class="indent"> |
| <div class="feedback-box float-left" style="width: 703px;"> |
| |
| <h3>Examining Implicit Object Values using the IDE's Debugger</h3> |
| |
| <p>You can use the IDE's Java debugger to examine values for implicit objects. |
| To do so, set a breakpoint on a line containing JSP or JSTL syntax in a |
| JSP page, then run the debugger. When the debugger suspends on the breakpoint, |
| you can open the Variables window (Window > Debugging > Variables) |
| to inspect values currently held by the application.</p> |
| |
| <p>Taking your current implementation of <code>category.jsp</code> as an |
| example, perform the following steps:</p> |
| |
| <ol> |
| <li>Set a breakpoint on the line containing: |
| |
| <pre><c:when test="${category.id == pageContext.request.queryString}"></pre> |
| |
| (To set a breakpoint, click in the left margin of the line. A breakpoint |
| ( <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/breakpoint-icon.png" |
| alt="Breakpoint icon"> ) icon displays.)</li> |
| |
| <li>In the IDE's main toolbar, click the Debug Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/debug-project-btn.png" |
| alt="Debug Project button"> ) button. A debugging session is |
| activated for the project, and the application's index page opens |
| in the browser.</li> |
| |
| <li>Click the bakery category in the index page. (You know that the |
| ID for the bakery category is '<code>3</code>').</li> |
| |
| <li>Return to the IDE, and note that the debugger is suspended on the |
| line containing the breakpoint. When suspended, the margin shows |
| a green arrow on the breakpoint ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/debugger-suspended-icon.png" |
| alt="Debug Project button"> ), and the line displays with green background.</li> |
| |
| <li>Open the Variables window (Ctrl-Shift-1) and expand the Implicit Objects > |
| pageContext > request > queryString node. Inspect the variable value |
| and note that the value is '<code>3</code>', corresponding to the category ID |
| from your selection.</li> |
| |
| <li>Press the Finish Debugger Session ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/finish-debugger-session-btn.png" |
| alt="Finish Debuger Session button"> ) button to terminate the debugger session.</li> |
| </ol> |
| |
| </div> |
| </div> |
| <br style="clear: left"/> |
| |
| <h4>Display title heading above product table</h4> |
| |
| <ol> |
| <li>Add the following SQL query to the top of the file, underneath the query you |
| just implemented. (New query is shown in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <sql:query var="categories" dataSource="jdbc/affablebean"> |
| SELECT * FROM category |
| </sql:query> |
| |
| <strong><sql:query var="selectedCategory" dataSource="jdbc/affablebean"> |
| SELECT name FROM category WHERE id = ? |
| <sql:param value="${pageContext.request.queryString}"/> |
| </sql:query></strong></pre></li> |
| |
| <li>Use JSP EL syntax to extract the category name from the query and |
| display it in the page. Make the following change to the |
| <code><p id="categoryTitle"></code> element. |
| (Displayed in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <p id="categoryTitle"><strong>${selectedCategory.rows[0].name}</strong></p></pre> |
| |
| Since the result from the <code>selectedCategory</code> query contains |
| only one item (i.e., user can select only one category), you can retrieve |
| the first row of the result set using '<code>selectedCategory<strong>.rows[0]</strong></code>'. |
| If a user selects the 'meats' category for example, the returned expression |
| would be '<code>{name=meats}</code>'. You could then access the category name |
| with '<code>${selectedCategory.rows[0]<strong>.name</strong>}</code>'.</li> |
| |
| <li>Save (Ctrl-S; ⌘-S on Mac) changes made to the file.</li> |
| |
| <li>Return to the browser and refresh the category page. The name of |
| the selected category now displays above the product table. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/category-page-bakery-title.png" |
| class="margin-around b-all" style="width:688px" alt="Category page with bakery title displayed over product table" |
| title="The name of the selected category dynamically displays above the product table"> |
| |
| <br> |
| <p class="notes"><strong>Note:</strong> As demonstrated in this and the |
| previous step, you do not need to explicitly recompile, deploy, and run |
| the project with each change to your code base. The IDE provides a Deploy |
| on on Save feature, which is enabled for Java web projects by default. |
| To verify that the feature is activated, right-click your project node |
| in the Projects window and choose Properties. In the Project Properties |
| window, click the Run category and examine the 'Deploy on Save' option.</p></li> |
| </ol> |
| |
| <h4>Display product details within the table</h4> |
| |
| <ol> |
| <li>Add the following SQL query to the top of the file, underneath the previous |
| queries you implemented. (New query is shown in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <sql:query var="categories" dataSource="jdbc/affablebean"> |
| SELECT * FROM category |
| </sql:query> |
| |
| <sql:query var="selectedCategory" dataSource="jdbc/affablebean"> |
| SELECT name FROM category WHERE id = ? |
| <sql:param value="${pageContext.request.queryString}"/> |
| </sql:query> |
| |
| <strong><sql:query var="categoryProducts" dataSource="jdbc/affablebean"> |
| SELECT * FROM product WHERE category_id = ? |
| <sql:param value="${pageContext.request.queryString}"/> |
| </sql:query></strong></pre></li> |
| |
| <li>Between the <code><table id="productTable"></code> tags, |
| replace the existing static table row placeholders (<code><tr></code> |
| tags) with the following <code><c:forEach></code> loop. |
| (Changes are displayed in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <table id="productTable"> |
| |
| <strong><c:forEach var="product" items="${categoryProducts.rows}" varStatus="iter"> |
| |
| <tr class="${((iter.index % 2) == 0) ? 'lightBlue' : 'white'}"> |
| <td> |
| <img src="${initParam.productImagePath}${product.name}.png" |
| alt="${product.name}"> |
| </td> |
| <td> |
| ${product.name} |
| <br> |
| <span class="smallText">${product.description}</span> |
| </td> |
| <td> |
| &euro; ${product.price} / unit |
| </td> |
| <td> |
| <form action="addToCart" method="post"> |
| <input type="hidden" |
| name="productId" |
| value="${product.id}"> |
| <input type="submit" |
| value="add to cart"> |
| </form> |
| </td> |
| </tr> |
| |
| </c:forEach></strong> |
| |
| </table></pre> |
| |
| Note that in the above snippet an EL expression is used to determine the background |
| color for table rows: |
| |
| <pre class="examplecode">class="${((iter.index % 2) == 0) ? 'lightBlue' : 'white'}"</pre> |
| |
| The API documentation for the <code><a href="http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/c/forEach.html" target="_blank"><c:forEach></a></code> |
| tag indicates that the <code>varStatus</code> attribute represents an object |
| that implements the |
| <code><a href="http://java.sun.com/products/jsp/jstl/1.1/docs/api/javax/servlet/jsp/jstl/core/LoopTagStatus.html" target="_blank">LoopTagStatus</a></code> |
| interface. Therefore, <code>iter.index</code> retrieves the index of the current |
| round of the iteration. Continuing with the expression, <code>(iter.index % 2) == 0)</code> |
| evaluates the remainder when <code>iter.index</code> is divided by <code>2</code>, |
| and returns a boolean value based on the outcome. Finally, an EL conditional operator |
| (<code>? :</code>) is used to set the returned value to '<code>lightBlue</code>' if true, |
| '<code>white</code>' otherwise. |
| |
| <br><br> |
| <p class="tips">For a description of JSP Expression Language operators, see the |
| Java EE 5 Tutorial: <a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/tutorial/doc/bnahq.html#bnaik" target="_blank">JavaServer |
| Pages Technology > Unified Expression Language > Operators</a>.</p></li> |
| |
| <li>Save (Ctrl-S; ⌘-S on Mac) changes made to the file.</li> |
| |
| <li>Return to the browser and refresh the category page. Product details |
| now display within the table for the selected category. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/category-page-bakery-product-table.png" |
| class="margin-around b-all" style="width:688px" alt="Category page displaying products for selected category" |
| title="Product details are dynamically displayed for the selected category"></li> |
| </ol> |
| |
| <p>You have now completed this tutorial unit. In it, you explored how to connect your |
| application to the database by setting up a connection pool and data source on the |
| server, then referenced the data source from the application. You also created several |
| context parameters, and learned how to access them from JSP pages. Finally, you |
| implemented JSTL tags into the application's web pages in order to dynamically |
| retrieve and display database data.</p> |
| |
| <p>You can download and examine <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot3.zip">snapshot |
| 3</a> if you'd like to compare your work with the solution project. The solution project |
| contains enhancements to the HTML markup and stylesheet in order to properly display all |
| provided images. It also provides welcome page text, and a basic implementation for the |
| page footer.</p> |
| </div> |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Connecting the Application to the Database">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <h2 id="troubleshoot">Troubleshooting</h2> |
| |
| <p>If you are having problems, see the troubleshooting tips below. If you continue to have difficulty, |
| or would like to provide constructive feedback, use the Send us Your Feedback link.</p> |
| |
| <ul> |
| <li>You receive the following exception: |
| |
| <pre class="examplecode" style="width: 700px"> |
| org.apache.jasper.JasperException: PWC6188: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application</pre> |
| |
| This is a <a href="https://netbeans.org/bugzilla/show_bug.cgi?id=188406" target="_blank">known |
| issue</a> for NetBeans IDE 6.9. Try to deploy the project, then access the file by typing its |
| URL in the browser. For example, if you are trying to view <code>testDataSource.jsp</code> in |
| a browser, enter '<code>http://localhost:8080/AffableBean/test/testDataSource.jsp</code>' in |
| the browser's URL field directly. Otherwise, add the IDE's JSTL 1.1 library to the project. In |
| the Projects window, right-click the Libraries node and choose Add Library. Select JSTL 1.1. |
| For more information, see: |
| <a href="http://forums.netbeans.org/topic28571.html" target="_blank">http://forums.netbeans.org/topic28571.html</a>.</li> |
| |
| <li>You receive the following exception: |
| |
| <pre class="examplecode" style="width: 700px">javax.servlet.ServletException: javax.servlet.jsp.JspException: Unable to get connection, DataSource invalid: "java.sql.SQLException: Error in allocating a connection. Cause: Class name is wrong or classpath is not set for : com.mysql.jdbc.jdbc2.optional.MysqlDataSource"</pre> |
| |
| This can occur when the MySQL driver has not been added to the domain <code>lib</code> |
| folder. (Note that after adding, it is necessary to restart the server if it is already |
| running.)</li> |
| |
| <li>You receive the following exception: |
| |
| <pre class="examplecode" style="width: 700px">javax.servlet.ServletException: javax.servlet.jsp.JspException: Unable to get connection, DataSource invalid: "java.sql.SQLException: No suitable driver found for jdbc/affablebean"</pre> |
| |
| This can occur when the <code>jdbc/affablebean</code> resource reference hasn't been |
| added to the <code>web.xml</code> deployment descriptor.</li> |
| |
| <li>You receive the following exception: |
| |
| <pre class="examplecode" style="width: 700px">javax.servlet.ServletException: javax.servlet.jsp.JspException: Unable to get connection, DataSource invalid: "java.sql.SQLException: Error in allocating a connection. Cause: Connection could not be allocated because: Access denied for user 'root'@'localhost' (using password: YES)"</pre> |
| |
| This can occur when you are using an incorrect username/password combination. Make sure |
| the username and password you use to connect to the MySQL server are correctly set for |
| your connection pool in the <code>sun-resources.xml</code> file. Also, check that the |
| username and password are correctly set for the connection pool in the GlassFish |
| Administration Console.</li> |
| </ul> |
| |
| <br> |
| <h2 id="seeAlsoConnectDb">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Resources</h3> |
| |
| <ul> |
| <li><a href="../../ide/mysql.html" target="_blank">Connecting to a MySQL Database</a></li> |
| <li><a href="../../web/quickstart-webapps.html" target="_blank">Introduction to Developing Web Applications</a></li> |
| <li><a href="../../web/mysql-webapp.html" target="_blank">Creating a Simple Web Application Using a MySQL Database</a></li> |
| <li><a href="../../ide/database-improvements-screencast.html" target="_blank">Screencast: Database Support in NetBeans IDE</a></li> |
| </ul> |
| |
| <h3>MySQL Resources</h3> |
| |
| <ul> |
| <li><a href="http://dev.mysql.com/librarian/" target="_blank">The MySQL Community Librarian</a></li> |
| <li><a href="http://dev.mysql.com/doc/refman/5.1/en/" target="_blank">MySQL 5.1 Reference Manual</a></li> |
| <li><a href="http://www.mysql.com/why-mysql/java/#howtos" target="_blank">MySQL and Java</a></li> |
| <li><a href="http://forums.mysql.com/" target="_blank">MySQL Forums</a></li> |
| </ul> |
| |
| <h3>JSP & EL Resources</h3> |
| |
| <ul> |
| <li><strong>Product Page:</strong> <a href="http://java.sun.com/products/jsp/" target="_blank">JavaServer Pages Technology</a></li> |
| <li><strong>Specification Download:</strong> <a href="http://jcp.org/aboutJava/communityprocess/mrel/jsr245/index.html" target="_blank">JSR 245: JSP and EL 2.2 Maintenance Release</a></li> |
| <li><strong>API Documentation:</strong> <a href="http://java.sun.com/products/jsp/2.1/docs/jsp-2_1-pfd2/index.html" target="_blank">JavaServer Pages 2.1 API Documentation</a></li> |
| <li><strong>Supporting Documentation:</strong> <a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/tutorial/doc/bnagx.html" target="_blank">Java EE 5 Tutorial - Chapter 5: JavaServer Pages Technology</a></li> |
| <li><strong>Syntax Reference:</strong> <a href="http://java.sun.com/products/jsp/syntax/2.0/syntaxref20.html" target="_blank">JavaServer Pages 2.0 Syntax Reference</a></li> |
| <li><strong>Official Forum:</strong> <a href="http://forums.sun.com/forum.jspa?forumID=45" target="_blank">Web Tier APIs - JavaServer Pages (JSP) and JSTL</a></li> |
| </ul> |
| |
| <h3>JSTL Resources</h3> |
| |
| <ul> |
| <li><strong>Product Page:</strong> <a href="http://java.sun.com/products/jsp/jstl/" target="_blank">JavaServer Pages Standard Tag Library</a></li> |
| <li><strong>Specification Download:</strong> <a href="http://jcp.org/aboutJava/communityprocess/final/jsr052/index2.html" target="_blank">JSR 52: JSTL 1.2 Maintenance Release</a></li> |
| <li><strong>Implementation Download:</strong> <a href="http://jstl.dev.java.net/download.html" target="_blank">GlassFish JSTL Project Download</a></li> |
| <li><strong>Tag Library Documentation:</strong> <a href="http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/index.html" target="_blank">JSTL 1.1 Tag Reference</a></li> |
| <li><strong>API Documentation:</strong> <a href="http://java.sun.com/products/jsp/jstl/1.1/docs/api/index.html" target="_blank">JSTL 1.1 API Reference</a></li> |
| </ul> |
| |
| <h3>Technical Articles & Reference Cards</h3> |
| |
| <ul> |
| <li><a href="http://java.sun.com/developer/technicalArticles/javaserverpages/JSP20/" target="_blank">Developing Web Applications With JavaServer Pages 2.0</a></li> |
| <li><a href="http://java.sun.com/developer/technicalArticles/J2EE/jsp_21/" target="_blank">Web Tier to Go With Java EE 5: Summary of New Features in JSP 2.1 Technology</a></li> |
| <li><a href="http://java.sun.com/products/jsp/reference/techart/unifiedEL.html" target="_blank">Unified Expression Language</a></li> |
| <li><a href="http://today.java.net/pub/a/today/2003/10/07/jstl1.html" target="_blank">Practical JSTL, Part 1</a></li> |
| <li><a href="http://www.ibm.com/developerworks/java/library/j-jstl0520/index.html" target="_blank">A JSTL primer, Part 4: Accessing SQL and XML content</a></li> |
| <li><a href="http://java.sun.com/products/jsp/syntax/2.0/card20.pdf">JavaServer Pages v2.0 Syntax Card</a></li> |
| <li><a href="http://refcardz.dzone.com/refcardz/essential-jsp-expression" target="_blank">Essential JSP Expression Language Reference Card</a></li> |
| <li><a href="http://download.oracle.com/docs/cd/E17409_01/javase/tutorial/jdbc/index.html" target="_blank">The Java Tutorials: JDBC Database Access</a></li> |
| <li><a href="http://java.sun.com/developer/Books/jdbc/" target="_blank">Database Programming with JDBC and Java, Second Edition</a></li> |
| <li><a href="http://refcardz.dzone.com/refcardz/essential-jsp-expression" target="_blank">Essential JSP Expression Language Reference Card</a></li> |
| <li><a href="http://java.sun.com/products/jndi/tutorial/" target="_blank">The JNDI Tutorial</a></li> |
| </ul> |
| </div> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="entity-session">The NetBeans E-commerce Tutorial - Adding Entity Classes and Session Beans</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><strong>Adding Entity Classes and Session Beans</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#whatEJB">What are EJB and JPA Technologies?</a></li> |
| <li><a href="#whatSession">What are Session Beans?</a></li> |
| <li><a href="#specification">About Specifications and Implementations</a></li> |
| <li><a href="#addEntity">Adding Entity Classes</a></li> |
| <li><a href="#addSession">Adding Session Beans</a></li> |
| <li><a href="#access">Accessing Data with EJBs</a></li> |
| <li><a href="#seeAlsoEntitySession">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>This tutorial unit introduces the <a href="http://java.sun.com/products/ejb/" target="_blank">Enterprise |
| JavaBeans</a> (EJB) and <a href="http://java.sun.com/javaee/technologies/persistence.jsp" target="_blank">Java |
| Persistence</a> (JPA) technologies. In it, you use two of the IDE's wizards that are essential |
| to Java EE development. These are:</p> |
| |
| <ul style="margin-left: 320px"> |
| <li><strong>Entity Classes from Database wizard:</strong> Creates a Java Persistence API |
| entity class for each selected database table, complete with named query annotations, |
| fields representing columns, and relationships representing foreign keys.</li> |
| |
| <li><strong>Session Beans for Entity Classes wizard:</strong> Creates an EJB session facade |
| for each entity class with basic access methods.</li> |
| </ul> |
| |
| <p>These two wizards provide an efficient way for you to quickly set up the model for your |
| application. If you reexamine the <a href="design.html#mvcDiagram">MVC diagram</a> for |
| the application you are building, you can see where EJB session beans and JPA entity |
| classes fit into its structure.</p> |
| |
| <div class="indent" style="text-align: center"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/design/mvc-diagram.png" |
| style="width:596px; margin-top:10px; margin-bottom:10px" |
| title="MVC diagram of the AffableBean application" |
| alt="MVC diagram of the AffableBean application"> |
| </div> |
| |
| <p>In this unit, the entity classes you create form a Java-based representation of the <code>affablebean</code> |
| database. While each entity class represents a database table, instances of entity classes |
| correspond to records that can be saved (i.e., <em>persisted</em>) to the database. The business |
| logic of the application is encapsulated by session beans, which can either be used as <em>facade</em> |
| classes that enable CRUD (Create-Read-Update-Delete) access to entities (as demonstrated here), |
| or they can contain code that implements actions specific to your application. (An example of this |
| is provided in <a href="#transaction">Unit 9: Integrating Transactional Business Logic</a>).</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans E-commerce |
| Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left;"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#glassFishEntitySession">GlassFish server</a></td> |
| <td class="tbltd1">v3 or Open Source Edition 3.0.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL database server</a></td> |
| <td class="tbltd1">version 5.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot3.zip">AffableBean |
| project</a></td> |
| <td class="tbltd1">snapshot 3</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><strong class="notes">Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which are |
| required for the application you build in this tutorial.</li> |
| |
| <li id="glassFishEntitySession">The NetBeans IDE Java Bundle also includes the GlassFish server, |
| which you require for this tutorial. You could |
| <a href="http://glassfish.dev.java.net/public/downloadsindex.html" target="_blank">download |
| the GlassFish server independently</a>, but the version provided with the |
| NetBeans download has the added benefit of being automatically registered with |
| the IDE.</li> |
| |
| <li>You can follow this tutorial unit without having completed previous units. To |
| do so, see the <a href="#setup">setup instructions</a>, which describe how |
| to prepare the database and establish connectivity between the IDE, GlassFish, |
| and MySQL.</li> |
| |
| <li><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot4.zip">Snapshot |
| 4</a> of the <code>AffableBean</code> project is available for download and |
| corresponds to state the project after completing this unit using NetBeans IDE |
| 6.9.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="whatEJB">What are EJB and JPA Technologies?</h2> |
| |
| <p>Up until now, the project that you've been developing in this tutorial could be run |
| in a web server with a servlet container, such as Apache Tomcat. After all, you've |
| so far only made use of JSTL and servlet technologies, and are connecting to the |
| database directly using JDBC. In fact, you could theoretically continue to develop |
| the application using just these technologies, while manually coding for all aspects |
| of your application, including thread-safety, transactions, and security. However, |
| using Enterprise beans with JPA entity classes allows you focus on the business logic |
| of your application while relying on solutions that have already been tried and tested. |
| The following sections introduce the two technologies and define their role in EE |
| development.</p> |
| |
| <ul> |
| <li><a href="#ejb">Enterprise JavaBeans</a></li> |
| <li><a href="#jpa">Java Persistence</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="ejb">Enterprise JavaBeans</h3> |
| |
| <p>The official <a href="http://java.sun.com/products/ejb/" target="_blank">EJB product |
| page</a> describes EnterPrise JavaBeans technology as a "server-side component |
| architecture" that "enables rapid and simplified development of distributed, |
| transactional, secure and portable applications." You can apply EJBs (i.e., |
| Enterprise beans) to your projects, and the services provided by the technology |
| remain transparent to you as a developer, thus eliminating the tedious and often |
| error-prone task of adding a lot of boiler plate code which would otherwise be |
| required. If you are new to EE development, you may question the need for EJBs in |
| your Java web application. The book |
| <a href="http://www.manning.com/panda/" target="_blank">EJB 3 In Action</a>, by Debu |
| Panda, Reza Rahman and Derek Lane, paraphrases the role of EJB technology nicely:</p> |
| |
| <blockquote style="margin-top: 0"> |
| <em>Although many people think EJBs are overkill for developing relatively |
| simple web applications of moderate size, nothing could be further from |
| the truth. When you build a house, you don't build everything from scratch. |
| Instead, you buy materials or even the services of a contractor as you need |
| it. It isn't too practical to build an enterprise application from scratch |
| either. Most server-side applications have a lot in common, including churning |
| business logic, managing application state, storing and retrieving information |
| from a relational database, managing transactions, implementing security, |
| performing asynchronous processing, integrating systems, and so on. |
| |
| <br><br> |
| As a framework, the EJB container provides these kinds of common functionality |
| as out-of-the-box services so that your EJB components can use them in your |
| applications without reinventing the wheel. For instance, let's say that when |
| you build a credit card module in your web application, you write a lot of |
| complex and error-prone code to manage transactions and security access control. |
| You could have avoided that by using the declarative transaction and security |
| services provided by the EJB container. These services as well as many others |
| are available to EJB components when they are deployed in an EJB container. |
| This means writing high-quality, feature-rich applications much faster than |
| you might think.</em><sup><a href="#footnote1EntitySession" id="1EntitySession" |
| style="text-decoration:none">[1]</a></sup> |
| </blockquote> |
| |
| <p>You can think of EJB both as components, or Java classes that are incorporated in |
| your project, as well as a <em>framework</em> that provides numerous enterprise-related |
| services. Some of the services that we take advantage of in this tutorial are described |
| in <a href="http://www.manning.com/panda/" target="_blank">EJB 3 In Action</a> as follows:</p> |
| |
| <ul> |
| <li><strong>Pooling:</strong> For each EJB component, the EJB platform creates |
| a pool of component instances that are shared by clients. At any point in |
| time, each pooled instance is only allowed to be used by a single client. |
| As soon as an instance is finished servicing a client, it is returned to |
| the pool for reuse instead of being frivolously discarded for the garbage |
| collector to reclaim.</li> |
| |
| <li><strong>Thread Safety:</strong> EJB makes all components thread-safe and |
| highly performant in ways athat are completely invisible. This means that |
| you can write your server components as if you were developing a single-threaded |
| desktop application. It doesn't matter how complex the component itself is; |
| EJB will make sure it is thread-safe.</li> |
| |
| <li><strong>Transactions:</strong> EJB supports declarative transaction management |
| that helps you add transactional behavior to components using simple |
| configuration instead of code. In effect, you can designate any component |
| method to be transactional. If the method completes normally, EJB commits |
| the transaction and makes the data changes made by the method permanent. |
| Otherwise the transaction is rolled back. Container-managed EJB transactions |
| are demonstrated in Unit 9, <a href="#transaction">Integrating Transactional |
| Business Logic</a>.</li> |
| |
| <li><strong>Security:</strong> EJB supports integration with the Java Authentication |
| and Authorization Service (JAAS) API, so it is easy to completely externalize |
| security and secure an application using simple configuration instead of cluttering |
| up your application with security code.<sup><a href="#footnote2EntitySession" id="2EntitySession" |
| style="text-decoration:none">[2]</a></sup> In Unit 11, <a href="security.html#secureEJB">Securing |
| the Application</a>, a demonstration of EJB's <a href="http://download.oracle.com/javaee/6/api/javax/annotation/security/RolesAllowed.html" |
| target="_blank"<code>@RolesAllowed</code></a> annotation is provided.</li> |
| </ul> |
| |
| |
| <h3 id="jpa">Java Persistence</h3> |
| |
| <p>In the context of Java Enterprise, <em>persistence</em> refers to the act of |
| automatically storing data contained in Java objects into a relational database. |
| The <a href="http://java.sun.com/javaee/technologies/persistence.jsp" target="_blank">Java |
| Persistence API</a> (JPA) is an object-relational mapping (ORM) technology that |
| enables applications to manage data between Java objects and a relational database |
| in a way that is transparent to the developer. This means that you can apply |
| JPA to your projects by creating and configuring a set of Java classes (<em>entities</em>) |
| that mirror your data model. Your application can then access these entities |
| as though it were directly accessing the database.</p> |
| |
| <p>There are various benefits to using JPA in your projects:</p> |
| |
| <ul> |
| <li>JPA has its own rich, SQL-like query language for static and dynamic queries. |
| Using the Java Persistence Query Language (JPQL), your applications remain |
| portable across different database vendors.</li> |
| |
| <li>You can avoid the task of writing low-level, verbose and error-prone JDBC/SQL code.</li> |
| |
| <li>JPA transparently provides services for data caching and performance optimization.</li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2 id="whatSession">What are Session Beans?</h2> |
| |
| <p>Enterprise session beans are invoked by a client in order to perform a specific business |
| operation. The name <em>session</em> implies that a bean instance is available for the |
| duration of a "unit of work". The <a href="http://jcp.org/aboutJava/communityprocess/final/jsr318/index.html" target="_blank">EJB |
| 3.1 specification</a> describes a typical session object as having the following |
| characteristics:</p> |
| |
| <ul class="toc"> |
| <li>Executes on behalf of a single client</li> |
| <li>Can be transaction-aware</li> |
| <li>Updates shared data in an underlying database</li> |
| <li>Does not represent directly shared data in the database, although it may |
| access and update such data</li> |
| <li>Is relatively short-lived</li> |
| <li>Is removed when the EJB container crashes. The client has to re-establish |
| a new session object to continue computation.</li> |
| </ul> |
| |
| <p>EJB provides three types of session beans: <em>stateful</em>, <em>stateless</em>, |
| and <em>singleton</em>. The following descriptions are adapted from the |
| <a href="http://download.oracle.com/docs/cd/E17410_01/javaee/6/tutorial/doc/index.html" target="_blank">Java |
| EE 6 Tutorial</a>.</p> |
| |
| <ul> |
| <li><strong>Stateful:</strong> The state of the bean is maintained across multiple |
| method calls. The "state" refers to the values of its instance variables. |
| Because the client interacts with the bean, this state is often called the |
| <em>conversational</em> state.</li> |
| |
| <li><strong>Stateless:</strong> Stateless beans are used for operations that can |
| occur in a single method call. When the method finishes processing, the |
| client-specific state of the bean is not retained. A stateless session bean |
| therefore does not maintain a conversational state with the client.</li> |
| |
| <li><strong>Singleton:</strong> A singleton session bean is instantiated once |
| per application, and exists for the lifecycle of the application. Singleton |
| session beans are designed for circumstances where a single enterprise bean |
| instance is shared across and concurrently accessed by clients.</li> |
| </ul> |
| |
| <p class="tips">For more information on EJB session beans, see the |
| <a href="http://download.oracle.com/docs/cd/E17410_01/javaee/6/tutorial/doc/gipjg.html" target="_blank">Java |
| EE 6 Tutorial: What is a Session Bean?</a>.</p> |
| |
| <p>For purposes of developing the e-commerce application in this tutorial, we will |
| only be working with stateless session beans.</p> |
| |
| |
| <br> |
| <h2 id="specification">About Specifications and Implementations</h2> |
| |
| <p>EJB and JPA technologies are defined by the following specifications:</p> |
| |
| <ul> |
| <li><a href="http://jcp.org/en/jsr/summary?id=317" target="_blank">JSR 317: Java Persistence 2.0</a></li> |
| <li><a href="http://jcp.org/en/jsr/summary?id=318" target="_blank">JSR 318: Enterprise JavaBeans 3.1</a></li> |
| </ul> |
| |
| <p>These specifications define the technologies. To apply a technology to your |
| project however, you must use an <em>implementation</em> of the specification. |
| When a specification becomes finalized, it includes a reference implementation, |
| which is a free implementation of the technology. If you find this concept |
| confusing, consider the following analogy: A musical composition (i.e., the notes |
| on a page) defines a piece of music. When a musician learns the composition and |
| records her performance, she provides an <em>interpretation</em> of the piece. |
| In this manner the musical composition is likened to the technical specification, |
| and the musician's recording corresponds to the specification's implementation.</p> |
| |
| <p class="tips">See <a href="intro.html#jcp">What is the Java Community Process?</a> |
| for an explanation of Java technical specifications, and how they are formally |
| standardized.</p> |
| |
| <p>If you examine the download pages for the final releases of the EJB and JPA specifications, |
| you'll find links to the following reference implementations:</p> |
| |
| <ul> |
| <li><strong>JPA:</strong> <a href="http://www.eclipse.org/eclipselink/downloads/ri.php" target="_blank">http://www.eclipse.org/eclipselink/downloads/ri.php</a></li> |
| <li><strong>EJB:</strong> <a href="http://glassfish.dev.java.net/downloads/ri" target="_blank">http://glassfish.dev.java.net/downloads/ri</a></li> |
| </ul> |
| |
| <p>Implementations of the JPA specification are dubbed <em>persistence providers</em>, |
| and the persistence provider which has been chosen as the reference implementation |
| for the JPA 2.0 specification is <a href="http://www.eclipse.org/eclipselink/" target="_blank">EclipseLink</a>.</p> |
| |
| <p>If you examine the link for the EJB reference implementation, you'll come to a page |
| that lists not only the implementation for EJB, but for all reference implementations |
| provided by <a href="http://glassfish.dev.java.net/" target="_blank">Project GlassFish</a>. |
| The reason for this is that Project GlassFish forms the reference implementation of the |
| Java EE 6 platform specification (<a href="http://jcp.org/en/jsr/summary?id=316" target="_blank">JSR |
| 316</a>). The GlassFish v3 application server (or the Open Source Edition), which you |
| are using to build the e-commerce project in this tutorial, contains the reference |
| implementations of all technologies developed under Project GlassFish. As such, it |
| is referred to as a Java EE 6 <em>container</em>.</p> |
| |
| <p>A Java EE container contains three essential components: a web (i.e., servlet) container, |
| an EJB container, and a persistence provider. The deployment scenario for the e-commerce |
| application is displayed in the diagram below. Entity classes that you create in this |
| unit are managed by the persistence provider. The session beans that you create in this |
| unit are managed by the EJB container. Views are rendered in JSP pages, which are |
| managed by the web container.</p> |
| |
| <div id="gf-java-ee-container" class="indent"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/java-ee-container.png" |
| class="margin-around" alt="GlassFish v3 Java EE container" |
| title="As a Java EE container, GlassFish v3 contains web and EJB containers, and EclipseLink, the persistence provider"> |
| </div> |
| |
| |
| <br> |
| <h2 id="addEntity">Adding Entity Classes</h2> |
| |
| <p>Begin by using the IDE's Entity Classes from Database wizard to generate entity classes |
| based on the <code>affablebean</code> schema. The wizard relies on the underlying |
| persistence provider to accomplish this task.</p> |
| |
| <ol> |
| <li>Open the <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot3.zip">project |
| snapshot</a> in the IDE. In the IDE, press Ctrl-Shift-O (�-Shift-O on Mac) and |
| navigate to the location on your computer where you unzipped the downloaded file.</li> |
| |
| <li>Press Ctrl-N (⌘-N on Mac) to open the File wizard.</li> |
| |
| <li>Select the Persistence category, then select Entity Classes from Database. Click Next.</li> |
| |
| <li>In Step 2: Database Tables, choose <code>jdbc/affablebean</code> from the Data Source |
| drop-down list. The drop-down list is populated by data sources registered with the |
| application server. |
| |
| <br><br> |
| When you choose the <code>jdbc/affablebean</code> data source, the IDE scans the |
| database and lists the database tables in the Available Tables pane. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/entity-from-database.png" |
| class="margin-around b-all" alt="Entity Classes from Database wizard" style="width: 688px" |
| title="Choose an available data source to have the IDE read in database tables"></li> |
| |
| <li>Click the Add All button, then click Next.</li> |
| |
| <li>Step 3 of the Entity Classes from Database wizard differs slightly between NetBeans |
| IDE 6.8 and 6.9. Depending on the version IDE you are using, perform the following steps. |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><a href="#68">NetBeans IDE 6.8</a></li> |
| <li><a href="#69">NetBeans IDE 6.9</a></li> |
| </ul> |
| |
| <h4 id="68">NetBeans IDE 6.8</h4> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/entity-classes-68.png" |
| class="margin-around b-all" alt="Entity Classes from Database wizard, Step 3: Entity Classes" |
| title="NetBeans 6.8 - Entity Classes from Database wizard, Step 3: Entity Classes" width="688px"> |
| |
| <ol style="list-style-type: lower-alpha"> |
| <li>Type in <strong>entity</strong> in the Package field. The wizard will create a new |
| package for the entity classes upon completing.</li> |
| |
| <li>Click the Create Persistence Unit button. The Create Persistence Unit dialog opens. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/create-pu.png" |
| class="margin-around b-all" alt="Create Persistence Unit dialog" |
| title="Use the Create Persistence Unit dialog to generate a persistence.xml file"> |
| |
| <br> |
| A <em>persistence unit</em> refers to a collection of entity classes that exist in an |
| application. The above dialog generates a <code>persistence.xml</code> file, which is |
| used by your persistence provider to specify configuration settings for the persistence |
| unit. Note that 'EclipseLink (JPA 2.0)' is the default selection for the server associated |
| with the project. Leave 'Table Generation Strategy' set to '<code>None</code>'. This |
| prevents the persistence provider from affecting your database. (For example, if you |
| want the persistence provider to delete then recreate the database based on the existing |
| entity classes, you could set the strategy to '<code>Drop and Create</code>'. This action |
| would then be taken each time the project is deployed.)</li> |
| |
| <li>Click Create.</li> |
| |
| <li>Back in Step 3: Entity Classes, note that the class names for the entities are based |
| on database tables. For example, the <code>CustomerOrder</code> entity is mapped to |
| the <code>customer_order</code> database table. Also note that the 'Generate Named |
| Query Annotations for Persistent Fields' option is selected by default. We will be |
| using various named queries later in the tutorial.</li> |
| |
| <li>Continue to <a href="#step7">step 7</a> below.</li> |
| </ol> |
| |
| <h4 id="69">NetBeans IDE 6.9</h4> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/entity-classes-69.png" |
| class="margin-around b-all" alt="Entity Classes from Database wizard, Step 3: Entity Classes" |
| title="NetBeans 6.9 - Entity Classes from Database wizard, Step 3: Entity Classes" width="688px"> |
| |
| <ol style="list-style-type: lower-alpha"> |
| |
| <li>Type in <strong>entity</strong> in the Package field. The wizard will create a new |
| package for the entity classes upon completing.</li> |
| |
| <li>Note the following: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li>The class names for the entities are based on database tables. For example, the |
| <code>CustomerOrder</code> entity will be mapped to the <code>customer_order</code> |
| database table.</li> |
| |
| <li>The 'Generate Named Query Annotations for Persistent Fields' option is selected by |
| default. We will be using various named queries later in the tutorial.</li> |
| |
| <li>The 'Create Persistence Unit' option is selected by default. A <em>persistence |
| unit</em> is a collection of entity classes that exist in an application. The |
| persistence unit is defined by a <code>persistence.xml</code> configuration file, |
| which is read by your persistence provider. Enabling this option therefore means |
| that the wizard will also generate a <code>persistence.xml</code> file and populate |
| it with default settings.</li> |
| </ul> |
| </li> |
| </ol></li> |
| |
| <li id="step7">Click Finish. The JPA entity classes are generated, based on the <code>affablebean</code> |
| database tables. You can examine the entity classes in the Projects window by expanding |
| the newly created <code>entity</code> package. Also, note that the new persistence unit |
| exists under the Configuration Files node. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/entity-classes.png" |
| class="margin-around b-all" alt="Projects window - entity classes displayed in project" |
| title="View new entity classes in the Projects window"> |
| |
| <br><br> |
| Note that the wizard generated an additional entity class, <code>OrderedProductPK</code>. |
| Recall that the data model's <code>ordered_product</code> table uses a composite |
| primary key that comprises the primary keys of both the <code>customer_order</code> |
| and <code>product</code> tables. (See <a href="data-model.html#manyToMany">Designing |
| the Data Model - Creating Many-To-Many Relationships</a>.) Because of this, the |
| persistence provider creates a separate entity class for the composite key, and |
| <em>embeds</em> it into the <code>OrderedProduct</code> entity. You can open |
| <code>OrderedProduct</code> in the editor to inspect it. JPA uses the <code>@EmbeddedId</code> |
| annotation to signify that the embeddable class is a composite primary key. |
| |
| <pre class="examplecode"> |
| public class OrderedProduct implements Serializable { |
| private static final long serialVersionUID = 1L; |
| <strong>@EmbeddedId</strong> |
| protected OrderedProductPK orderedProductPK;</pre> |
| |
| <p class="tips">Press Ctrl-Space on the <code>@EmbeddedId</code> annotation to |
| invoke the API documentation.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/embedded-id.png" |
| class="margin-around b-all" alt="API documentation invoked on @EmbeddedId" |
| title="Press Ctrl-Space to invoke the API documentation"></li> |
| |
| <li id="pu">Open the persistence unit (<code>persistence.xml</code>) in the editor. The |
| IDE provides a Design view for persistence units, in addition to the XML view. The |
| Design view provides a convenient way to make configuration changes to the persistence |
| provider's management of the project. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/persistence-unit.png" |
| class="margin-around b-all" alt="Design view of AffableBeanPU persistence unit" style="width: 688px" |
| title="Design view of the AffableBeanPU persistence unit"></li> |
| |
| <li>Click the XML tab at the top of the <code>AffableBeanPU</code> persistence unit |
| to open the XML view. Add the following property to the file. |
| |
| <pre class="examplecode"> |
| <persistence-unit name="AffableBeanPU" transaction-type="JTA"> |
| <jta-data-source>jdbc/affablebean</jta-data-source> |
| <strong><properties> |
| <property name="eclipselink.logging.level" value="FINEST"/> |
| </properties></strong> |
| </persistence-unit></pre> |
| |
| You set the logging level property to <code>FINEST</code> so that you can view all |
| possible output produced by the persistence provider when the application runs. This |
| enables you to see the SQL that the persistence provider is using on the database, |
| and can facilitate in any required debugging. |
| |
| <br><br> |
| <p class="tips">See the official EclipseLink documentation for an explanation |
| of logging and a list of all logging values: |
| <a href="http://wiki.eclipse.org/EclipseLink/Examples/JPA/Logging" target="_blank">How |
| To Configure Logging</a></p></li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="addSession">Adding Session Beans</h2> |
| |
| <p>In this section, we use the IDE's Session Beans for Entity Classes wizard to generate |
| an EJB <em>session facade</em> for each of the entity classes that you just created. |
| Each session bean will contain basic access methods for its respective entity class.</p> |
| |
| <p>A <em>session facade</em> is a design pattern advertised in the |
| <a href="http://java.sun.com/blueprints/enterprise/index.html" target="_blank">Enterprise |
| BluePrints program</a>. As stated in the |
| <a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/SessionFacade.html" target="_blank">Core |
| J2EE Pattern Catalog</a>, it attempts to resolve common problems that arise in a |
| multi-tiered application environment, such as:</p> |
| |
| <ul class="toc"> |
| <li>Tight coupling, which leads to direct dependence between clients and business objects</li> |
| <li>Too many method invocations between client and server, leading to network performance problems</li> |
| <li>Lack of a uniform client access strategy, exposing business objects to misuse</li> |
| </ul> |
| |
| <p>A session facade abstracts the underlying business object interactions and provides a |
| service layer that exposes only the required functionality. Thus, it hides from the |
| client's view the complex interactions between the participants. Thus, the session |
| bean (representing the session facade) manages the relationships between business |
| objects. The session bean also manages the life cycle of these participants by |
| creating, locating, modifying, and deleting them as required by the workflow.</p> |
| |
| <ol> |
| <li>Press Ctrl-N (⌘-N on Mac) to open the File wizard.</li> |
| |
| <li>Select the Persistence category, then select Session Beans for Entity Classes. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/session-beans-for-entity-classes.png" |
| class="margin-around b-all" alt="File wizard: Persistence category, Session Beans for Entity Classes file type" |
| style="width: 688px" title="Select Session Beans for Entity Classes to generate a session facade for your persistence model"></li> |
| |
| <li>Click Next.</li> |
| |
| <li>In Step 2: Entity Classes, note that all entity classes contained in your project |
| are listed on the left, under Available Entity Classes. Click Add All. All entity |
| classes are moved to the right, under Selected Entity Classes.</li> |
| |
| <li>Click Next.</li> |
| |
| <li>In Step 3: Generated Session Beans, type in <strong>session</strong> into the Package field. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/generated-session-beans.png" |
| class="margin-around b-all" alt="Session Beans for Entity Classes wizard - Step 3: Generated Session Beans" |
| title="Specify the location of the new session beans, and whether to create interfaces"> |
| |
| <br> |
| <p class="notes"><strong>Note:</strong> You can use the wizard to generate local and remote |
| interfaces for the session beans. While there is benefit to programming session beans to |
| interfaces (For example, hiding business object interactions behind an interface enables |
| you to further decouple the client from your business logic. This also means that you can |
| code multiple implementations of the interface for your application, should the need arise.), |
| this lies outside the scope of the tutorial. Note that EJB versions prior to 3.1 <em>require</em> |
| that you implement an interface for each session bean.</p></li> |
| |
| <li>Click Finish. The IDE generates session beans for each of the entity classes contained |
| in your project. In the Projects window, expand the new <code>session</code> package to |
| examine the session beans. |
| |
| <br><br> |
| <table> |
| <tr class="align-left"> |
| <th style="padding-left:10px">NetBeans 6.8</th> |
| <th style="padding-left:10px">NetBeans 6.9</th> |
| </tr> |
| <tr> |
| <td> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/projects-window-session-beans.png" |
| class="margin-around b-all" alt="Projects window - session beans displayed in project" |
| title="Examine new session beans in the Projects window"> |
| </td> |
| <td> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/projects-window-session-beans-69.png" |
| class="margin-around b-all" alt="Projects window - session beans displayed in project" |
| title="Examine new session beans in the Projects window"> |
| </td> |
| </tr> |
| </table> |
| |
| <p class="notes"><strong>Note:</strong> As shown above, NetBeans IDE 6.9 provides slight |
| improvements in the way the Session Beans for Entity Classes wizard generates facade |
| classes. Namely, boiler-plate code that is common to all classes is factored out |
| into an abstract class named <code>AbstractFacade</code>. If you are working in version |
| 6.9, open any of the facade classes that have been generated (aside from <code>AbstractFacade</code>). |
| You'll see that the class extends <code>AbstractFacade</code>.</p></li> |
| |
| <li>Open a session facade in the editor, for example, <code>ProductFacade</code>. All of |
| the generated session facades instantiate an |
| <a href="http://java.sun.com/javaee/6/docs/api/javax/persistence/EntityManager.html" |
| target="_blank"><code>EntityManager</code></a> using the |
| <a href="http://download.oracle.com/javaee/6/api/javax/persistence/PersistenceContext.html" |
| target="_blank"><code>@PersistenceContext</code></a> annotation. |
| |
| <pre class="examplecode"> |
| @PersistenceContext(unitName = "AffableBeanPU") |
| private EntityManager em;</pre> |
| |
| The <code>@PersistenceContext</code> annotation is used to inject a container-managed |
| <code>EntityManager</code> into the class. In other words, we rely on GlassFish' EJB |
| container to open and close <code>EntityManager</code>s as and when needed. The |
| <code>unitName</code> element specifies the <code>AffableBeanPU</code> persistence unit, |
| which has been defined in the application's <code>persistence.xml</code> file. |
| |
| <br><br> |
| The <code>EntityManager</code> is an integral component of the Java Persistence |
| API, and is responsible for performing persistence actions on the database. |
| The book <a href="http://www.manning.com/panda/" target="_blank">EJB 3 In Action</a> |
| describes the <code>EntityManager</code> as follows: |
| |
| <blockquote> |
| <em>The JPA <code>EntityManager</code> interface manages entities in terms |
| of actually providing persistence services. While entities tell a JPA |
| provider how they map to the database, they do not persist themselves. |
| The <code>EntityManager</code> interface reads the ORM metadata for an |
| entity and performs persistence operations.</em> |
| </blockquote></li> |
| |
| <!-- TEXT CURRENTLY NOT USED: |
| |
| In the above example, the <code>EntityManager</code>'s <code>createQuery</code> |
| method is called to perform a query on the database. If you examine the |
| <code>createQuery</code> API documentation (press Ctrl-Space on the method |
| in the editor), you see that the method takes a Java Persistence Query Language |
| (JPQL) query string as an argument, and returns a <code>Query</code> object. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/create-query-api.png" |
| class="margin-around b-all" alt="API documentation for EntityManager's createQuery method" |
| style="width:688px" title="Press Ctrl-Space to view API documentation"> |
| |
| <br> |
| <p class="tips">For more information on the JPQL, including terminology, syntax, |
| and example queries, see the |
| <a href="http://download.oracle.com/docs/cd/E17410_01/javaee/6/tutorial/doc/bnbtg.html" target="_blank">Java |
| EE 6 Tutorial, Chapter 21: The Java Persistence Query Language</a>.</p> |
| |
| The <code>Query</code> object in turn calls <code>setParameter</code> to |
| bind the <code>categoryId</code> parameter used in the query string with the |
| the <code>Category</code> object that is passed into the method. Finally, |
| <code>getResultList()</code> is called to execute a <code>SELECT</code> query |
| and return the query results as a <code>List</code> of <code>Product</code>s. |
| --> |
| </ol> |
| |
| <p>Your application now contains a persistence model of the <code>affablebean</code> database in |
| the form of JPA entity classes. It also contains a session facade consisting of Enterprise |
| beans that can be used to access the entity classes. The next section demonstrates how you |
| can access the database using the session beans and entity classes.</p> |
| |
| |
| <br> |
| <h2 id="access">Accessing Data with EJBs</h2> |
| |
| <p>In the <a href="#connect-db">previous tutorial unit</a>, you learned how to access the |
| database from the application by configuring a data source on GlassFish, adding a resource |
| reference to the application's deployment descriptor, and using JSTL <code><sql></code> |
| tags in the application's JSP pages. This is a valuable technique, as it allows you to |
| quickly set up prototypes that include data from the database. However, this is not a |
| realistic scenario for medium to large-sized applications, or applications managed by a |
| team of developers, as it would prove difficult to maintain or scale. Furthermore, if you |
| are developing the application into multiple tiers or are adhering to the MVC pattern, you |
| would not want to keep data-access code in your front-end. Using Enterprise beans with a |
| persistence model enables you better conform to the MVC pattern by effectively decoupling |
| the presentation and model components.</p> |
| |
| <p>The following instructions demonstrate how to begin using the session and entity beans in |
| the <code>AffableBean</code> project. You are going to remove the JSTL data access logic |
| that you previously set up for the index and category pages. In its place, you'll utilize |
| the data access methods provided by the session beans, and store the data in scoped |
| variables so that it can be retrieved from front-end page views. We'll tackle the index |
| page first, then move on to the more complicated category page.</p> |
| |
| <ul> |
| <li><a href="#index">index page</a></li> |
| <li><a href="#category">category page</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="index">index page</h3> |
| |
| <p>The index page requires data for the four product categories. In our current setup, |
| the JSTL <code><sql></code> tags query the database for category details each |
| time the index page is requested. Since this information is rarely modified, it makes |
| more sense from a performance standpoint to perform the query only once after the |
| application has been deployed, and store the data in an application-scoped attribute. |
| We can accomplish this by adding this code to the <code>ControllerServlet</code>'s |
| <code>init</code> method.</p> |
| |
| <ol> |
| <li>In the Projects window, double-click the Source Packages > <code>controller</code> |
| > <code>ControllerServlet</code> node to open it in the editor.</li> |
| |
| <li>Declare an instance of <code>CategoryFacade</code>, and apply the <code>@EJB</code> |
| annotation to the instance. |
| |
| <pre class="examplecode"> |
| public class ControllerServlet extends HttpServlet { |
| |
| <strong>@EJB |
| private CategoryFacade categoryFacade;</strong> |
| |
| ... |
| }</pre> |
| |
| The <code>@EJB</code> annotation instructs the EJB container to instantiate |
| the <code>categoryFacade</code> variable with the EJB named <code>CategoryFacade</code>.</li> |
| |
| <li>Use the IDE's hints to add import statements for: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><code>javax.ejb.EJB</code></li> |
| <li><code>session.CategoryFacade</code></li> |
| </ul> |
| |
| <p class="tips">Pressing Ctrl-Shift-I (⌘-Shift-I on Mac) automatically adds |
| required imports to your class.</p></li> |
| |
| <li>Add the following <code>init</code> method to the class. The web container |
| initializes the servlet by calling its <code>init</code> method. This occurs |
| only once, after the servlet is loaded and before it begins servicing requests. |
| |
| <pre class="examplecode"> |
| public class ControllerServlet extends HttpServlet { |
| |
| @EJB |
| private CategoryFacade categoryFacade; |
| |
| <strong>public void init() throws ServletException { |
| |
| // store category list in servlet context |
| getServletContext().setAttribute("categories", categoryFacade.findAll()); |
| }</strong> |
| |
| ... |
| }</pre> |
| |
| Here, you apply the facade class' <code>findAll</code> method to query |
| the database for all records of <code>Category</code>. You then set the resulting |
| <code>List</code> of <code>Category</code> objects as an attribute that can be |
| referenced by the "<code>categories</code>" string. Placing the |
| reference in the <code>ServletContext</code> means that the reference exists |
| in a scope that is application-wide. |
| |
| <br><br> |
| <p class="tips">To quickly determine the method signature of the <code>findAll</code> |
| method, hover your mouse over the method while holding down the Ctrl key |
| (⌘ on Mac). (The image below displays the popup that appears using |
| NetBeans IDE 6.8.)</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/method-signature.png" |
| class="margin-around b-all" alt="Editor displaying method signature in a pop-up" |
| title="Over your mouse over the method while holding down the Ctrl key to view its signature"> |
| |
| <br> |
| Clicking the hyperlink enables you to navigate directly to the method.</li> |
| |
| <li>Use the IDE's hint to add the <code>@Overrides</code> annotation. The <code>init</code> |
| method is defined by <code>HttpServlet</code>'s superclass, <code>GenericServlet</code>. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/override.png" |
| class="margin-around b-all" alt="Hint displayed in editor" |
| title="Use the IDE's hint to add the @Overrides annotation to the method"> |
| |
| <br> |
| Adding the annotation is not required, however it does provide several advantages: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li>It enables you to use compiler checking to ensure that you are actually |
| overriding a method that you assume you are overriding.</li> |
| |
| <li>It improves readability, as it becomes clear when methods in your source code |
| are being overridden.</li> |
| </ul> |
| |
| <p class="tips">For more information on annotations, see the |
| <a href="http://download.oracle.com/javase/tutorial/java/javaOO/annotations.html" target="_blank">Java |
| Tutorials: Annotations</a>.</p></li> |
| |
| <li>Now that you have set up an application-scoped attribute that contains a list of |
| categories, modify the index page to access the newly created attribute. |
| |
| <br><br> |
| Double-click the Web Pages > <code>index.jsp</code> node in the Projects window |
| to open the file in the editor.</li> |
| |
| <li>Comment out (or delete) the <code><sql:query></code> statement that is |
| listed at the top of the file. To comment out code in the editor, highlight |
| the code, then press Ctrl-/ (⌘-/ on Mac). |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/commented-out.png" |
| class="margin-around b-all" alt="Commented-out snippet displayed in editor" |
| title="Press Ctrl-/ to comment out a code snippet in the editor"></li> |
| |
| <li>Modify the opening <code><c:forEach></code> tag so that its <code>items</code> |
| attribute references the new application-scoped <code>categories</code> attribute. |
| |
| <pre class="examplecode"><c:forEach var="category" items="<strong>${categories}</strong>"></pre></li> |
| |
| <li>Open the project's web deployment descriptor. Press Alt-Shift-O (Ctrl-Shift-O on Mac) |
| and in the Go to File dialog, type '<code>web</code>', then click OK. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/go-to-file.png" |
| class="margin-around b-all" alt="Go to File dialog" |
| title="Use the Go to File dialog to quickly open files in the editor"></li> |
| |
| <li>Comment out (or delete) the <code><resource-ref></code> entry. The entry was required |
| for the <code><sql></code> tags in order to identify the data source registered on the |
| server. We are now relying on JPA to access the database, and the <code>jdbc/affablebean</code> |
| data source has already been specified in the persistence unit. (Refer to the <a href="#pu">Design |
| view of the project's persistence unit</a> above.) |
| |
| <br><br> |
| Highlight the entire <code><resource-ref></code> entry, then press Ctrl-/ (⌘-/ on Mac). |
| |
| <pre class="examplecode"> |
| <strong><!-- </strong><resource-ref> |
| <description>Connects to database for AffableBean application</description> |
| <res-ref-name>jdbc/affablebean</res-ref-name> |
| <res-type>javax.sql.ConnectionPoolDataSource</res-type> |
| <res-auth>Container</res-auth> |
| <res-sharing-scope>Shareable</res-sharing-scope> |
| </resource-ref> <strong>--></strong></pre></li> |
| |
| <li>Run the project. Click the Run Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) button. The project's index page opens in the browser, |
| and you see that all four category names and images display. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/index-page.png" |
| class="margin-around b-all" alt="Index page displaying category details" style="width:688px" |
| title="Verify that the index page is able to retrieve category details"></li> |
| </ol> |
| |
| |
| <h3 id="category">category page</h3> |
| |
| <p>The <a href="design.html#category">category page</a> requires three pieces of data |
| in order to render properly:</p> |
| |
| <ol style="margin: 5px 0 0 -1em" class="toc"> |
| <li><strong>category data:</strong> for left column category buttons</li> |
| |
| <li><strong>selected category:</strong> the selected category is highlighted in |
| the left column, and the name of the selected category displays above the |
| product table</li> |
| |
| <li><strong>product data for selected category:</strong> for products displayed |
| in the product table</li> |
| </ol> |
| |
| <p>Let's approach each of the three pieces of data individually.</p> |
| |
| <ul style="margin: 5px 0 0 -1.5em"> |
| <li><a href="#categoryData">category data</a></li> |
| <li><a href="#selectedCategoryData">selected category</a></li> |
| <li><a href="#productData">product data for selected category</a></li> |
| </ul> |
| |
| <h4 id="categoryData">category data</h4> |
| |
| <p>To account for category data, we can reuse the application-scoped <code>categories</code> |
| attribute that we created for the index page.</p> |
| |
| <ol> |
| <li>Open <code>category.jsp</code> in the editor, and comment out (Ctrl-/; ⌘-/ on Mac) |
| the JSTL <code><sql></code> statements that are listed at the top of the file. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/comment-out-sql.png" |
| class="margin-around b-all" alt="<sql> statements commented out in editor" |
| title="Comment out JSTL <sql> statements in the category page"></li> |
| |
| <li>Modify the opening <code><c:forEach></code> tag so that its <code>items</code> |
| attribute references the application-scoped <code>categories</code> attribute. |
| (This is identical to what you did above for <code>index.jsp</code>.) |
| |
| <pre class="examplecode"><c:forEach var="category" items="<strong>${categories}</strong>"></pre></li> |
| |
| <li>Run the project to examine the current state of the category page. Click the Run Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) button. When the project's index page opens in the browser, |
| click any of the four categories. The category buttons in the left column display and |
| function as expected. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/category-page-left-column.png" |
| class="margin-around b-all" alt="Category page displaying category buttons in left column" |
| style="width:688px" title="Category buttons in left column display and function as expected"></li> |
| </ol> |
| |
| <h4 id="selectedCategoryData">selected category</h4> |
| |
| <p>To retrieve the selected category, we can use the <code>categoryFacade</code> |
| that we already created to find the <code>Category</code> whose ID matches |
| the request query string.</p> |
| |
| <ol> |
| <li>Open the <code>ControllerServlet</code> in the editor. (If already opened, press Ctrl-Tab |
| and choose from the pop-up list.)</li> |
| |
| <li>Start implementing functionality to acquire the selected category. Locate |
| the <code>TODO: Implement category request</code> comment, delete it and |
| add the following code (in <strong>bold</strong>). |
| |
| <pre class="examplecode"> |
| // if category page is requested |
| if (userPath.equals("/category")) { |
| |
| <strong>// get categoryId from request |
| String categoryId = request.getQueryString(); |
| |
| if (categoryId != null) { |
| |
| }</strong> |
| |
| // if cart page is requested |
| } else if (userPath.equals("/viewCart")) {</pre> |
| |
| You retrieve the requested category ID by calling <code>getQueryString()</code> |
| on the request. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> The logic to determine the selected |
| category within the left column category buttons is already implemented |
| in <code>category.jsp</code> using an EL expression, which is comparable |
| to calling <code>getQueryString()</code> in the servlet. The EL expression |
| is: <code>pageContext.request.queryString</code>.</p></li> |
| |
| <li>Add the following line of code within the <code>if</code> statement. |
| |
| <pre class="examplecode"> |
| // get categoryId from request |
| String categoryId = request.getQueryString(); |
| |
| if (categoryId != null) { |
| |
| <strong>// get selected category |
| selectedCategory = categoryFacade.find(Short.parseShort(categoryId));</strong> |
| }</pre> |
| |
| You use the <code>CategoryFacade</code>'s <code>find</code> method to |
| retrieve the <code>Category</code> object based on the requested category |
| ID. Note that you must cast <code>categoryId</code> to a <code>Short</code>, |
| as this is the type used for the <code>id</code> field in the <code>Category</code> |
| entity class.</li> |
| |
| <li>Click the badge ( <img src="../../../../images_www/articles/73/javaee/ecommerce/common/editor-badge.png" |
| alt="Hint badge"> ) in the left margin to use the editor's hint to declare |
| <code>selectedCategory</code> as a local variable within the <code>doGet</code> |
| method. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/local-variable.png" |
| class="margin-around b-all" alt="Editor hints" |
| title="Use editor hints to declare local variables"> |
| |
| <br> |
| Because <code>selectedCategory</code> is of type <code>Category</code>, which |
| hasn't yet been imported into the class, the IDE automatically adds an import |
| statement for <code>entity.Category</code> to the top of the file.</li> |
| |
| <li>Add the following line to place the retrieved <code>Category</code> object |
| in the request scope. |
| |
| <pre class="examplecode"> |
| // get categoryId from request |
| String categoryId = request.getQueryString(); |
| |
| if (categoryId != null) { |
| |
| // get selected category |
| selectedCategory = categoryFacade.find(Short.parseShort(categoryId)); |
| |
| <strong>// place selected category in request scope |
| request.setAttribute("selectedCategory", selectedCategory);</strong> |
| }</pre></li> |
| |
| <li>In the editor, switch to <code>category.jsp</code>. (Press Ctrl-Tab and choose from |
| the pop-up list.)</li> |
| |
| <li>Locate <code><p id="categoryTitle"></code> and make the following |
| change. |
| |
| <pre class="examplecode"> |
| <p id="categoryTitle"> |
| <span style="background-color: #f5eabe; padding: 7px;"><strong>${selectedCategory.name}</strong></span> |
| </p></pre> |
| |
| You are now using the <code>selectedCategory</code> attribute, which you just placed |
| in the request scope from the <code>ControllerServlet</code>. Using '<code>.name</code>' |
| within the EL expression calls the <code>getName</code> method on the given |
| <code>Category</code> object.</li> |
| |
| <li>Switch back to the browser and refresh the category page. The name of the selected |
| category now displays in the page. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/category-page-selected-category.png" |
| class="margin-around b-all" alt="Category page displaying name of selected category" |
| style="width:688px" title="Selected category name displays in the category page"> |
| </li> |
| </ol> |
| |
| <h4 id="productData">product data for selected category</h4> |
| |
| <p>In order to retrieve all products for a selected category, we'll make use of the |
| <code>Category</code> entity's <code>getProductCollection()</code> method. Start |
| by calling this method on <code>selectedCategory</code> to get a collection of |
| all <code>Product</code>s associated with the <code>selectedCategory</code>. |
| Then store the collection of products as an attribute in the request scope, and |
| finally reference the scoped attribute from the <code>category.jsp</code> page |
| view.</p> |
| |
| <ol> |
| <li>In the <code>ControllerServlet</code>, add the following statement to the code that |
| manages the category request. |
| |
| <pre class="examplecode"> |
| // if category page is requested |
| if (userPath.equals("/category")) { |
| |
| // get categoryId from request |
| String categoryId = request.getQueryString(); |
| |
| if (categoryId != null) { |
| |
| // get selected category |
| selectedCategory = categoryFacade.find(Short.parseShort(categoryId)); |
| |
| // place selected category in request scope |
| request.setAttribute("selectedCategory", selectedCategory); |
| |
| <strong>// get all products for selected category |
| categoryProducts = selectedCategory.getProductCollection();</strong> |
| }</pre> |
| |
| Calling <code>getProductCollection()</code> here enables us to get a collection |
| of all <code>Product</code>s associated with the <code>selectedCategory</code>.</li> |
| |
| <li>Use the editor's hint to define <code>categoryProducts</code> as a local variable |
| for the <code>doGet</code> method. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/local-variable2.png" |
| class="margin-around b-all" alt="Editor hints" |
| title="Use editor hints to declare local variables"></li> |
| |
| <li>Place the collection of <code>Product</code>s in the request scope so that it |
| can be retrieved from the application's front-end. |
| |
| <pre class="examplecode"> |
| // if category page is requested |
| if (userPath.equals("/category")) { |
| |
| // get categoryId from request |
| String categoryId = request.getQueryString(); |
| |
| if (categoryId != null) { |
| |
| // get selected category |
| selectedCategory = categoryFacade.find(Short.parseShort(categoryId)); |
| |
| // place selected category in request scope |
| request.setAttribute("selectedCategory", selectedCategory); |
| |
| // get all products for selected category |
| categoryProducts = selectedCategory.getProductCollection(); |
| |
| <strong>// place category products in request scope |
| request.setAttribute("categoryProducts", categoryProducts); |
| }</strong></pre></li> |
| |
| <li>Open the <code>category.jsp</code> file in the editor and make the following |
| change to the product table. |
| |
| <pre class="examplecode"> |
| <table id="productTable"> |
| |
| <c:forEach var="product" items="<strong>${categoryProducts}</strong>" varStatus="iter"></pre> |
| |
| The <code><c:forEach></code> tag now references the <code>categoryProducts</code> |
| collection. The <code>c:forEach</code> loop will now iterate over each <code>Product</code> |
| object contained in the collection, and extract data accordingly.</li> |
| |
| <li>Press F6 (fn-F6 on Mac) to run the project. Navigate to the category |
| page in the browser and note that all products now display for each category. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/entity-session/category-page-product-table.png" |
| class="margin-around b-all" alt="Category page displaying products in table" |
| style="width:688px" title="Product table displays products of a given category"> |
| </li> |
| </ol> |
| </div> |
| |
| <p>This tutorial unit provided a brief introduction to JPA and EJB technologies. It also |
| described the role of Java specifications, and how their reference implementations are |
| used by the GlassFish application server. It then demonstrated how to create a set of |
| JPA entity classes that provide a Java implementation of the project database. Then, |
| following the <em>session facade</em> pattern, it showed how to create a set of EJB |
| session beans that exist on top of the entity classes and enable convenient access to |
| them. Finally, you modified the <code>AffableBean</code> project to utilize the new |
| session beans and entities for database access required in the index and category pages.</p> |
| |
| <p>You can download |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot4.zip">snapshot |
| 4</a> of the <code>AffableBean</code> project, which corresponds to state the project |
| after completing this unit using NetBeans IDE 6.9.</p> |
| |
| <p>In the next unit you explore session management, and how to enable the application to |
| remember a user's actions as he or she clicks through the site. This is key to implementing |
| a shopping cart mechanism in an e-commerce application.</p> |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Adding Entity Classes and Session Beans">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <br> |
| <h2 id="seeAlsoEntitySession">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Resources</h3> |
| |
| <ul> |
| <li><a href="../../../trails/java-ee.html" target="_blank">Java EE & Java Web Learning Trail</a></li> |
| <li><a href="../javaee-intro.html" target="_blank">Introduction to Java EE Technology</a></li> |
| <li><a href="../javaee-gettingstarted.html" target="_blank">Getting Started with Java EE Applications</a></li> |
| <li><a href="../secure-ejb.html" target="_blank">Building Secure Enterprise Beans in Java EE</a></li> |
| <li><a href="../javaee-entapp-ejb.html" target="_blank">Creating an Enterprise Application with EJB 3.1</a></li> |
| <li><a href="../jpa-eclipselink-screencast.html" target="_blank">Using JPA Support with EclipseLink</a> [screencast]</li> |
| <li><a href="../../../../community/media.html" target="_blank">Video Tutorials and Demos for NetBeans IDE</a></li> |
| <li><a href="http://refcardz.dzone.com/refcardz/netbeans-java-editor-68" target="_blank">NetBeans Java Editor 6.8 Reference Card</a></li> |
| </ul> |
| |
| <h3>EJB Resources</h3> |
| |
| <ul> |
| <li><strong>Product Page:</strong> <a href="http://java.sun.com/products/ejb/" target="_blank">Enterprise JavaBeans Technology</a></li> |
| <li><strong>Specification Download:</strong> <a href="http://jcp.org/aboutJava/communityprocess/final/jsr318/index.html" target="_blank">JSR 318: EJB 3.1 Final Release</a></li> |
| <li><strong>Reference Implementation:</strong> <a href="http://glassfish.dev.java.net/downloads/ri" target="_blank">http://glassfish.dev.java.net/downloads/ri</a></li> |
| <li><strong>Official Forum:</strong> <a href="http://forums.sun.com/forum.jspa?forumID=13" target="_blank">Enterprise Technologies - Enterprise JavaBeans</a></li> |
| <li><strong>Java EE 6 Tutorial:</strong> <a href="http://download.oracle.com/docs/cd/E17410_01/javaee/6/tutorial/doc/bnblr.html" target="_blank">Part IV - Enterprise Beans</a></li> |
| </ul> |
| |
| <h3>JPA Resources</h3> |
| |
| <ul> |
| <li><strong>Product Page:</strong> <a href="http://java.sun.com/javaee/technologies/persistence.jsp" target="_blank">Java Persistence API</a></li> |
| <li><strong>Specification Download:</strong> <a href="http://jcp.org/aboutJava/communityprocess/final/jsr317/index.html" target="_blank">JSR 317: Java Persistence 2.0 Final Release</a></li> |
| <li><strong>Reference Implementation:</strong> <a href="http://www.eclipse.org/eclipselink/downloads/ri.php" target="_blank">http://www.eclipse.org/eclipselink/downloads/ri.php</a></li> |
| <li><strong>Java EE 6 Tutorial:</strong> <a href="http://download.oracle.com/docs/cd/E17410_01/javaee/6/tutorial/doc/bnbpy.html" target="_blank">Part VI - Persistence</a></li> |
| </ul> |
| |
| <h3>GlassFish Resources</h3> |
| |
| <ul> |
| <li><a href="http://glassfish.dev.java.net/docs/index.html" target="_blank">GlassFish v3 Documentation</a></li> |
| <li><a href="http://www.sun.com/offers/details/GlassFish_Tomcat.html" target="_blank">Learning GlassFish for Tomcat Users</a></li> |
| <li><a href="http://glassfish.dev.java.net/javaee5/persistence/persistence-example.html" target="_blank">GlassFish Project - Java Persistence Example</a></li> |
| <li><a href="http://docs.sun.com/app/docs/doc/820-7759" target="_blank">Your First Cup: An Introduction to the Java EE Platform</a></li> |
| <li><a href="http://glassfish.dev.java.net/downloads/ri/" target="_blank">Reference Implementation Downloads</a></li> |
| </ul> |
| |
| <h3>Technical Articles</h3> |
| |
| <ul> |
| <li><a href="http://www.theserverside.com/news/1363656/New-Features-in-EJB-31" target="_blank">New Features in EJB 3.1</a></li> |
| <li><a href="http://www.ibm.com/developerworks/java/library/j-ejb1008.html" target="_blank">EJB Best Practices: Entity Bean Protection</a></li> |
| <li><a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/SessionFacade.html" target="_blank">Core J2EE Patterns - Session Facade</a></li> |
| <li><a href="http://www.ibm.com/developerworks/websphere/library/techarticles/0106_brown/sessionfacades.html" target="_blank">Rules and Patterns for Session Facades</a></li> |
| <li><a href="http://www.oracle.com/technology/sample_code/tech/java/j2ee/designpattern/businesstier/sessionfacade/readme.html" target="_blank">Design Pattern Sample Application - Session Facade</a></li> |
| <li><a href="http://www.ibm.com/developerworks/websphere/library/bestpractices/using_httpservlet_method.html" target="_blank">Best Practice: Using HttpServlet <code>init</code> Method</a></li> |
| </ul> |
| |
| <h3>Books</h3> |
| |
| <ul> |
| <li><a href="http://www.amazon.com/Beginning-Java-EE-GlassFish-Second/dp/143022889X/ref=dp_ob_title_bk" target="_blank">Beginning Java EE 6 with GlassFish 3</a></li> |
| <li><a href="http://www.amazon.com/Java-EE-GlassFish-Application-Server/dp/1849510369/ref=sr_1_1?s=books&ie=UTF8&qid=1281888153&sr=1-1" target="_blank">Java EE 6 with GlassFish 3 Application Server</a></li> |
| <li><a href="http://www.apress.com/book/view/1590598954" target="_blank">Pro NetBeans IDE 6 Rich Client Platform Edition</a></li> |
| <li><a href="http://www.amazon.com/Real-World-Patterns-Rethinking-Practices/dp/0557078326/ref=pd_sim_b_4" target="_blank">Real World Java EE Patterns Rethinking Best Practices</a></li> |
| <li><a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420/ref=sr_1_1?s=books&ie=UTF8&qid=1281985949&sr=1-1" target="_blank">Patterns of Enterprise Application Architecture</a></li> |
| <li><a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/ref=sr_1_1?s=books&ie=UTF8&qid=1281985959&sr=1-1" target="_blank">Domain-Driven Design: Tackling Complexity in the Heart of Software</a></li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2>References</h2> |
| |
| <ol> |
| <li id="footnote1EntitySession"><a href="#1EntitySession" style="text-decoration:none">^</a> Adapted from <a href="http://www.manning.com/panda/" target="_blank">EJB |
| 3 In Action</a> Chapter 1, section 1.1.2: EJB as a framework.</li> |
| |
| <li id="footnote2EntitySession"><a href="#2EntitySession" style="text-decoration:none">^</a> There are many other services |
| provided by EJB. For a more comprehensive list, see <a href="http://www.manning.com/panda/" target="_blank">EJB |
| 3 In Action</a>, Chapter 1, section 1.3.3: Gaining functionality with EJB services.</li> |
| </ol> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="manage-sessions">The NetBeans E-commerce Tutorial - Managing Sessions</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><strong>Managing Sessions</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#session-data">Handling Session Data</a></li> |
| <li><a href="#debug">Examining Session Data with the Java Debugger</a></li> |
| <li><a href="#session-track">Examining Session Tracking Options</a></li> |
| <li><a href="#time-out">Handling Session Time-Outs</a></li> |
| <li><a href="#seeAlsoManageSessions">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>Every e-commerce application that offers some form of shopping cart functionality |
| needs to be able to remember user-specific data as users click through the website. |
| Unfortunately for you the developer, the HTTP protocol, over which communication |
| on the Internet takes place, is a <em>stateless</em> protocol. Each request received |
| by your server is an independent piece of information that has no relation to previously |
| received requests. Therefore, if a customer clicks a button to add an item to his |
| or her shopping cart, your application must take measures to ensure not only that |
| the state of the user's cart is updated, but that the action doesn't affect the |
| cart of another user who happens to be browsing the site at the same time.</p> |
| |
| <p>In order to properly handle the above-described scenario, you need to implement |
| functionality so that a <em>session</em> can be created and maintained for the |
| duration of a user's visit to the site. Servlet technology, which is the foundation |
| of all Java-based web applications, provides for this with its |
| <a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/http/HttpSession.html" target="_blank"><code>HttpSession</code></a> |
| interface. You also need to define several classes, namely <code>ShoppingCart</code> |
| and <code>ShoppingCartItem</code>, that allow the application to temporarily store |
| user data while the session is being maintained.</p> |
| |
| <p>This tutorial unit takes a different approach from others in the NetBeans E-commerce |
| Tutorial. Instead of having you create project files and providing steps with code |
| snippets for you to copy and paste into your own project, you open the completed |
| project snapshot for this unit, and examine the code using the IDE's debugger and |
| other tools. In the process, you'll learn how to apply an <code>HttpSession</code> |
| object to your code so that each visit to the website results in a dedicated session. |
| You also learn about <em>scoped variables</em>, and their usage in both Java classes |
| and JSP pages. This unit also discusses <code>HttpSession</code>'s default mechanism |
| for maintaining sessions (i.e., cookies) and shows what steps need to be taken in |
| the event that cookies are deactivated in a user's browser. Finally, session time-outs |
| are covered, and the unit demonstrates how to handle them by creating a simple filter |
| that intercepts requests to check whether a session exists.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans E-commerce |
| Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left;"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#glassFishManageSessions">GlassFish server</a></td> |
| <td class="tbltd1">v3 or Open Source Edition 3.0.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL database server</a></td> |
| <td class="tbltd1">version 5.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot5.zip">AffableBean |
| project</a></td> |
| <td class="tbltd1">snapshot 5</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><strong class="notes">Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which are |
| required for the application you build in this tutorial.</li> |
| |
| <li id="glassFishManageSessions">The NetBeans IDE Java Bundle also includes the GlassFish server, |
| which you require for this tutorial. You could |
| <a href="http://glassfish.dev.java.net/public/downloadsindex.html" target="_blank">download |
| the GlassFish server independently</a>, but the version provided with the |
| NetBeans download has the added benefit of being automatically registered with |
| the IDE.</li> |
| |
| <li>You can follow this tutorial unit without having completed previous units. To |
| do so, see the <a href="#setup">setup instructions</a>, which describe how |
| to prepare the database and establish connectivity between the IDE, GlassFish, |
| and MySQL.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="session-data">Handling Session Data</h2> |
| |
| <p>Applications can manage user sessions with the <code>HttpSession</code> object. |
| You can bind user-specific data to the <code>HttpSession</code> object, then access |
| this data at a later stage. Both bind and access actions can be done from Java |
| classes, as well as from session-scoped variables in EL expressions.</p> |
| |
| <ul> |
| <li><a href="#httpSession">Working with an HttpSession Object</a></li> |
| <li><a href="#scopedVariables">Working with Scoped Variables in Web Applications</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="httpSession">Working with an HttpSession Object</h3> |
| |
| <p>The <code>AffableBean</code> application uses the <code>HttpSession</code> object |
| to identify users over multiple requests. An <code>HttpSession</code> object is |
| obtained using <code>getSession()</code> on a given request:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| HttpSession session = request.getSession();</pre> |
| |
| <p>If a session object doesn't yet exist for the request, the method creates and returns |
| a new session object.</p> |
| |
| <p>You can use the session object as a vehicle for passing data between requests. You |
| use the <code>setAttribute</code> method to bind objects to the session. Likewise, |
| you use <code>getAttribute</code> to retrieve objects from the session. In the |
| <code>AffableBean</code> application for example, the user's shopping cart is created |
| and bound to the user session in the following manner:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| ShoppingCart cart = new ShoppingCart(); |
| session.setAttribute("cart", cart);</pre> |
| |
| <p>In order to retrieve the cart from the session, the <code>getAttribute</code> method |
| is applied:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| cart = (ShoppingCart) session.getAttribute("cart");</pre> |
| |
| <p>In JSP pages, you can access objects bound to the session using EL expressions. Continuing |
| with the above example, if a <code>ShoppingCart</code> object named '<code>cart</code>' |
| is bound to the session, you can access the object using the following EL expression: |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px">${cart}</pre> |
| |
| <p>Accessing the <code>ShoppingCart</code> object on its own is of little value however. |
| What you really want is a way to access values stored in the object. If you explore |
| the new <code>ShoppingCart</code> class in the project snapshot, you'll note that it |
| contains the following properties:</p> |
| |
| <ul> |
| <li><code>double total</code></li> |
| <li><code>int numberOfItems</code></li> |
| <li><code>List<String, ShoppingCartItem> items</code></li> |
| </ul> |
| |
| <p>Provided that properties have matching getter methods, you can access values for |
| singular properties using simple dot notation in an EL expression. If you examine |
| the <code>cart.jsp</code> page, you'll see that this is exactly how the value for |
| <code>numberOfItems</code> is accessed:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| <p>Your shopping cart contains ${cart.numberOfItems} items.</p></pre> |
| |
| <p>In order to extract data from properties that contain multiple values, such as the |
| above <code>items</code> list, the <code>cart.jsp</code> page uses a <code><c:forEach></code> |
| loop:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| <c:forEach var="cartItem" items="${cart.items}" varStatus="iter"> |
| |
| <c:set var="product" value="${cartItem.product}"/> |
| |
| <tr class="${((iter.index % 2) == 0) ? 'lightBlue' : 'white'}"> |
| <td> |
| <img src="${initParam.productImagePath}${product.name}.png" |
| alt="${product.name}"> |
| </td> |
| |
| <td>${product.name}</td> |
| |
| <td> |
| &euro; ${cartItem.total} |
| <br> |
| <span class="smallText">( &euro; ${product.price} / unit )</span> |
| </td> |
| ... |
| </tr> |
| |
| </c:forEach></pre> |
| |
| <p><code>ShoppingCartItem</code>'s <code>product</code> property identifies the product |
| type for a cart item. The above loop takes advantage of this by first setting a |
| <code>product</code> variable to the expression <code>${cartItem.product}</code>. It |
| then uses the variable to obtain information about that product (e.g., name, price).</p> |
| |
| |
| <h3 id="scopedVariables">Working with Scoped Variables in Web Applications</h3> |
| |
| <p>When working with JSP/Servlet technology, there are four scope objects available to |
| you within the realm of the application. JSP technology implements <em>implicit |
| objects</em> that allows you to access classes defined by the Servlet API.</p> |
| |
| <div class="margin-around"> |
| <table width="688px"> |
| <tr> |
| <th class="tblheader" scope="col">Scope</th> |
| <th class="tblheader" scope="col">Definition</th> |
| <th class="tblheader" scope="col">Servlet Class</th> |
| <th class="tblheader" scope="col">JSP Implicit Object</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><strong>Application</strong></td> |
| <td class="tbltd1">Global memory for a web application</td> |
| <td class="tbltd1"><code><a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/ServletContext.html" target="_blank">javax.servlet.ServletContext</a></code></td> |
| <td class="tbltd1"><code>applicationScope</code></td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><strong>Session</strong></td> |
| <td class="tbltd1">Data specific to a user session</td> |
| <td class="tbltd1"><code><a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/http/HttpSession.html" target="_blank">javax.servlet.http.HttpSession</a></code></td> |
| <td class="tbltd1"><code>sessionScope</code></td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><strong>Request</strong></td> |
| <td class="tbltd1">Data specific to an individual server request</td> |
| <td class="tbltd1"><code><a href="http://java.sun.com/javaee/6/docs/api/javax/servlet/http/HttpServletRequest.html" target="_blank">javax.servlet.HttpServletRequest</a></code></td> |
| <td class="tbltd1"><code>requestScope</code></td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><strong>Page</strong></td> |
| <td class="tbltd1">Data that is only valid in the context of a single page (JSPs only)</td> |
| <td class="tbltd1"><code>[n/a]</code></td> |
| <td class="tbltd1"><code>pageScope</code></td> |
| </tr> |
| </table> |
| </div> |
| |
| <p>If you open your project's <code>category.jsp</code> file in the editor, you'll see |
| that EL expressions include various scoped variables, including <code>${categories}</code>, |
| <code>${selectedCategory}</code> and <code>${categoryProducts}</code>. The <code>${categories}</code> |
| variable is application-scoped, which is set in the <code>ControllerServlet</code>'s |
| <code>init</code> method:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| // store category list in servlet context |
| getServletContext().setAttribute("categories", categoryFacade.findAll());</pre> |
| |
| <p>The other two, <code>${selectedCategory}</code> and <code>${categoryProducts}</code>, |
| are placed in the application's session scope from the <code>ControllerServlet</code>. |
| For example:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| // place selected category in session scope |
| session.setAttribute("selectedCategory", selectedCategory);</pre> |
| |
| <p class="notes"><strong>Note:</strong> If you are continuing from the previous tutorial |
| units, you'll likely note that <code>${selectedCategory}</code> and <code>${categoryProducts}</code> |
| were originally placed in the request scope. In previous units this was fine, but |
| consider now what happens if a user clicks the 'add to cart' button in a category page. |
| The server responds to an <code>addToCart</code> request by returning the currently |
| viewed category page. It therefore needs to know the <code>selectedCategory</code> and |
| the <code>categoryProducts</code> pertaining to the selected category. Rather than |
| establishing this information for each request, you place it in the session scope from |
| a <code>category</code> request so that it is maintained across multiple requests, and |
| can be accessed when you need it. Also, examine the functionality provided by the cart |
| page. (A functional description is <a href="#cartPage">provided below</a>.) The 'continue |
| shopping' button returns the user to the previously viewed category. Again, the |
| <code>selectedCategory</code> and the <code>categoryProducts</code> variables are required.</p> |
| |
| <p>When referencing scoped variables in an EL expression, you do not need to specify the |
| variable's scope (provided that you do not have two variables of the same name in |
| different scopes). The JSP engine checks all four scopes and returns the first |
| variable match it finds. In <code>category.jsp</code> for example, the expression:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| ${categoryProducts}</pre> |
| |
| <p>is shorthand for:</p> |
| |
| <pre class="examplecode" style="width:664px; margin-left:10px; margin-top:-2px"> |
| ${sessionScope.categoryProducts}</pre> |
| |
| <span class="tips">For more information, see the following resources:</span> |
| |
| <ul style="margin: 5px 0 0 1em"> |
| <li><a href="http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/web-tier/web-tier5.html#1079198" target="_blank">Designing |
| Enterprise Applications with the J2EE Platform: State Scopes</a></li> |
| <li><a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/tutorial/doc/bnafo.html" target="_blank">Sharing Information > Using Scoped Objects</a></li> |
| <li><a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/tutorial/doc/bnahq.html#bnaij" target="_blank">Unified Expression Language > Implicit Objects</a></li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2 id="debug">Examining Session Data with the Java Debugger</h2> |
| |
| <p>Begin exploring how the application behaves during runtime. Use the IDE's debugger to |
| step through code and examine how the <code>HttpSession</code> is created, and how other |
| objects can be placed in the session scope to be retrieved at a later point.</p> |
| |
| <ol> |
| <li>Open the <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot5.zip">project |
| snapshot</a> for this tutorial unit in the IDE. Click the Open Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/open-project-btn.png" |
| alt="Open Project button"> ) button and use the wizard to navigate to the location |
| on your computer where you downloaded the project. If you are proceeding from the |
| <a href="#entity-session">previous tutorial unit</a>, note that this project |
| snapshot includes a new <code>cart</code> package, containing <code>ShoppingCart</code> |
| and <code>ShoppingCartItem</code> classes. |
| |
| Also, the following files have been modified: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><code>WEB-INF/web.xml</code></li> |
| <li><code>css/affablebean.css</code></li> |
| <li><code>WEB-INF/jspf/header.jspf</code></li> |
| <li><code>WEB-INF/jspf/footer.jspf</code></li> |
| <li><code>WEB-INF/view/cart.jsp</code></li> |
| <li><code>WEB-INF/view/category.jsp</code></li> |
| <li><code>WEB-INF/view/checkout.jsp</code></li> |
| <li><code>controller/ControllerServlet</code></li> |
| </ul></li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) to ensure that it is properly configured with your database and |
| application server. |
| |
| <br><br> |
| <p class="alert">If you receive an error when running the project, revisit the |
| <a href="#setup">setup instructions</a>, which describe how to prepare the |
| database and establish connectivity between the IDE, GlassFish, and MySQL.</p></li> |
| |
| <li>Test the application's functionality in your browser. If you are continuing directly from |
| the <a href="#entity-session">previous tutorial unit</a>, you'll note the following |
| enhancements. |
| |
| <h4>category page</h4> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>Clicking 'add to cart' for the first time enables the shopping cart and 'proceed to |
| checkout' widgets to display in the header.</li> |
| <li>Clicking 'add to cart' results in an update to the number of cart items in the header's |
| shopping cart widget.</li> |
| <li>Clicking 'view cart' results in the cart page displaying.</li> |
| <li>Clicking 'proceed to checkout' results in the checkout page displaying.</li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/category-page.png" |
| class="margin-around b-all" alt="Browser image of category page" style="width:688px" |
| title="Category page includes shopping cart functionality"> |
| |
| <h4 id="cartPage">cart page</h4> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>Clicking 'clear cart' results in shopping cart being emptied of items.</li> |
| <li>Clicking 'continue shopping' results in a return to the previously viewed category.</li> |
| <li>Clicking 'proceed to checkout' results in the checkout page displaying.</li> |
| <li>Entering a number (1 - 99) in an item's quantity field then clicking 'update' |
| results in a recalculation of the total price for the item, and of the subtotal.</li> |
| <li>Entering zero in an item's quantity field then clicking 'update' results in |
| the item being removed from the displayed table.</li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/cart-page.png" |
| class="margin-around b-all" alt="Browser image of cart page" style="width:688px" |
| title="Cart page includes shopping cart functionality"> |
| |
| <h4>checkout page</h4> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>Clicking 'view cart' results in the cart page displaying.</li> |
| <li>Clicking 'submit purchase' results in the confirmation page displaying (without |
| user-specific data).</li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/checkout-page.png" |
| class="margin-around b-all" alt="Browser image of checkout page" style="width:688px" |
| title="Checkout page includes shopping cart functionality"></li> |
| |
| <li>Use the Go to File dialog to open the <code>ControllerServlet</code> in the editor. Press |
| Alt-Shift-O (Ctrl-Shift-O on Mac), then type '<code>Controller</code>' in the dialog and |
| click OK. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/connect-db/go-to-file-dialog.png" |
| class="margin-around b-all" alt="Go to File dialog" |
| title="Use the Go to File dialog to quickly open project resources in the editor"></li> |
| |
| <li>Set a breakpoint in the <code>doPost</code> method on the line that creates an <code>HttpSession</code> |
| object (line 150). To set a breakpoint, click in the left margin of the editor. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/breakpoint.png" |
| class="margin-around b-all" alt="Breakpoint set in editor" |
| title="Click in editor's left margin to set breakpoints"> |
| |
| <p class="tips">To toggle line numbers for the editor, right-click in the left margin and |
| choose Show Line Numbers.</p></li> |
| |
| <li>Run the debugger. Click the Debug Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/debug-project-btn.png" |
| alt="Debug Project button"> ) button in the IDE's main toolbar. The GlassFish server starts |
| (or restarts, if it is already running) and opens a socket on its debug port number. The |
| application welcome page opens in your browser. |
| |
| <br><br> |
| <p class="tips">You can view and modify the debug port number from the Servers window (Tools |
| > Servers). Select the Java tab for the server you are using. Specify the port number |
| in the 'Address to use' field under Debug Settings.</p></li> |
| |
| <li>When the application's welcome page displays in the browser, click any category image to navigate |
| to the category page. Recall that clicking the 'add to cart' button sends an <code>addToCart</code> |
| request to the server: |
| |
| <pre class="examplecode"><form action="addToCart" method="post"></pre> |
| |
| As you may recall from <a href="page-views-controller.html#controller">Preparing the Page Views |
| and Controller Servlet</a>, the <code>ControllerServlet</code>'s <code>doPost</code> method handles |
| requests for the <code>/addToCart</code> URL pattern. You can therefore expect that when a user |
| clicks an 'add to cart' button, the <code>doPost</code> method is called.</li> |
| |
| <li>Click 'add to cart' for any product in the category page. Switch back to the IDE and note that |
| the debugger suspends on the breakpoint. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/breakpoint-suspended.png" |
| class="margin-around b-all" alt="Debugger suspended on breakpoint in editor" |
| title="Debugger suspends on breakpoints in editor"></li> |
| |
| <li>Place your cursor on the call to <code>getSession()</code> and press Ctrl-Space to invoke the |
| Javadoc documentation. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/javadoc-getsession.png" |
| class="margin-around b-all" alt="Javadoc documentation displayed in editor" style="width:688px" |
| title="Press Ctrl-Space to invoke Javadoc documentation"> |
| |
| <br> |
| According to the documentation, <code>getSession()</code> returns the <code>HttpSession</code> |
| currently associated with the request, and if no session exists, the method creates a new session |
| object. |
| |
| <br><br> |
| <div class="feedback-box float-left" style="width: 683px;"> |
| |
| <h3>Taking Advantage of the IDE's Javadoc Support</h3> |
| |
| <p>The IDE provides built-in Javadoc support for Java EE development. The IDE |
| bundles with the Java EE 6 API Specification, which you can open in an |
| external browser by choosing Help > Javadoc References > Java EE 6.</p> |
| |
| <p>The IDE also includes various other features that enable easy access to API |
| documentation:</p> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><strong>Javadoc window:</strong> Choose Window > Other > Javadoc. |
| The Javadoc window opens in the bottom region of the IDE, and displays |
| API documentation relevant to your cursor's location in the editor.</li> |
| |
| <li><strong>Javadoc Index Search:</strong> Choose Help > Javadoc Index |
| Search (Shift-F1; fn-Shift-F1 on Mac). Type in the name of the class |
| you are looking for, then select a class from the listed results. The |
| complete class description from the API Specification displays in the |
| bottom pane of the window.</li> |
| |
| <li><strong>Documentation popup in the editor:</strong> Javadoc documentation |
| displays in a popup window when you press Ctrl-Space on a given element |
| in the editor. You can click the External Browser ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/external-browser-btn.png" |
| alt="External Browser button"> ) button to have the documentation open |
| in your browser. |
| |
| If you want to use Ctrl-Space for code completion only, you can deactivate |
| the documentation popup by opening the Options window (Tools > Options; |
| NetBeans > Preferences on Mac), then selecting Editor > Code Completion. |
| Deselect the 'Auto Popup Documentation Window' option.</li> |
| </ul> |
| |
| <p>When you document your own work, consider adding Javadoc comments to your |
| classes and methods. Open the <code>ShoppingCart</code> class and examine |
| the Javadoc comments added to the class methods. Javadoc comments are marked |
| by the <code>/** ... */</code> delimiters. For example, the <code>addItem</code> |
| method has the following comment before its signature:</p> |
| |
| <div class="margin-around"> |
| <pre class="examplecode" style="width:643px"> |
| /** |
| * Adds a <code>ShoppingCartItem</code> to the <code>ShoppingCart</code>'s |
| * <code>items</code> list. If item of the specified <code>product</code> |
| * already exists in shopping cart list, the quantity of that item is |
| * incremented. |
| * |
| * @param product the <code>Product</code> that defines the type of shopping cart item |
| * @see ShoppingCartItem |
| */ |
| public synchronized void addItem(Product product) {</pre> |
| </div> |
| |
| <p>This enables you (and others working on the project) to view Javadoc documentation |
| on the method. To demonstrate, open the Navigator (Ctrl-7; ⌘-7 on Mac) and |
| hover your mouse over the <code>addItem</code> method.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/javadoc-additem.png" |
| title="Hover over methods in Navigator to view Javadoc documentation" |
| alt="Javadoc popup" class="margin-around b-all"> |
| |
| <p>You can also use the IDE to generate a set of Javadoc HTML pages. In the Projects |
| window, right-click your project node and choose Generate Javadoc. The IDE generates |
| the Javadoc in the <code>dist/javadoc</code> folder of your project's directory |
| and opens the index page in the browser.</p> |
| |
| <br> |
| <p>For more information on Javadoc, see the following resources:</p> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><a href="http://java.sun.com/j2se/javadoc/" target="_blank">Javadoc Tool Official Home Page</a></li> |
| <li><a href="http://java.sun.com/j2se/javadoc/writingdoccomments/index.html" target="_blank">How |
| to Write Doc Comments for the Javadoc Tool</a></li> |
| </ul> |
| </div> |
| |
| <div style="clear:left"></div> |
| </li> |
| |
| <li>Hover your mouse over the <code>session</code> variable. Note that the debugger suspends |
| on the line <em>it is about to execute.</em> The value returned by <code>getSession()</code> |
| has not yet been saved into the <code>session</code> variable, and you see a popup stating |
| that "<code>session</code> is not a known variable in the current context." |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-variable.png" |
| class="margin-around b-all" alt="Debugger popup displayed in editor" |
| title="Hover your mouse over variables and expressions to determine their current values"></li> |
| |
| <li>Click the Step Over ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-btn.png" |
| alt="Step Over button"> ) button in the debugger toolbar located above the editor. The line is |
| executed, and the debugger steps to the next line in the file.</li> |
| |
| <li>Hover your mouse over the <code>session</code> variable again. Now you see the value currently |
| set to the <code>session</code> variable. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-variable-set.png" |
| rel="lytebox" title="Hover your mouse over variables and expressions to determine their current values"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-variable-set.png" |
| class="margin-around b-all" alt="Debugger popup displayed in editor" width="688px" |
| title="Click to enlarge"></a> |
| |
| <p class="tips">In NetBeans 6.9, you can click the grey pointer ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/grey-pointer.png" |
| alt="Step Over button"> ) in the popup to expand a list of variable values contained in the |
| highlighted element.</p></li> |
| |
| <li>Click the Step Over ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-btn.png" |
| alt="Step Over button"> ) button (F8; fn-F8 on Mac) to arrive at the <code>if</code> statement (line |
| 154). Because you just clicked the 'add to cart' button in the browser, you know that the expression |
| <code>userPath.equals("/addToCart")</code> should evaluate to <code>true</code>.</li> |
| |
| <li>Highlight the <code>userPath.equals("/addToCart")</code> expression (by control-clicking |
| with your mouse). This time you see a popup indicating the value of the expression you highlighted. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/expression.png" |
| class="margin-around b-all" alt="Evaluated expression displayed in popup" |
| title="Highlight expressions to determine their current values"></li> |
| |
| <li>Press F8 (fn-F8 on Mac) to step to the next line (line 158). The application has been designed |
| so that the <code>ShoppingCart</code> object for the user session is only created when the user |
| adds an item to the cart for the first time. Since this is the first time the <code>addToCart</code> |
| request has been received in this debug session, you can expect the <code>cart</code> object to |
| equal <code>null</code>. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/cart-null.png" |
| class="margin-around b-all" alt="Evaluated expression displayed in popup" |
| title="Cart object doesn't exist until user adds item to shopping cart"></li> |
| |
| <li>Press F8 (fn-F8 on Mac) to step to the next line (line 160). Then, on line 160, where the |
| <code>ShoppingCart</code> object is created, click the Step Into ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-into-btn.png" |
| alt="Step Into button"> ) button. The debugger steps into the method being called. In this |
| case, you are taken directly to the <code>ShoppingCart</code>'s constructor. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/cart-constructor.png" |
| class="margin-around b-all" alt="Evaluated expression displayed in popup" |
| title="Step into methods to follow runtime execution to other classes"></li> |
| |
| <li>Press Ctrl-Tab to switch back to the <code>ControllerServlet</code>. Note that the IDE |
| provides a Call Stack ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/call-stack-badge.png" |
| alt="Call Stack badge"> ) badge on line 160, indicating that the debugger is currently suspended |
| somewhere on a method higher up in the call stack. |
| |
| <br><br> |
| <p class="tips">Press Alt-Shift-3 (Ctrl-Shift-3 on Mac) to open the IDE's Call Stack window.</p></li> |
| |
| <li>Press F8 (fn-F8 on Mac) to continue stepping through code. When the debugger completes the |
| <code>ShoppingCart</code> constructor, you are taken back to the <code>ControllerServlet</code>. |
| |
| <br><br> |
| Line 161 of the <code>ControllerServlet</code> binds the newly-created <code>cart</code> object |
| to the session. |
| |
| <pre class="examplecode">session.setAttribute("cart", cart);</pre> |
| |
| To witness this, open the debugger's Variables window. Choose Window > Debugging > Variables, |
| or press Alt-Shift-1 (Ctrl-Shift-1 on Mac). |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-win-session.png" |
| rel="lytebox" title="Open the debugger's Variables window to inspect variable values as you step through code"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-win-session.png" |
| class="margin-around b-all" alt="Variables window" width="688px" |
| title="Click to enlarge"></a> |
| |
| <br> |
| If you expand the session > session > attributes node, you are able to view the |
| objects that are bound to the session. In the above image, there are two items currently |
| bound to the session (highlighted). These are <code>selectedCategory</code> and |
| <code>categoryProducts</code>, instantiated in the <code>ControllerServlet</code> at lines |
| 83 and 89, respectively. Both of these items were bound earlier, when you clicked a category |
| image, and the <code>ControllerServlet</code> processed the category page request.</li> |
| |
| <li>Press F8 (fn-F8 on Mac) to execute line 161. The <code>cart</code> object is bound to the |
| session, and the Variables window updates to reflect changes. In the Variables window, note |
| that the session now contains three attributes, the third being the newly initialized |
| <code>ShoppingCart</code> object (highlighted below). |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-win-session-cart.png" |
| rel="lytebox" title="ShoppingCart object is bound to session with the setAttribute method"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-win-session-cart.png" |
| class="margin-around b-all" alt="Variables window" width="688px" |
| title="Click to enlarge"></a> |
| |
| <br> |
| <p class="tips">So far, we have not "proven" that the session, as listed in |
| the Variables window, represents an <code>HttpSession</code>. As previously mentioned, |
| <code>HttpSession</code> is actually an interface, so when we talk about an <code>HttpSession</code> |
| object, or session object, we are in fact referring to any object that implements the |
| <code>HttpSession</code> interface. In the Variables window, if you hover your cursor |
| over '<code>session</code>', a popup displays indicating that the variable represents |
| an <code>HttpSession</code> object. The <code>StandardSessionFacade</code> type, as |
| displayed, is the internal class that GlassFish uses to implement the <code>HttpSession</code> |
| interface. If you are familiar with Tomcat and are puzzled by the |
| '<code>org.apache.catalina</code>' paths that appear in the Value column, this is |
| because the GlassFish web/servlet container is in fact a derivative of the Apache Tomcat |
| container.</p> |
| |
| A new <code>ShoppingCart</code> is added to the session, and the request continues |
| to be processed. In order to complete implementation of the 'add to cart' functionality, |
| the following actions are taken: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>the ID of the selected product is retrieved from the request (line 165)</li> |
| <li>a <code>Product</code> object is created using the ID (line 169)</li> |
| <li>a new <code>ShoppingCartItem</code> is created using the <code>product</code> (line 170)</li> |
| <li>the <code>ShoppingCartItem</code> is added to <code>ShoppingCart</code>'s <code>items</code> list (line 170)</li> |
| </ul></li> |
| |
| <li>Press F8 (fn-F8 on Mac) to continue stepping through code while being mindful of the above-listed |
| four actions. Pause when the debugger suspends on line 170.</li> |
| |
| <li id="step21">Create a watch on the session. This will allow you to view values contained |
| in the session when you step into the <code>addItem</code> method in the next step. |
| Right-click the session in the Variables window and choose Create Fixed Watch. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/create-watch.png" |
| class="margin-around b-all" alt="Right-click menu displayed in Variables window" |
| title="Create watches on variables as you step through code in a debug session"> |
| |
| <p class="tips">Alternatively, you can place your cursor on the <code>session</code> variable |
| in the editor, then right-click and choose New Watch. The New Watch dialog enables you to |
| specify variables or expressions to watch continuously when debugging an application. (In |
| the case of expressions, highlight the expression first, then right-click and choose New |
| Watch.) |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/new-watch-dialog.png" |
| class="margin-around b-all" alt="New Watch dialog" |
| title="Right-click variables and expressions in the editor and choose New Watch"></p> |
| |
| A new watch is created on the <code>session</code> variable and all variables it contains. |
| The watch is visible from the Watches window (Window > Debugging > Watches) or, if |
| you toggle the Watches ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/watch-btn.png" |
| alt="Watches button"> ) button in the left margin of the Variables window, it displays in |
| the top row of the Variables window. |
| |
| <br><br> |
| The debugger enables you to keep an eye on variables as it steps through code. This can |
| be helpful, for example if you'd like to follow changes to specific variable values (and |
| don't want to need to sift through the full list presented in the Variables window with |
| each step), or if you temporarily step into a class that doesn't contain the variables |
| you are interested in.</li> |
| |
| <li>Click the Step Into ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-into-btn.png" |
| alt="Step Into button"> ) button to step into <code>ShoppingCart</code>'s <code>addItem</code> |
| method.</li> |
| |
| <li>Step through the <code>addItem</code> method until you reach line 53. As the Javadoc states, |
| <code>addItem</code> <em>"adds a <code>ShoppingCartItem</code> to the <code>ShoppingCart</code>'s |
| <code>items</code> list. If item of the specified <code>product</code> already exists in |
| shopping cart list, the quantity of that item is incremented."</em></li> |
| |
| <li>Examine the <code>session</code> variable which you created a watch on (<a href="#step21">step |
| 21</a> above). The <code>items.add(scItem)</code> statement in line 51 added the new |
| <code>ShoppingCartItem</code> to the <code>items</code> list in the <code>ShoppingCart</code>. |
| This is evident by drilling into the third attribute (i.e., the <code>cart</code> variable) |
| contained in the session. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-window-add-item.png" |
| rel="lytebox" title="Session displays the new ShoppingCartItem as listed in the ShoppingCart's 'items' list"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-window-add-item.png" |
| class="margin-around b-all" alt="Variables window" width="688px" |
| title="Click to enlarge"></a> |
| |
| <br> |
| At this stage, you can see how an <code>HttpSession</code> is created for the request, |
| how a <code>ShoppingCart</code> object is created and attached to the session, and how |
| a <code>ShoppingCartItem</code> is created based on the user's product choice, then added |
| to the <code>ShoppingCart</code>'s list of <code>items</code>. The only remaining action |
| is to forward the request to the <code>category.jsp</code> view.</li> |
| |
| <li>Open the header JSP fragment (<code>header.jspf</code>) in the editor and place a |
| breakpoint on line 86. This line contains the EL statement within the shopping cart |
| widget that displays the number of cart items. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/breakpoint-jsp.png" |
| class="margin-around b-all" alt="Breakpoint set in JSP page" width="688px" |
| title="You can suspend the debugger in JSP pages"></li> |
| |
| <li>Click the Continue ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/continue-btn.png" |
| alt="Continue button"> ) button in the debugger toolbar. The debugger continues until |
| execution completes, or until it reaches another breakpoint. In this case, the debugger |
| suspends on line 86 in the header JSP fragment. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> In order to suspend the debugger in a JSP page, |
| you need to set a breakpoint. For example, when the <code>ControllerServlet</code> |
| forwards the request to the appropriate view, the debugger will not automatically |
| suspend within the JSP page.</p></li> |
| |
| <li>Open the Variables window (Alt-Shift-1; Ctrl-Shift-1 on Mac) if it is not already open. |
| Unlike with Java classes, the debugger <em>does not</em> provide tooltips when you hover |
| your mouse over variables or expressions in a JSP page. However, the Variables window does |
| enable you to determine variable values as you step through code. So, where can you find |
| the value for <code>${cart.numberOfItems}</code>?</li> |
| |
| <li>In the Variables window, expand the Implicit Objects > pageContext > session > |
| session > attributes node. This provides access to the session object, just as you |
| saw earlier when working in the <code>ControllerServlet</code>. In fact, you may note |
| that the session which you created a watch on in step 21 above points to the very same |
| object. Here you can verify that the value of <code>${cart.numberOfItems}</code> equals |
| '<code>1</code>'. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-window-number-of-items.png" |
| rel="lytebox" title="In JSP pages, view session attributes within the pageContext implicit object"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/variables-window-number-of-items.png" |
| class="margin-around b-all" alt="Variables window" width="688px" |
| title="Click to enlarge"></a> |
| |
| <p class="tips">Maximize the Variables window, or any window in the IDE, by right-clicking |
| the window header, then choosing Maximize Window (Shift-Esc).</p> |
| |
| The debugger gives you access to the <code>pageContext</code> implicit object. |
| <code>pageContext</code> represents the context of the JSP page, and offers direct |
| access to various objects including the <code>HttpServletRequest</code>, |
| <code>HttpSession</code>, and <code>ServletContext</code> objects. For more information, |
| see the <a href="http://java.sun.com/javaee/5/docs/tutorial/doc/bnahq.html#bnaij" target="_blank">Java |
| EE 5 Tutorial: Implicit Objects</a>.</li> |
| |
| <li>Click the Finish Session ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/finish-session-btn.png" |
| alt="Finish Session button"> ) button. The runtime finishes executing, and the debug |
| session terminates. The browser displays a fully-rendered category page, and you can |
| see that the shopping cart widget in the page header contains one item.</li> |
| </ol> |
| |
| <p>Hopefully you now feel comfortable using the IDE's debugger not only to examine your project |
| when it behaves unexpectedly, but also as a tool to become more familiar with code. |
| Other useful buttons in the debugger toolbar include:</p> |
| |
| <ul> |
| <li>( <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-out.png" |
| alt="Step Out button"> ) <strong>Step Out:</strong> Steps you out of the current method call. |
| Executes and removes the topmost method call in your call stack.</li> |
| |
| <li>( <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/run-to-cursor.png" |
| alt="Run to Cursor button"> ) <strong>Run to Cursor:</strong> Executes up to the line on |
| which your cursor is placed.</li> |
| |
| <li>( <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/apply-code-changes.png" |
| alt="Apply Code Changes button"> ) <strong>Apply Code Changes:</strong> After editing a |
| file, you can press this button so that the file is recompiled and changes are taken into |
| account in the debug session.</li> |
| |
| <li>( <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-expression.png" |
| alt="Step Over Expression button"> ) <strong>Step Over Expression:</strong> Enables you |
| to view the input parameters and resulting output values of each method call within an |
| expression. You can inspect the output values for the previous method and the input |
| parameters for the next method in the Local Variables window. When there are no further |
| method calls, Step Over Expression behaves like the Step Over ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-btn.png" |
| alt="Step Over button"> ) command.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="session-track">Examining Session Tracking Options</h2> |
| |
| <p>There are three conventional ways of tracking sessions between client and server. By |
| far the most common is with cookies. URL rewriting can be applied in the event that |
| cookies are not supported or disabled. Hidden form fields can also be used as a means |
| of "maintaining state" over multiple requests, but these are limited to |
| usage within forms.</p> |
| |
| <p>The <code>AffableBean</code> project includes an example of the hidden field method |
| in both the category and cart pages. The 'add to cart' and 'update' buttons that display |
| for product items contain a hidden field which relays the product ID to the server |
| when the button is clicked. If you open the <code>cart.jsp</code> page in the editor, |
| you'll see that the <code><form></code> tags contain a hidden field.</p> |
| |
| <pre class="examplecode" style="width:730px; margin-left:10px; margin-top:-2px"> |
| <form action="updateCart" method="post"> |
| <strong><input type="hidden" |
| name="productId" |
| value="${product.id}"></strong> |
| ... |
| </form></pre> |
| |
| <p>In this manner, the product ID is sent as a request parameter which the server uses |
| to identify the item within the user's cart whose quantity needs to be modified.</p> |
| |
| <p>The Servlet API provides a high-level mechanism for managing sessions. Essentially, |
| it creates and passes a cookie between the client and server with each request-response |
| cycle. If the client browser doesn't accept cookies, the servlet engine automatically |
| reverts to URL rewriting. The following two exercises demonstrate this functionality.</p> |
| |
| <ul> |
| <li><a href="#http-monitor">Examining Client-Server Communication with the HTTP Monitor</a></li> |
| <li><a href="#url-rewrite">Maintaining Sessions with URL Rewriting</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="http-monitor">Examining Client-Server Communication with the HTTP Monitor</h3> |
| |
| <p>By default, the servlet engine uses cookies to maintain and identify sessions between |
| requests. A random, alphanumeric number is generated for each session object, which |
| serves as a unique identifier. This identifier is passed as a '<code>JSESSIONID</code>' |
| cookie to the client. When the client makes a request, the servlet engine reads the |
| value of the <code>JSESSIONID</code> cookie to determine the session which the request |
| belongs to.</p> |
| |
| <p>To demonstrate this, we'll use the debugger in tandem with the IDE's HTTP Monitor.</p> |
| |
| <ol> |
| <li>Begin by activating the HTTP Monitor for the server you are using. Choose Tools |
| > Servers. In the left column of the Servers window, select the server you are |
| using (GlassFish). Then, in the main column, select the Enable HTTP Monitor option. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/servers-win-http-monitor.png" |
| class="margin-around b-all" alt="Servers window" width="688px" |
| title="Select the Enable HTTP Monitor option to activate the HTTP Monitor"></li> |
| |
| <li>If your server is already running, you need to restart it. However, since we plan |
| to use the debugger, and running the debugger restarts the server to communicate |
| on a different port, just click the Debug Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/debug-project-btn.png" |
| alt="Debug Project button"> ) button in the IDE's main toolbar. The server restarts, |
| a debug session begins and the application's welcome page opens in your browser. The |
| HTTP Monitor displays in the bottom region of the IDE. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/http-monitor.png" |
| class="margin-around b-all" alt="HTTP Monitor" width="688px" |
| title="HTTP Monitor displays by default in bottom region of the IDE"></li> |
| |
| <li>Click the AffableBean record in the left column (as shown in the above image). When |
| you select records in the left column, the right (i.e., main) column refreshes to |
| display corresponding data. In the above image, the Request tab displays the requested |
| URI (<code>/AffableBean/</code>), the HTTP method (<code>GET</code>), and points out |
| that there was no query string sent with the request.</li> |
| |
| <li>Select the Session tab. Note that there is a statement, "The session was created |
| as a result of this request." This is due to the fact that the server has sent a |
| <code>Set-Cookie</code> header for the <code>JSESSIONID</code> cookie in its response. |
| Also note that the new session ID is listed under 'Session properties'. As will later |
| be shown, the session ID is the value of the <code>JSESSIONID</code> cookie. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-tab.png" |
| class="margin-around b-all" alt="HTTP Monitor - Session tab" |
| title="Session details are displayed under the Session tab in the HTTP Monitor"> |
| |
| <br> |
| You may wonder how a session object was created from a request for the site welcome page. |
| After all, the <code>ControllerServlet</code> does not handle the initial request for |
| <code>/AffableBean/</code>, and nowhere does this request encounter <code>getSession()</code>. |
| Or does it? Recall that JSP pages are compiled into servlets upon deployment. Once you've |
| deployed your project to the server, you can actually use the IDE to view the JSP's compiled |
| servlet on your server.</li> |
| |
| <li>In the Projects window, right-click the <code>index.jsp</code> file and choose View Servlet. |
| An <code>index_jsp.java</code> file opens in the editor. This is the servlet that was automatically |
| compiled from the <code>index.jsp</code> page.</li> |
| |
| <li>Perform a search in the file for <code>getSession</code>. Press Ctrl-F (⌘-F on Mac), |
| type '<code>getSession</code>' in the search bar, then press Enter. |
| |
| <br><br> |
| <p class="tips"> Ctrl-F (⌘-F on Mac) is a keyboard shortcut for Edit > Find.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/get-session.png" |
| class="margin-around b-all" alt="Editor displaying getSession method" |
| title="The getSession method exists in the JSP page's compiled servlet"> |
| |
| <br> |
| The <code>getSession</code> method is in fact called. The reason this occurs is because |
| JSP pages include the <code>pageContext.session</code> implicit object by default. If you |
| wanted to deactivate this behavior, you could add the following directive to the top of |
| a JSP file: |
| |
| <pre class="examplecode"><%@page session="false" %></pre> |
| |
| and the <code>getSession</code> method in the compiled servlet would be removed. |
| |
| <br><br> |
| <p class="tips">To find out the location of the compiled servlet on your server, |
| you can hover your mouse over the servlet's name tab above the editor. A popup |
| displays the path to the file on your computer.</p></li> |
| |
| <li>In the browser, select a category then add an item to your cart. Switch back to the |
| IDE. Note that the debugger suspends on the breakpoint in the <code>ControllerServlet</code> |
| you set earlier (line 150). All breakpoints are remembered between sessions. To remove |
| the breakpoint, you could click the breakpoint ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/breakpoint-badge.png" |
| alt="Breakpoint badge"> ) badge in the editor's left margin. However, since there are |
| multiple breakpoints already set in the project, open the debugger's Breakpoints |
| window (Window > Debugging > Breakpoints). |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/breakpoints-window.png" |
| class="margin-around b-all" alt="Breakpoints window" |
| title="View all breakpoints in your project from the Breakpoints window"> |
| |
| <br> |
| From the Breakpoints window, you can view and call actions on all breakpoints |
| set in projects opened in the IDE.</li> |
| |
| <li>Right-click the breakpoint set in <code>header.jspf</code> and choose Delete. |
| Then right-click the breakpoint set in the <code>ControllerServlet</code> and |
| choose Disable. (You'll re-enable it later in this exercise.)</li> |
| |
| <li>Click the Continue ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/continue-btn.png" |
| alt="Continue button"> ) button. The request finishes executing, and the category |
| page displays in the browser with one item added to the cart.</li> |
| |
| <li>In the HTTP Monitor, search for the <code>addToCart</code> request in the left |
| column, then select it to display details in the main column. |
| |
| <br><br> |
| <p class="tips">Click the Ascending Sort ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/ascending-sort-btn.png" |
| alt="Ascending Sort button"> ) button so that the most recent records are listed |
| at the top.</p> |
| |
| <br> |
| Under the Request tab, note the requested URI (<code>/AffableBean/addToCart</code>), |
| the HTTP method (<code>POST</code>), and the request parameters (<code>productId</code> |
| and <code>submit</code>). |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/http-monitor-add-to-cart.png" |
| rel="lytebox" title="View request data, including request parameters, under the HTTP Monitor's Request tab"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/http-monitor-add-to-cart.png" |
| class="margin-around b-all" style="width:688px" alt="HTTP Monitor - Request tab" |
| title="Click to enlarge"></a></li> |
| |
| <li>Select the Cookies tab. Here you see that a cookie named <code>JSESSIONID</code> exists, |
| and was sent from the client to the server. Note that the value for the cookie is the |
| same as the Session ID displayed under the Session tab. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/cookies-tab.png" |
| class="margin-around b-all" alt="HTTP Monitor - Cookies tab" |
| title="Cookies are displayed under the Cookies tab in the HTTP Monitor"> |
| |
| <br> |
| Likewise, if you click the Header tab, you see the cookie listed, since '<code>Cookie</code>' |
| is a request header that was sent by the client. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/headers-tab.png" |
| class="margin-around b-all" alt="HTTP Monitor - Cookies tab" |
| title="Cookies are displayed under the Cookies tab in the HTTP Monitor"> |
| |
| <p class="tips">See Wikipedia's <a href="http://en.wikipedia.org/wiki/List_of_HTTP_headers" target="_blank">List |
| of HTTP headers</a> for more information on request and response headers.</p></li> |
| |
| <li>Select the Session tab. There is a statement which indicates, "The session existed |
| before this request." Also note that the <code>cart</code> attribute is listed under |
| 'Session attributes after the request'. This makes sense, since we know that the |
| <code>cart</code> object is bound to the session when the <code>addToCart</code> request |
| is processed for the first time. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-tab-add-to-cart.png" |
| class="margin-around b-all" alt="HTTP Monitor - Session tab" |
| title="Session attributes are displayed under the Session tab in the HTTP Monitor"> |
| |
| <br><br> |
| In the next few steps, locate the session ID and <code>JSESSIONID</code> cookie in the |
| Variables window.</li> |
| |
| <li>Re-enable the breakpoint you set earlier in the <code>ControllerServlet</code>. Press |
| Alt-Shift-5 (Ctrl-Shift-5 on Mac) to open the Breakpoints window, then click in the |
| checkbox next to the breakpoint entry to re-enable it.</li> |
| |
| <li>In the browser, click the 'add to cart' button for one of the listed products.</li> |
| |
| <li>Switch to the IDE and note that the debugger is suspended on the breakpoint set |
| in the <code>ControllerServlet</code>. Click the Step Over ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-btn.png" |
| alt="Step Over button"> ) button so that the <code>session</code> variable is assigned |
| to the session object.</li> |
| |
| <li>Open the Variables window (Alt-Shift-1; Ctrl-Shift-1 on Mac) and expand session > |
| session. You'll find the session ID listed as the value for the <code>id</code> |
| variable.</li> |
| |
| <li>To locate the <code>JSESSIONID</code> cookie, recall that you can normally access |
| cookies from a servlet by calling the |
| <a href="http://java.sun.com/webservices/docs/1.6/api/javax/servlet/http/HttpServletRequest.html#getCookies%28%29" target="_blank"><code>getCookies</code></a> |
| method on the <code>HttpServletRequest</code>. Therefore, drill into the request object: |
| request > Inherited > request > request > Inherited > cookies. |
| Here you see the <code>cookies</code> ArrayList. If you expand the list, you'll |
| find the <code>JSESSIONID</code> cookie, the value of which is the session ID.</li> |
| |
| <li>Click the Finish Session ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/finish-session-btn.png" |
| alt="Finish Session button"> ) button to terminate the debug session.</li> |
| </ol> |
| |
| |
| <h3 id="url-rewrite">Maintaining Sessions with URL Rewriting</h3> |
| |
| <p>As mentioned, the servlet engine detects whether cookies are supported for the client |
| browser, and if not, it switches to URL rewriting as a means of maintaining sessions. |
| This all happens transparently for the client. For you, the developer, the process |
| isn't entirely transparent.</p> |
| |
| <p>You need to ensure that the application is capable of rewriting URLs whenever cookies |
| are disabled. You do this by calling the response’s <code>encodeURL</code> method |
| on all URLs returned by servlets in your application. Doing so enables the session |
| ID to be appended to the URL in the event that the use of cookies is not an option; |
| otherwise, it returns the URL unchanged.</p> |
| |
| <p>For example, the browser sends a request for <code>AffableBean</code>'s third category |
| (bakery): <code>category?3</code>. The server responds with session ID included in the |
| URL:</p> |
| |
| <pre class="examplecode">/AffableBean/category<strong>;jsessionid=364b636d75d90a6e4d0085119990</strong>?3</pre> |
| |
| <p>As stated above, <em>all URLs returned by your application's servlets must be encoded</em>. |
| Keep in mind that JSP pages are compiled into servlets. How can you encode URLs in JSP |
| pages? JSTL's |
| <a href="http://java.sun.com/products/jsp/jstl/1.1/docs/tlddocs/c/url.html" target="_blank"><code><c:url></code></a> |
| tag serves this purpose. The following exercise demonstrates the problem and illustrates |
| a solution.</p> |
| |
| <ol> |
| <li>Temporarily disable cookies in your browser. If you are using Firefox, you can |
| choose Tools > Options (Firefox > Preferences on Mac). In the window that |
| displays, select the Privacy tab, then under History, select 'Use custom settings |
| for history' in the provided drop-down. Deselect the 'Accept cookies from sites' |
| option. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/firefox.png" |
| class="margin-around b-all" alt="Firefox Preferences window" |
| title="Temporarily disable cookies in your browser"></li> |
| |
| <li>Run the <code>AffableBean</code> project. When the welcome page displays, click |
| into a category, then try adding an item to your cart. You'll see that the |
| application's functionality is severely compromised in its present state. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/compromised.png" |
| class="margin-around b-all" alt="Broken categories page" width="688px" |
| title="The application's functionality is compromised when the client doesn't accept cookies"> |
| |
| <br> |
| As before, the server generates a session and binds objects to it. This is how |
| the category page is able to display the selected category and products. However, |
| the server has failed in its attempt to set a <code>JSESSIONID</code> cookie. |
| Therefore, when the client makes a second request (when user clicks 'add to cart'), |
| the server has no way of identifying the session which the request belongs to. |
| It therefore cannot locate any of the attributes previously set in the session, |
| such as <code>selectedCategory</code> and <code>categoryProducts</code>. This |
| why the rendered response lacks the information specified by these attributes.</li> |
| |
| <li>Open the project's <code>category.jsp</code> page in the editor. Locate the line |
| that implements the 'add to cart' button (line 58). The <code><form></code> |
| element's <code>action</code> attribute determines the request sent to the server. |
| |
| <pre class="examplecode"><form action="addToCart" method="post"></pre></li> |
| |
| <li>Modify the request so that it is passed through the <code><c:url></code> tag. |
| |
| <pre class="examplecode"><form action="<strong><c:url value='addToCart'/></strong>" method="post"></pre></li> |
| |
| <li>Press Ctrl-S (⌘-S on Mac) to save changes to the file. Recall that the IDE |
| provides the Deploy on Save feature, which is enabled by default. This means that |
| any saved changes are automatically deployed to your server.</li> |
| |
| <li>In the browser, select a different category so that the application renders the |
| newly modified category page.</li> |
| |
| <li>Examine the source code for the page. In Firefox, you can press Ctrl-U (⌘-U on |
| Mac). The 'add to cart' button for each product displays with the session ID appended |
| to the URL. |
| |
| <pre class="examplecode"> |
| <form action="addToCart<strong>;jsessionid=4188657e21d72f364e0782136dde</strong>" method="post"></pre></li> |
| |
| <li>Click the 'add to cart' button for any item. You see that the server is now able |
| to determine the session which the request belongs to, and renders the response |
| appropriately.</li> |
| |
| <li>Before proceeding, make sure to re-enable cookies for your browser.</li> |
| </ol> |
| |
| <p id="encodeUrl">Again, every link that a user is able to click on within the application, |
| whose response requires some form of session-related data, needs to be properly encoded. |
| Sometimes implementation is not as straight-forward as the example shown above. For |
| example, the 'clear cart' widget used in <code>cart.jsp</code> currently sets a |
| <code>clear</code> parameter to <code>true</code> when the link is clicked.</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:700px"> |
| <%-- clear cart widget --%> |
| <c:if test="${!empty cart && cart.numberOfItems != 0}"> |
| <a href="viewCart<strong>?clear=true</strong>" class="bubble hMargin">clear cart</a> |
| </c:if></pre></div> |
| |
| <p>The <code><c:url></code> tag can be applied to the URL in the following manner:</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:700px"> |
| <%-- clear cart widget --%> |
| <c:if test="${!empty cart && cart.numberOfItems != 0}"> |
| |
| <strong><c:url var="url" value="viewCart"> |
| <c:param name="clear" value="true"/> |
| </c:url></strong> |
| |
| <a href="<strong>${url}</strong>" class="bubble hMargin">clear cart</a> |
| </c:if></pre></div> |
| |
| <p>The <code>clear=true</code> parameter is set by adding a <code><c:param</code> tag |
| between the <code><c:url></code> tags. A variable named '<code>url</code>' is set |
| using <c:url>'s <code>var</code> attribute, and <code>var</code> is then accessed |
| in the HTML anchor tag using the <code>${url}</code> expression.</p> |
| |
| <p>You can download and examine |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot6.zip">snapshot |
| 6</a> to see how all links in the project have been encoded.</p> |
| |
| <p class="alert">URL rewriting should only be used in the event that cookies are not an |
| available tracking method. URL rewriting is generally considered a suboptimal solution |
| because it exposes the session ID in logs, bookmarks, referer headers, and cached HTML, |
| in addition to the browser's address bar. It also requires more server-side resources, |
| as the server needs to perform additional steps for each incoming request in order |
| to extract the session ID from the URL and pair it with an existing session.</p> |
| </div> |
| |
| |
| <br> |
| <h2 id="time-out">Handling Session Time-Outs</h2> |
| |
| <ul> |
| <li><a href="#time-interval">Setting Session Time Intervals</a></li> |
| <li><a href="#programmatically">Programmatically Handling Session Time-Outs</a></li> |
| </ul> |
| |
| <div class="indent"> |
| |
| <h3 id="time-interval">Setting Session Time Intervals</h3> |
| |
| <p>You should consider the maximum time interval which your server maintains sessions for. |
| If your website receives heavy traffic, a large number of sessions could expend your |
| server's memory capacity. You might therefore shorten the interval in hopes of removing |
| unused sessions. On the other hand, you certainly wouldn't want to cut sessions too short, |
| as this could become a usability issue that might have a negative impact on the business |
| behind the website. Taking the <code>AffableBean</code> application as an example, a user |
| proceeds to checkout after filling her shopping cart with items. She then realizes she |
| needs to enter her credit card details and goes off to find her purse. After returning |
| to her computer with credit card in hand, she fills in the checkout form and clicks submit. |
| During this time however, her session has expired on the server. The user sees that her |
| shopping cart is empty and is redirected to the homepage. Will she really take the time |
| to step through the process again?</p> |
| |
| <p>The following steps demonstrate how to set the session time-out interval in the |
| <code>AffableBean</code> project to 10 minutes. Of course, the actual duration ultimately |
| depends on your server resources, the business objectives of the application, and the |
| popularity of your website.</p> |
| |
| <ol> |
| <li>Open the application's deployment descriptor in the editor. Press Alt-Shift-O |
| (Ctrl-Shift-O on Mac) to use the IDE's Go to File dialog. Type in '<code>web</code>', |
| then click OK. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/go-to-file.png" |
| class="margin-around b-all" alt="Go to File dialog" |
| title="The Go to File dialog enables quick navigation to project files"> |
| |
| <br> |
| The editor displays the <code>web.xml</code> file in the XML view. The |
| template that NetBeans provides for the <code>web.xml</code> file includes |
| a default setting for 30 minutes. |
| |
| <pre class="examplecode"> |
| <session-config> |
| <session-timeout> |
| 30 |
| </session-timeout> |
| </session-config></pre></li> |
| |
| <li>Click the General tab, and type in '<code>10</code>' in the Session Timeout field. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-timeout.png" |
| class="margin-around b-all" alt="General tab of web.xml file" style="width:688px" |
| title="Specify session time-out for the application under the web.xml's General tab"></li> |
| |
| <li>Save the file (Ctrl-S; ⌘-S on Mac). |
| |
| <br><br> |
| If you switch back to the XML view, you'll see that the <code><session-timeout></code> |
| element has been updated. |
| |
| <pre class="examplecode"> |
| <session-config> |
| <session-timeout>10</session-timeout> |
| </session-config></pre> |
| </li> |
| </ol> |
| |
| <p class="notes"><strong>Note:</strong> Alternatively, you could remove the <code><session-timeout></code> |
| element altogether, and edit the <code>session-properties</code> element in the GlassFish-specific |
| deployment descriptor (<code>sun-web.xml</code>). This would set the global time-out for all |
| applications in the server's web module. See the |
| <a href="http://docs.sun.com/app/docs/doc/821-1752/beaha" target="_blank">Oracle GlassFish Server |
| 3.0.1 Application Development Guide: Creating and Managing Sessions</a> for more details.</p> |
| |
| |
| <h3 id="programmatically">Programmatically Handling Session Time-Outs</h3> |
| |
| <p>If your application relies on sessions, you need to take measures to ensure that it can |
| gracefully handle situations in which a request is received for a session that has timed |
| out or cannot be identified. You can accomplish this in the <code>AffableBean</code> |
| application by creating a simple filter that intercepts requests heading to the <code>ControllerServlet</code>. |
| The filter checks if a session exists, and if not, it forwards the request to the site's |
| welcome page.</p> |
| |
| <ol> |
| <li>Start by examining the problem that arises when a session times out midway through |
| a user's visit to the site. Temporarily reset the session time-out interval to one |
| minute. Open the web deployment descriptor (<code>web.xml</code>) and enter '<code>1</code>' |
| between the <code><session-timeout></code> tags. |
| |
| <pre class="examplecode"> |
| <session-config> |
| <session-timeout><strong>1</strong></session-timeout> |
| </session-config></pre></li> |
| |
| <li>Run the <code>AffableBean</code> project. In the browser, click into a category page, |
| add several items to your cart, then click 'view cart'. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/cart-page-session-intact.png" |
| class="margin-around b-all" alt="Cart page displaying items in shopping cart" style="width:688px" |
| title="The cart page relies on a session object to display items in shopping cart"></li> |
| |
| <li>Wait at least one full minute.</li> |
| |
| <li>Update the quantity for one of the items displayed in the cart page. (Any number between |
| 1 and 99 is acceptable.) Click 'update'. The server returns an HTTP Status 500 message. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/glassfish-error-report.png" |
| class="margin-around b-all" alt="GlassFish error report displayed in browser" style="width:688px" |
| title="NullPointerException occurs when request for expired session is received"></li> |
| |
| <li>Examine the GlassFish server log in the IDE. Open the Output window (Ctrl-4; ⌘-4 on Mac) |
| and select the GlassFish Server tab. Scroll to the bottom of the log to examine the error's stack |
| trace. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/gf-server-output.png" rel="lytebox" |
| title="NullPointerException occurs when request belonging to expired session is received"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/gf-server-output.png" |
| class="margin-around b-all" alt="GlassFish error report displayed in browser" style="width:688px" |
| title="Click to enlarge"></a> |
| |
| <br> |
| The server log indicates that a <code>NullPointerException</code> occurred at line 184 |
| in the <code>ControllerServlet</code>. The Output window forms a link to the line where |
| the exception occurred.</li> |
| |
| <li>Click the link. You navigate directly to line 184 in the <code>ControllerServlet</code>. |
| Hovering your mouse over the error badge in the editor's left margin provides a tooltip |
| describing the exception. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/nullpointer-exception.png" |
| class="margin-around b-all" alt="Error badge and tooltip displayed in editor" |
| title="Error badge and tooltip indicate the location and cause of the problem"> |
| |
| <br> |
| Because the session had already expired before the request was received, the servlet |
| engine was unable to associate the request with its corresponding session. It was |
| therefore unable to locate the <code>cart</code> object (line 151). The exception |
| finally occurred in line 184 when the engine attempted to call a method on a variable |
| equating to <code>null</code>. |
| |
| <br><br> |
| Now that we've identified the problem, let's fix it by implementing a filter.</li> |
| |
| <li>Click the New File ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/new-file-btn.png" |
| alt="New File button"> ) button in the IDE's toolbar. (Alternatively, press Ctrl-N; |
| ⌘-N on Mac.)</li> |
| |
| <li>Select the <strong>Web</strong> category, then select <strong>Filter</strong> |
| and click Next.</li> |
| |
| <li>Name the filter <code>SessionTimeoutFilter</code>. Type <code>filter</code> into |
| the Packages field so that the filter class is placed in a new package when created.</li> |
| |
| <li>Click Next. Accept default settings and click Finish. A template for the <code>SessionTimeoutFilter</code> |
| is generated and opens in the editor. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> Currently, in NetBeans 6.9, it isn't possible |
| to use the wizard to set a mapping to a servlet that isn't registered in the web |
| deployment descriptor. (<code>ControllerServlet</code> was registered using the |
| <code>@WebServlet</code> annotation.) We'll therefore modify the generated code |
| in the next step.</p></li> |
| |
| <li>Modify the <code>@WebFilter</code> annotation signature so that it appears as follows. |
| |
| |
| <pre class="examplecode">@WebFilter(<strong>servletNames = {"Controller"}</strong>) |
| public class SessionTimeoutFilter implements Filter {</pre> |
| |
| This sets the filter to intercept any requests that are handled by the <code>ControllerServlet</code>. |
| (Alternatively, you could have kept the <code>urlPatterns</code> attribute, and listed all |
| patterns that the <code>ControllerServlet</code> handles.) |
| |
| <br><br> |
| Note that '<code>Controller</code>' is the name of the <code>ControllerServlet</code>, |
| as specified in the servlet's <code>@WebServlet</code> annotation signature. Also note |
| that you've removed the <code>filterName</code> attribute, since the name of the filter |
| class is used by default. |
| |
| <br><br> |
| The IDE's filter template provides a lot of interesting code which is worth inspecting |
| in its own right. However, most of it is not needed for our purposes here. Any filter |
| class must implement the <code>Filter</code> interface, which defines three methods: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li><strong><code>init</code>:</strong> performs any actions after the filter is initialized |
| but before it is put into service</li> |
| <li><strong><code>destroy</code>:</strong> removes the filter from service. This method can |
| also be used to perform any cleanup operations.</li> |
| <li><strong><code>doFilter</code>:</strong> used to perform operations for each request the |
| filter intercepts</li> |
| </ul> |
| |
| <p class="tips">Use the Javadoc Index Search to pull up documentation on the |
| <code>Filter</code> interface. Press Shift-F1 (fn-Shift-F1 on Mac), then type |
| '<code>Filter</code>' into the search field and hit Enter. Select the 'Interface |
| in javax.servlet' entry. The Javadoc documentation displays in the lower pane of |
| the index search tool.</p></li> |
| |
| <li>Replace the body of the <code>SessionTimeoutFilter</code> with the following contents. |
| |
| <pre class="examplecode"> |
| @WebFilter(servletNames = {"Controller"}) |
| public class SessionTimeoutFilter implements Filter { |
| |
| <strong>public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
| throws IOException, ServletException { |
| |
| HttpServletRequest req = (HttpServletRequest) request; |
| |
| HttpSession session = req.getSession(false); |
| |
| // if session doesn't exist, forward user to welcome page |
| if (session == null) { |
| try { |
| req.getRequestDispatcher("/index.jsp").forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| return; |
| } |
| |
| chain.doFilter(request, response); |
| } |
| |
| public void init(FilterConfig filterConfig) throws ServletException {} |
| |
| public void destroy() {}</strong> |
| |
| }</pre></li> |
| |
| <li>Press Ctrl-Shift-I (⌘-Shift-I on Mac) to fix import statements. |
| (Imports need to be added for <code>HttpServletRequest</code> and <code>HttpSession</code>.) |
| Also, use the editor hints to add the <code>@Override</code> annotation |
| to the <code>init</code>, <code>destroy</code>, and <code>doFilter</code> |
| methods. |
| |
| <br><br> |
| In the coming steps, you run the debugger on the project and step through the |
| <code>doFilter</code> method to see how it determines whether the request is bound |
| to an existing session.</li> |
| |
| <li>Open the Breakpoints window (Alt-Shift-5; Ctrl-Shift-5 on Mac) and ensure that |
| you do not have any existing breakpoints set. To delete a breakpoint, right-click |
| the breakpoint and choose Delete. (If you completed the above exercise, |
| <a href="#http-monitor">Examining Client-Server Communication with the HTTP |
| Monitor</a>, you may have an outstanding breakpoint set in the <code>ControllerServlet</code>.)</li> |
| |
| <li>Run the debugger. Click the Debug Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/debug-project-btn.png" |
| alt="Debug Project button"> ) button in the IDE's main toolbar.</li> |
| |
| <li>When the welcome page displays in the browser, select a category, then add several |
| items to your shopping cart.</li> |
| |
| <li>Set a breakpoint on the line in <code>SessionTimeoutFilter</code>'s |
| <code>doFilter</code> method that tries to access the session (line 32). |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/filter-breakpoint.png" |
| class="margin-around b-all" alt="Breakpoint set in editor" |
| title="Set a breakpoint on the getSession method"></li> |
| |
| <li>In the browser, click the 'view cart' button. Switch to the IDE and note that the |
| debugger has suspended on the breakpoint. |
| |
| <br><br> |
| Recall that <code>getSession()</code> creates a new session object if |
| the current one doesn't exist. Here, we use <code>getSession(false)</code>, |
| which refrains from creating a new object if none is found. In other words, |
| the method returns <code>null</code> if the session doesn't exist.</li> |
| |
| <li>Click the Step Over ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/step-over-btn.png" |
| alt="Step Over button"> ) button, then hover your mouse over the <code>session</code> |
| variable. Provided that a minute hasn't passed since the previous request was |
| sent, you'll see that the variable has been assigned to a <code>StandardSessionFacade</code>. |
| This represents the session object for the request. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-exists.png" |
| class="margin-around b-all" alt="Popup displaying 'session' variable assigned to a session object" |
| title="Hover your mouse over variables to determine their current value"></li> |
| |
| <li>Continue stepping through the method until the request is processed. Since <code>session</code> |
| doesn't equal <code>null</code>, you skip the <code>if</code> statement and <code>chain.doFilter</code> |
| then forwards the request to the <code>ControllerServlet</code> (line 44).</li> |
| |
| <li>In the browser, make sure a full minute has passed, then update a quantity for |
| one of the product items in your cart. This is the same procedure we went through |
| earlier in the exercise when the status 500 message was returned. Now that the |
| filter intercepts requests heading to the <code>ControllerServlet</code>, let's |
| see what happens when a session time-out occurs.</li> |
| |
| <li>After clicking 'update', switch to the IDE and note that the debugger is again suspended |
| on the breakpoint set in the filter.</li> |
| |
| <li>Highlight the <code>req.getSession(false)</code> expression, then hover your |
| mouse over it. Here you see the expression equates to <code>null</code>, as the |
| session has already expired. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/session-null.png" |
| class="margin-around b-all" alt="Popup displaying 'session' variable equates to 'null'" |
| title="Highlight expressions and hover your mouse over them to determine their current value"></li> |
| |
| <li>Continue stepping through the code. Now that the <code>session</code> variable |
| equals <code>null</code>, the <code>if</code> statement on line 35 is processed, |
| and the request is forwarded to <code>/index.jsp</code>. When the debugger finishes |
| executing, you'll see that the browser displays the site's welcome page.</li> |
| |
| <li>Click the Finish Session ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/manage-sessions/finish-session-btn.png" |
| alt="Finish Session button"> ) button to terminate the debug session.</li> |
| |
| <li>Open the project's <code>web.xml</code> file and change the session time-out interval |
| back to 10 minutes. |
| |
| <pre class="examplecode"> |
| <session-config> |
| <session-timeout><strong>10</strong></session-timeout> |
| </session-config></pre> |
| </li> |
| |
| <li>Save (Ctrl-S; ⌘-S on Mac) the file.</li> |
| </ol> |
| </div> |
| |
| <p><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot6.zip">Snapshot |
| 6</a> provides you with the completed project version for this tutorial unit. One final topic |
| concerning session management should be mentioned. You can explicitly terminate a session by |
| calling the <code>invalidate</code> method on the session object. If the session is no longer |
| needed, it should be removed in order to conserve the memory available to your server. After |
| you complete the next unit, <a href="#transaction">Integrating Transactional Business |
| Logic</a>, you will see how the <code>ControllerServlet</code>, upon successfully processing |
| a customer order, destroys the user's <code>cart</code> object and terminates the session |
| using the <code>invalidate</code> method.</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:710px; margin-left:10px; margin-top:-2px"> |
| // if order processed successfully send user to confirmation page |
| if (orderId != 0) { |
| |
| // dissociate shopping cart from session |
| cart = null; |
| |
| // end session |
| session.invalidate(); |
| |
| ... |
| }</pre></div> |
| |
| <p>This is demonstrated in |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot8.zip">project |
| snapshot 8</a> (and later snapshots).</p> |
| |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Managing Sessions">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <h2 id="seeAlsoManageSessions">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Resources</h3> |
| |
| <ul> |
| <li><a href="../../../../features/java/debugger.html" target="_blank">NetBeans IDE Features: Debugger</a></li> |
| <li><a href="../../java/debug-multithreaded.html" target="_blank">Debugging Multithreaded Applications</a></li> |
| <li><a href="../../java/debug-multithreaded-screencast.html" target="_blank">Video of the Multithreaded Debugging with the NetBeans IDE</a></li> |
| <li><a href="../../java/debug-evaluator-screencast.html" target="_blank">Video of Using the Code Snippet Evaluator in the NetBeans Debugger</a></li> |
| <li><a href="../../../../community/media.html" target="_blank">Video Tutorials and Demos for NetBeans IDE</a></li> |
| <li><a href="https://netbeans.org/projects/www/downloads/download/shortcuts.pdf">Keyboard Shortcuts & Code Templates Card</a></li> |
| <li><a href="../javaee-gettingstarted.html" target="_blank">Getting Started with Java EE Applications</a></li> |
| <li><a href="../javaee-intro.html" target="_blank">Introduction to Java EE Technology</a></li> |
| <li><a href="../../../trails/java-ee.html" target="_blank">Java EE & Java Web Learning Trail</a></li> |
| </ul> |
| |
| <h3>GlassFish Resources</h3> |
| |
| <ul> |
| <li><a href="http://wiki.glassfish.java.net/Wiki.jsp?page=Screencasts" target="_blank">GlassFish Screencasts</a></li> |
| <li><a href="http://glassfish.dev.java.net/docs/index.html" target="_blank">GlassFish v3 Documentation</a></li> |
| <li><a href="http://www.sun.com/offers/details/GlassFish_Tomcat.html" target="_blank">Learning GlassFish for Tomcat Users</a></li> |
| <li><a href="http://docs.sun.com/app/docs/doc/821-1751" target="_blank">Oracle GlassFish Server 3.0.1 Administration Guide</a></li> |
| <li><a href="http://docs.sun.com/app/docs/doc/821-1750" target="_blank">Oracle GlassFish Server 3.0.1 Application Deployment Guide</a></li> |
| <li><a href="http://docs.sun.com/app/docs/doc/821-1752" target="_blank">Oracle GlassFish Server 3.0.1 Application Development Guide</a></li> |
| </ul> |
| |
| <h3>Technical Articles & Miscellaneous Resources</h3> |
| |
| <ul> |
| <li><a href="http://java.sun.com/javaee/reference/code/" target="_blank">Java EE Code Samples & Apps</a></li> |
| <li><a href="http://java.sun.com/j2se/javadoc/" target="_blank">Javadoc Tool</a> [product homepage]</li> |
| <li><a href="http://java.sun.com/j2se/javadoc/writingdoccomments/index.html" target="_blank">How to Write Doc Comments for the Javadoc Tool</a></li> |
| <li><a href="http://java.sun.com/products/servlet/Filters.html" target="_blank">The Essentials of Filters</a></li> |
| <li><a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/InterceptingFilter.html" target="_blank">Core J2EE Patterns - Intercepting Filter</a></li> |
| <li><a href="http://courses.coreservlets.com/Course-Materials/csajsp2.html" target="_blank">Beginning and Intermediate-Level Servlet, JSP, and JDBC Tutorials</a></li> |
| <li><a href="http://courses.coreservlets.com/Course-Materials/msajsp.html" target="_blank">Advanced Servlet and JSP Tutorials</a></li> |
| <li><a href="http://courses.coreservlets.com/Course-Materials/java5.html" target="_blank">Java 5 & Java 6 Tutorials</a></li> |
| <li><a href="http://www.ibm.com/developerworks/java/library/j-jstl0211.html" target="_blank">A JSTL primer, Part 1: The expression language</a></li> |
| <li><a href="http://www.ibm.com/developerworks/java/library/j-jstl0318/index.html" target="_blank">A JSTL primer, Part 2: Getting down to the core</a></li> |
| </ul> |
| </div> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="transaction">The NetBeans E-commerce Tutorial - Integrating Transactional Business Logic</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><strong>Integrating Transactional Business Logic</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#overview">Overview of the Transaction</a></li> |
| <li><a href="#projSnapshot">Examining the Project Snapshot</a></li> |
| <li><a href="#orderManager">Creating the <code>OrderManager</code> EJB</a></li> |
| <li><a href="#requestParam">Handling Request Parameters</a></li> |
| <li><a href="#placeOrder">Implementing <code>placeOrder</code> and Helper Methods</a></li> |
| <li><a href="#entityManager">Utilizing JPA's EntityManager</a></li> |
| <li><a href="#persistenceContext">Synchronizing the Persistence Context with the Database</a></li> |
| <li><a href="#transactionProgrammatically">Setting up the Transaction Programmatically</a></li> |
| <li><a href="#validate">Validating and Converting User Input</a></li> |
| <li><a href="#seeAlsoTransaction">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>The purpose of this tutorial unit is to demonstrate how you can use the object-relational |
| mapping (ORM) capabilities provided by EJB and JPA technologies to gather data |
| from a web request and write to a back-end database. Of particular interest is |
| EJB's support for <em>container-managed</em> transactions (refer to the |
| <a href="entity-session.html#gf-java-ee-container">GlassFish v3 Java EE Container |
| diagram</a>). By applying several non-intrusive annotations, you can transform |
| your EJB class into a transaction manager, thereby ensuring the integrity of the |
| data contained in the database. In other words, the transaction manager handles |
| multiple write actions to the database as a single unit of work. It ensures that |
| the work-unit is performed either in its entirety or, if failure occurs at some |
| point during the process, any changes made are rolled back to the database's |
| pre-transaction state.</p> |
| |
| <p>Within the context of the <code>AffableBean</code> application, this tutorial unit |
| focuses on processing a customer order when data from the checkout form is received. |
| You create an <code>OrderManager</code> EJB to process the checkout form data |
| along with the session <code>cart</code> object. The <code>OrderManager</code> |
| performs a transaction that involves multiple write actions to the <code>affablebean</code> |
| database. If any of the actions fails, the transaction is rolled back.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans |
| E-commerce Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left;"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#glassFishTransaction">GlassFish server</a></td> |
| <td class="tbltd1">v3 or Open Source Edition 3.0.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL database server</a></td> |
| <td class="tbltd1">version 5.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot7.zip">AffableBean |
| project</a></td> |
| <td class="tbltd1">snapshot 7</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><strong class="notes">Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which are |
| required for the application you build in this tutorial.</li> |
| |
| <li id="glassFishTransaction">The NetBeans IDE Java Bundle also includes the GlassFish server, |
| which you require for this tutorial. You could |
| <a href="http://glassfish.dev.java.net/public/downloadsindex.html" target="_blank">download |
| the GlassFish server independently</a>, but the version provided with the |
| NetBeans download has the added benefit of being automatically registered with |
| the IDE.</li> |
| |
| <li>You can follow this tutorial unit without having completed previous units. To |
| do so, see the <a href="#setup">setup instructions</a>, which describe how |
| to prepare the database and establish connectivity between the IDE, GlassFish, |
| and MySQL.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="overview">Overview of the Transaction</h2> |
| |
| <p>In order to process the data from the checkout form as well as the items contained |
| in the customer's shopping cart, you create an <code>OrderManager</code> EJB. The |
| <code>OrderManager</code> uses the provided data and performs the following write |
| actions to the database:</p> |
| |
| <ul style="margin: 5px 0 0 -.7em" class="toc"> |
| <li>A new <code>Customer</code> record is added.</li> |
| <li>A new <code>CustomerOrder</code> record is added.</li> |
| <li>New <code>OrderedProduct</code> records are added, according to the items contained |
| in the <code>ShoppingCart</code>.</li> |
| </ul> |
| |
| <p>We'll implement this by creating a <code>placeOrder</code> method which performs the |
| three write actions by sequentially calling private helper methods, <code>addCustomer</code>, |
| <code>addOrder</code>, and <code>addOrderedItems</code>. We'll also implement the |
| three helper methods in the class. To leverage EJB's container-managed transaction |
| service, we only require two annotations. These are:</p> |
| |
| <ul style="margin: 5px 0 0 -.7em" class="toc"> |
| <li><a href="http://java.sun.com/javaee/6/docs/api/javax/ejb/TransactionManagement.html" target="_blank"><code>@TransactionManagement</code></a><code>(</code><a href="http://java.sun.com/javaee/6/docs/api/javax/ejb/TransactionManagementType.html"><code>TransactionManagementType</code></a>.<code><em>CONTAINER</em>)</code>: Used to specify that any transactions occurring in the class are container-managed.</li> |
| <li><a href="http://java.sun.com/javaee/6/docs/api/javax/ejb/TransactionAttribute.html" target="_blank"><code>@TransactionAttribute</code></a><code>(</code><a href="http://java.sun.com/javaee/6/docs/api/javax/ejb/TransactionAttributeType.html"><code>TransactionAttributeType</code></a>.<code><em>REQUIRED</em>)</code>: Used on the method that invokes the transaction to specify that a new transaction should be created (if one does not already exist).</li> |
| </ul> |
| |
| <div class="indent" id="transactionDiagram"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/transaction-diagram.png" |
| alt="Diagram of transaction implemented in AffableBean" class="margin-around" |
| title="Several write actions are performed within a single transaction"> |
| </div> |
| |
| <p>Because we are implementing the transaction within a larger context, we'll approach this |
| exercise by dividing it into several easily-digestible tasks.</p> |
| |
| <ul> |
| <li><a href="#projSnapshot">Examining the Project Snapshot</a></li> |
| <li><a href="#orderManager">Creating the OrderManager EJB</a></li> |
| <li><a href="#requestParam">Handling Request Parameters</a></li> |
| <li><a href="#placeOrder">Implementing <code>placeOrder</code> and Helper Methods</a></li> |
| <li><a href="#entityManager">Utilizing JPA's EntityManager</a></li> |
| <li><a href="#persistenceContext">Synchronizing the Persistence Context with the Database</a></li> |
| <li><a href="#transactionProgrammatically">Setting up the Transaction Programmatically</a></li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="projSnapshot">Examining the Project Snapshot</h2> |
| |
| <p>Begin by examining the project snapshot associated with this tutorial unit.</p> |
| |
| <ol style="margin-top:0"> |
| <li>Open the <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot7.zip">project |
| snapshot</a> for this tutorial unit in the IDE. Click the Open Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/open-project-btn.png" |
| alt="Open Project button"> ) button and use the wizard to navigate to the location |
| on your computer where you downloaded the project. If you are proceeding from the |
| <a href="#manage-sessions">previous tutorial unit</a>, note that this project |
| snapshot is identical to the state of the project after completing the previous unit, |
| but with the following exceptions: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>The <code>confirmation.jsp</code> page is fully implemented.</li> |
| <li>The <code>affablebean.css</code> stylesheet includes rules specific |
| to the <code>confirmation.jsp</code> page implementation.</li> |
| </ul></li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) to ensure that it is properly configured with your database |
| and application server. |
| |
| <br><br> |
| <p class="alert">If you receive an error when running the project, revisit the |
| <a href="#setup">setup instructions</a>, which describe how to prepare the |
| database and establish connectivity between the IDE, GlassFish, and MySQL.</p></li> |
| |
| <li>Test the application's functionality in your browser. In particular, step through the |
| entire <a href="design.html#business">business process flow</a>. When you click the |
| submit an order from the checkout page, the confirmation page currently displays as |
| follows: |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/confirmation-page-start.png" |
| alt="Confirmation page displayed in browser" class="margin-around b-all" style="width:688px" |
| title="Confirmation page displays without any data relating to the processed order"> |
| |
| <br> |
| No data related to the order is displayed on the confirmation page. In fact, in its |
| current state the application doesn't do anything with the data from the checkout form. |
| By the end of this tutorial unit, the application will gather customer data and use |
| it to process an order. In its final state, the application will display a summary |
| of the processed order on the confirmation page, remove the user's <code>ShoppingCart</code> |
| and terminate the user session. |
| (<a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot8.zip">Snapshot |
| 8</a> completes the request-response cycle when a checkout form is submitted.) |
| </li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="orderManager">Creating the OrderManager EJB</h2> |
| |
| <ol> |
| <li>Click the New File ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/new-file-btn.png" |
| alt="New File button"> ) button in the IDE's toolbar. (Alternatively, press Ctrl-N; |
| ⌘-N on Mac.) In the New File wizard, select the Java EE category, then select |
| Session Bean.</li> |
| |
| <li>Click Next. Name the EJB '<code>OrderManager</code>', place the EJB in the <code>session</code> |
| package, and accept other default settings. (Create a stateless session bean, and do not |
| have the wizard generate an interface for the bean.) |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/ejb-wizard.png" |
| alt="Session Bean wizard" class="margin-around b-all" |
| title="Create a stateless EJB session bean using the Session Bean wizard"></li> |
| |
| <li>Click Finish. The new <code>OrderManager</code> class is generated and opens in the editor.</li> |
| </ol> |
| |
| <br> |
| <h2 id="requestParam">Handling Request Parameters</h2> |
| |
| <ol> |
| <li>Open the project's <code>ControllerServlet</code>. (Either select it from the Projects |
| window, or press Alt-Shift-O (Ctrl-Shift-O on Mac) and use the Go to File dialog.)</li> |
| |
| <li>Locate the area in the <code>doPost</code> method where the <code>/purchase</code> request |
| will be implemented (line 190). |
| |
| <br><br> |
| <p class="tips">Press Ctrl-G to use the Go To Line dialog.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/go-to-line.png" |
| alt="Go to Line dialog" class="margin-around b-all" |
| title="Use the Go to Line dialog to quickly navigate to a specific line"></li> |
| |
| <li>Implement code that extracts the parameters from a submitted checkout form. Locate |
| the <code>TODO: Implement purchase action</code> comment, delete it, and add the |
| following: |
| |
| <pre class="examplecode"> |
| // if purchase action is called |
| } else if (userPath.equals("/purchase")) { |
| |
| <strong>if (cart != null) { |
| |
| // extract user data from request |
| String name = request.getParameter("name"); |
| String email = request.getParameter("email"); |
| String phone = request.getParameter("phone"); |
| String address = request.getParameter("address"); |
| String cityRegion = request.getParameter("cityRegion"); |
| String ccNumber = request.getParameter("creditcard"); |
| }</strong> |
| |
| userPath = "/confirmation"; |
| }</pre></li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="placeOrder">Implementing placeOrder and Helper Methods</h2> |
| |
| <ol> |
| <li>In the <code>ControllerServlet</code>, add a reference to the <code>OrderManager</code> |
| EJB. Scroll to the top of the class and add a reference beneath the session facade EJBs |
| that are already listed. |
| |
| <pre class="examplecode"> |
| public class ControllerServlet extends HttpServlet { |
| |
| private String userPath; |
| private String surcharge; |
| private ShoppingCart cart; |
| |
| @EJB |
| private CategoryFacade categoryFacade; |
| @EJB |
| private ProductFacade productFacade; |
| <strong>@EJB |
| private OrderManager orderManager;</strong></pre></li> |
| |
| <li>Press Ctrl-Shift-I (�:-Shift-I on Mac) to allow the editor to add an import |
| statement for <code>session.OrderManager</code>.</li> |
| |
| <li>Use the extracted parameters, as well as the session <code>cart</code> object, as |
| arguments for the <code>OrderManager.placeOrder</code> method. Add the following |
| code: |
| |
| <pre class="examplecode"> |
| // if purchase action is called |
| } else if (userPath.equals("/purchase")) { |
| |
| if (cart != null) { |
| |
| // extract user data from request |
| String name = request.getParameter("name"); |
| String email = request.getParameter("email"); |
| String phone = request.getParameter("phone"); |
| String address = request.getParameter("address"); |
| String cityRegion = request.getParameter("cityRegion"); |
| String ccNumber = request.getParameter("creditcard"); |
| |
| <strong>int orderId = orderManager.placeOrder(name, email, phone, address, cityRegion, ccNumber, cart);</strong> |
| } |
| |
| userPath = "/confirmation"; |
| }</pre> |
| |
| Note that we haven't created the <code>placeOrder</code> method yet. This is why |
| the editor flags an error. You can use the tip that displays in the left margin, |
| which allows you to generate the method signature in the appropriate class. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/transaction/tool-tip-create-method.png" |
| rel="lytebox" title="Use editor tips to generate method signatures in other classes"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/tool-tip-create-method.png" |
| alt="Tip displayed in editor" class="margin-around b-all" style="width:688px" |
| title="Click to enlarge"></a></li> |
| |
| <li>Click the tip. The IDE generates the <code>placeOrder</code> method in the |
| <code>OrderManager</code> class. |
| |
| <pre class="examplecode"> |
| @Stateless |
| public class OrderManager { |
| |
| <strong>public int placeOrder(String name, String email, String phone, String address, String cityRegion, String ccNumber, ShoppingCart cart) { |
| throw new UnsupportedOperationException("Not yet implemented"); |
| }</strong> |
| |
| ... |
| }</pre> |
| |
| The import statement for <code>cart.ShoppingCart</code> is also automatically inserted at the |
| top of the file.</li> |
| |
| <li>In the new <code>placeOrder</code> method, use the method arguments to make calls to the |
| (yet nonexistent) helper methods. Enter the following: |
| |
| <pre class="examplecode"> |
| public int placeOrder(String name, String email, String phone, String address, String cityRegion, String ccNumber, ShoppingCart cart) { |
| |
| <strong>Customer customer = addCustomer(name, email, phone, address, cityRegion, ccNumber); |
| CustomerOrder order = addOrder(customer, cart); |
| addOrderedItems(order, cart);</strong> |
| }</pre> |
| |
| Note that we need to follow a particular order due to database constraints. For example, |
| a <code>Customer</code> record needs to be created before the <code>CustomerOrder</code> |
| record, since the <code>CustomerOrder</code> requires a reference to a <code>Customer</code>. |
| Likewise, the <code>OrderedItem</code> records require a reference to an existing |
| <code>CustomerOrder</code>.</li> |
| |
| <li>Press Ctrl-Shift-I (⌘:-Shift-I on Mac) to fix imports. Import statements for |
| <code>entity.Customer</code> and <code>entity.CustomerOrder</code> are automatically |
| added to the top of the file.</li> |
| |
| <li>Use the editor hints to have the IDE generate method signatures for <code>addCustomer</code>, |
| <code>addOrder</code>, and <code>addOrderedItems</code>. After utilizing the three hints, |
| the <code>OrderManager</code> class looks as follows. |
| |
| <pre class="examplecode"> |
| @Stateless |
| public class OrderManager { |
| |
| public int placeOrder(String name, String email, String phone, String address, String cityRegion, String ccNumber, ShoppingCart cart) { |
| |
| Customer customer = addCustomer(name, email, phone, address, cityRegion, ccNumber); |
| CustomerOrder order = addOrder(customer, cart); |
| addOrderedItems(order, cart); |
| } |
| |
| <strong>private Customer addCustomer(String name, String email, String phone, String address, String cityRegion, String ccNumber) { |
| throw new UnsupportedOperationException("Not yet implemented"); |
| } |
| |
| private CustomerOrder addOrder(Customer customer, ShoppingCart cart) { |
| throw new UnsupportedOperationException("Not yet implemented"); |
| } |
| |
| private void addOrderedItems(CustomerOrder order, ShoppingCart cart) { |
| throw new UnsupportedOperationException("Not yet implemented"); |
| }</strong> |
| |
| }</pre> |
| |
| Note that an error is still flagged in the editor, due to the fact that the method |
| is currently lacking a return statement. The <code>placeOrder</code> signature |
| indicates that the method returns an <code>int</code>. As will later be demonstrated, |
| the method returns the order ID if it has been successfully processed, otherwise |
| <code>0</code> is returned.</li> |
| |
| <li>Enter the following return statement. |
| |
| <pre class="examplecode"> |
| public int placeOrder(String name, String email, String phone, String address, String cityRegion, String ccNumber, ShoppingCart cart) { |
| |
| Customer customer = addCustomer(name, email, phone, address, cityRegion, ccNumber); |
| CustomerOrder order = addOrder(customer, cart); |
| addOrderedItems(order, cart); |
| <strong>return order.getId();</strong> |
| }</pre> |
| |
| At this stage, all errors in the <code>OrderManager</code> class are resolved.</li> |
| |
| <li>Begin implementing the three helper methods. For now, simply add code that |
| applies each method's input parameters to create new entity objects. |
| |
| <br><br> |
| <h4>addCustomer</h4> |
| |
| <p>Create a new <code>Customer</code> object and return the object.</p> |
| |
| <pre class="examplecode"> |
| private Customer addCustomer(String name, String email, String phone, String address, String cityRegion, String ccNumber) { |
| |
| <strong>Customer customer = new Customer(); |
| customer.setName(name); |
| customer.setEmail(email); |
| customer.setPhone(phone); |
| customer.setAddress(address); |
| customer.setCityRegion(cityRegion); |
| customer.setCcNumber(ccNumber); |
| |
| return customer;</strong> |
| }</pre> |
| |
| <br> |
| <h4>addOrder</h4> |
| |
| <p>Create a new <code>CustomerOrder</code> object and return the object. Use the |
| <code>java.util.Random</code> class to generate a random confirmation number.</p> |
| |
| <pre class="examplecode"> |
| private CustomerOrder addOrder(Customer customer, ShoppingCart cart) { |
| |
| <strong>// set up customer order |
| CustomerOrder order = new CustomerOrder(); |
| order.setCustomer(customer); |
| order.setAmount(BigDecimal.valueOf(cart.getTotal())); |
| |
| // create confirmation number |
| Random random = new Random(); |
| int i = random.nextInt(999999999); |
| order.setConfirmationNumber(i); |
| |
| return order;</strong> |
| }</pre> |
| |
| <br> |
| <h4>addOrderedItems</h4> |
| |
| <p>Iterate through the <code>ShoppingCart</code> and create |
| <code>OrderedProduct</code>s. In order to create an <code>OrderedProduct</code>, |
| you can use the <code>OrderedProductPK</code> entity class. The instantiated |
| <code>OrderedProductPK</code> can be passed to the <code>OrderedProduct</code> |
| constructor, as demonstrated below.</p> |
| |
| <pre class="examplecode"> |
| private void addOrderedItems(CustomerOrder order, ShoppingCart cart) { |
| |
| <strong>List<ShoppingCartItem> items = cart.getItems(); |
| |
| // iterate through shopping cart and create OrderedProducts |
| for (ShoppingCartItem scItem : items) { |
| |
| int productId = scItem.getProduct().getId(); |
| |
| // set up primary key object |
| OrderedProductPK orderedProductPK = new OrderedProductPK(); |
| orderedProductPK.setCustomerOrderId(order.getId()); |
| orderedProductPK.setProductId(productId); |
| |
| // create ordered item using PK object |
| OrderedProduct orderedItem = new OrderedProduct(orderedProductPK); |
| |
| // set quantity |
| orderedItem.setQuantity(scItem.getQuantity()); |
| }</strong> |
| }</pre></li> |
| |
| <li>Press Ctrl-Shift-I (⌘-Shift-I on Mac) to fix imports. A dialog |
| opens to display all classes that will be imported. Note that the dialog |
| correctly guesses for <code>java.util.List</code>. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/fix-all-imports.png" |
| alt="Fix All Imports dialog" class="margin-around b-all" |
| title="Press Ctrl-Shift-I to fix imports in a file"></li> |
| |
| <li>Click OK. All necessary import statements are added, and the class becomes |
| free of any compiler errors.</li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="entityManager">Utilizing JPA's EntityManager</h2> |
| |
| <p>As was mentioned in <a href="#entity-session">Adding Entity Classes and Session |
| Beans</a>, the <code>EntityManager</code> API is included in JPA, and is responsible |
| for performing persistence operations on the database. In the <code>AffableBean</code> |
| project, all of the EJBs employ the <code>EntityManager</code>. To demonstrate, |
| open any of the session facade beans in the editor and note that the class uses |
| the <code>@PersistenceContext</code> annotation to express a dependency on a |
| container-managed <code>EntityManager</code> and its associated persistence context |
| (<code>AffableBeanPU</code>, as specified in the <code>persistence.xml</code> file). |
| For example, the <code>ProductFacade</code> bean looks as follows:</p> |
| |
| <pre class="examplecode" style="width:720px"> |
| @Stateless |
| public class ProductFacade extends AbstractFacade<Product> { |
| <strong>@PersistenceContext(unitName = "AffableBeanPU") |
| private EntityManager em;</strong> |
| |
| protected EntityManager getEntityManager() { |
| return em; |
| } |
| |
| ... |
| |
| // manually created |
| public List<Product> findForCategory(Category category) { |
| return em.createQuery("SELECT p FROM Product p WHERE p.category = :category"). |
| setParameter("category", category).getResultList(); |
| } |
| |
| }</pre> |
| |
| <p>To be able to write to the database, the <code>OrderManager</code> EJB must |
| take similar measures. With an <code>EntityManager</code> instance, we can |
| then modify the helper methods (<code>addCustomer</code>, <code>addOrder</code>, |
| <code>addOrderedItems</code>) so that the entity objects they create are |
| written to the database.</p> |
| |
| <ol> |
| <li>In <code>OrderManager</code>, apply the <code>@PersistenceContext</code> |
| annotation to express a dependency on a container-managed <code>EntityManager</code> |
| and the <code>AffableBeanPU</code> persistence context. Also declare |
| an <code>EntityManager</code> instance. |
| |
| <pre class="examplecode"> |
| @Stateless |
| public class OrderManager { |
| |
| <strong>@PersistenceContext(unitName = "AffableBeanPU") |
| private EntityManager em;</strong> |
| |
| ... |
| }</pre></li> |
| <li>Press Ctrl-Shift-I (⌘:-Shift-I on Mac) to fix imports. Import statements |
| for <code>javax.persistence.EntityManager</code> and <code>javax.persistence.PersistenceContext</code> |
| are added to the top of the class.</li> |
| |
| <li>Use the <code>EntityManager</code> to mark entity objects to be written to the |
| database. This is accomplished using the <code>persist</code> method in the |
| <code>EntityManager</code> API. Make the following modifications to the helper |
| methods. |
| |
| <br><br> |
| <h4>addCustomer</h4> |
| |
| <pre class="examplecode" style="margin-top:0"> |
| private Customer addCustomer(String name, String email, String phone, String address, String cityRegion, String ccNumber) { |
| |
| Customer customer = new Customer(); |
| customer.setName(name); |
| customer.setEmail(email); |
| customer.setPhone(phone); |
| customer.setAddress(address); |
| customer.setCityRegion(cityRegion); |
| customer.setCcNumber(ccNumber); |
| |
| <strong>em.persist(customer);</strong> |
| return customer; |
| }</pre> |
| |
| <br> |
| <h4>addOrder</h4> |
| |
| <pre class="examplecode" style="margin-top:0"> |
| private CustomerOrder addOrder(Customer customer, ShoppingCart cart) { |
| |
| // set up customer order |
| CustomerOrder order = new CustomerOrder(); |
| order.setCustomer(customer); |
| order.setAmount(BigDecimal.valueOf(cart.getTotal())); |
| |
| // create confirmation number |
| Random random = new Random(); |
| int i = random.nextInt(999999999); |
| order.setConfirmationNumber(i); |
| |
| <strong>em.persist(order);</strong> |
| return order; |
| }</pre> |
| |
| <br> |
| <h4>addOrderedItems</h4> |
| |
| <pre class="examplecode" style="margin-top:0"> |
| private void addOrderedItems(CustomerOrder order, ShoppingCart cart) { |
| |
| List<ShoppingCartItem> items = cart.getItems(); |
| |
| // iterate through shopping cart and create OrderedProducts |
| for (ShoppingCartItem scItem : items) { |
| |
| int productId = scItem.getProduct().getId(); |
| |
| // set up primary key object |
| OrderedProductPK orderedProductPK = new OrderedProductPK(); |
| orderedProductPK.setCustomerOrderId(order.getId()); |
| orderedProductPK.setProductId(productId); |
| |
| // create ordered item using PK object |
| OrderedProduct orderedItem = new OrderedProduct(orderedProductPK); |
| |
| // set quantity |
| orderedItem.setQuantity(String.valueOf(scItem.getQuantity())); |
| |
| <strong>em.persist(orderedItem);</strong> |
| } |
| }</pre> |
| |
| The <code>EntityManager</code>'s <code>persist</code> method does not immediately |
| write the targeted object to the database. To describe this more accurately, the |
| <code>persist</code> method places the object in the <em>persistence context</em>. |
| This means that the <code>EntityManager</code> takes on the responsibility of ensuring |
| that the entity object is synchronized with the database. Think of the persistence |
| context as an intermediate state used by the <code>EntityManager</code> to pass |
| entities between the object realm and the relational realm (hence the term 'object-relational |
| mapping'). |
| |
| <br><br> |
| What is the scope of the persistence context? If you open the IDE's Javadoc Index Search |
| (Shift-F1; Shift-fn-F1 on Mac) and examine the Javadoc documentation for the |
| <a href="http://java.sun.com/javaee/6/docs/api/javax/persistence/PersistenceContext.html" target="_blank"><code>@PersistenceContext</code></a> |
| annotation, you'll note that the <code>type</code> element is used to "specif[y] |
| whether a transaction-scoped persistence context or an extended persistence context |
| is to be used." A <em>transaction-scoped</em> persistence context is created at |
| the start of a transaction, and terminated when the transaction ends. An <em>extended</em> |
| persistence context applies to stateful session beans only, and spans multiple transactions. |
| The Javadoc documentation also informs us that <code>javax.persistence.PersistenceContextType.TRANSACTION</code> |
| is the default value for the <code>type</code> element. Therefore, although we didn't |
| specify that the <code>EntityManager</code> place objects in a transaction-scoped persistence |
| context, this is in fact how a container-managed <code>EntityManager</code> behaves by |
| default.</li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="persistenceContext">Synchronizing the Persistence Context with the Database</h2> |
| |
| <p>At this stage you might assume that, transaction or no transaction, the <code>OrderManager</code> |
| is now able to successfully write entity objects to the database. Run the project |
| and see how customer orders are currently being processed.</p> |
| |
| <ol> |
| <li>Press F6 (fn-F6 on Mac) to run the project.</li> |
| |
| <li>Step through the <a href="design.html#business">business process flow</a>. |
| When you arrive at the checkout page, be sure to enter data that you know |
| will not cause SQL errors to occur when the write actions are performed. |
| (Validation is discussed in a later tutorial unit.) For example, enter the |
| following into the checkout form: |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><strong>name:</strong> <code>Hugo Reyes</code></li> |
| <li><strong>email:</strong> <code>hurley@mrcluck.com</code></li> |
| <li><strong>phone:</strong> <code>606252924</code></li> |
| <li><strong>address:</strong> <code>Karlova 33</code></li> |
| <li><strong>prague:</strong> <code>1</code></li> |
| <li><strong>credit card number:</strong> <code>1111222233334444</code></li> |
| </ul> |
| |
| <p class="tips">In the coming steps, you are going to examine the server log |
| in the IDE's Output window. Before submitting the checkout form, open the |
| Output window and clear the server log. You can accomplish this by right-clicking |
| in the server log and choosing Clear (Ctrl-L; ⌘-L on Mac).</p></li> |
| |
| <li>Click the 'submit purchase' button. The server responds with an HTTP status 500 |
| message. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/gf-error-report.png" |
| alt="Browser window displaying HTTP status 500 message" class="margin-around b-all" |
| title="Server responds with an HTTP status 500 message" style="width:688px"></li> |
| |
| <li>Switch to the IDE and examine the server log. The server log is located in the |
| Output window (Ctrl-4; ⌘-4 on Mac) under the GlassFish server tab. You come |
| across the following text. |
| |
| <pre class="examplecode">WARNING: A system exception occurred during an invocation on EJB OrderManager method |
| public int session.OrderManager.placeOrder(java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,java.lang.String,cart.ShoppingCart) |
| javax.ejb.EJBException |
| ... |
| Caused by: java.lang.NullPointerException |
| <u>at session.OrderManager.addOrderedItems(OrderManager.java:75)</u> |
| <u>at session.OrderManager.placeOrder(OrderManager.java:33)</u></pre> |
| |
| <p class="tips">Maximize the Output window by pressing Shift-Esc.</p> |
| |
| The underlines displayed in the server log form links allowing you to navigate |
| directly to the lines in your source files where errors are occurring.</li> |
| |
| <li>Click the link to <code>session.OrderManager.addOrderedItems</code>. |
| The editor displays the line that is causing the exception. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/null-pointer-exception.png" |
| alt="Editor displaying NullPointerException error" class="margin-around b-all" |
| title="Click links in server output window to navigate directly to offending lines in source files"> |
| |
| <br> |
| To understand why <code>order.getId</code> method returns <code>null</code>, |
| consider what the code is actually trying to accomplish. The <code>getId</code> |
| method attempts to get the ID of an order which is currently in the process |
| of being created. Since the ID is an auto-incrementing primary key, the database |
| automatically generates the value only when the record is added. One way to |
| overcome this is to manually synchronize the persistence context with the database. |
| This can be accomplished using the <code>EntityManager</code>'s |
| <a href="http://java.sun.com/javaee/6/docs/api/javax/persistence/EntityManager.html#flush%28%29" target="_blank"><code>flush</code></a> |
| method.</li> |
| |
| <li>In the <code>addOrderedItems</code> method, add a call to flush the persistence |
| context to the database. |
| |
| <pre class="examplecode"> |
| private void addOrderedItems(CustomerOrder order, ShoppingCart cart) { |
| |
| <strong>em.flush();</strong> |
| |
| List<ShoppingCartItem> items = cart.getItems(); |
| |
| // iterate through shopping cart and create OrderedProducts |
| for (ShoppingCartItem scItem : items) { |
| |
| int productId = scItem.getProduct().getId(); |
| |
| // set up primary key object |
| OrderedProductPK orderedProductPK = new OrderedProductPK(); |
| orderedProductPK.setCustomerOrderId(order.getId()); |
| orderedProductPK.setProductId(productId); |
| |
| // create ordered item using PK object |
| OrderedProduct orderedItem = new OrderedProduct(orderedProductPK); |
| |
| // set quantity |
| orderedItem.setQuantity(String.valueOf(scItem.getQuantity())); |
| |
| em.persist(orderedItem); |
| } |
| }</pre></li> |
| |
| <li>Rerun the project and step through the business process flow. This time, |
| when you submit the checkout form the confirmation page displays.</li> |
| |
| <li>To confirm that the details have been recorded in the database, open |
| the IDE's Services window (Ctrl-5; ⌘-5 on Mac). Locate the <code>affablebean</code> |
| connection node. If the node appears broken ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/connection-broken.png" |
| alt="Broken connection node"> ), right-click the node and choose Connect.</li> |
| |
| <li>Drill into the connection and locate the <code>affablebean</code> database's |
| <code>customer</code> table. Right-click the table and choose View Data. A |
| graphical display of the <code>customer</code> table appears in the editor. |
| The customer details that you added in the checkout form display as a record |
| in the table. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/customer-record.png" |
| alt="Graphical display of affablebean customer table" class="margin-around b-all" style="width:688px" |
| title="View Data menu option performs a 'select *' query on the selected table"> |
| |
| <br> |
| In this manner, you can also examine the <code>customer_order</code> and |
| <code>ordered_product</code> tables to determine whether data has been recorded.</li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="transactionProgrammatically">Setting up the Transaction Programmatically</h2> |
| |
| <p>A transaction's primary function is to ensure that all operations are performed |
| successfully, and if not, then none of the individual operations are |
| performed.<sup><a href="#footnote1Transaction" id="1Transaction" style="text-decoration:none">[1]</a></sup> |
| The following steps demonstrate how to ensure that the write operations performed |
| in the <code>placeOrder</code> method are treated as a single transaction.</p> |
| |
| <ol> |
| <li>Refer to the <a href="#transactionDiagram">transaction diagram</a> above. Add the |
| two transaction-related annotations to the <code>OrderManager</code> EJB. |
| |
| <pre class="examplecode"> |
| @Stateless |
| <strong>@TransactionManagement(TransactionManagementType.CONTAINER)</strong> |
| public class OrderManager { |
| |
| @PersistenceContext(unitName = "AffableBeanPU") |
| private EntityManager em; |
| |
| <strong>@TransactionAttribute(TransactionAttributeType.REQUIRED)</strong> |
| public int placeOrder(String name, String email, String phone, String address, String cityRegion, String ccNumber, ShoppingCart cart) { |
| |
| try { |
| ...</pre> |
| |
| The <code>@TransactionManagement</code> annotation is used to specify that any |
| transactions occurring in the <code>OrderManager</code> EJB are container-managed. |
| The <code>@TransactionAttribute</code> annotation placed on the <code>placeOrder</code> |
| method specifies that any operations occurring in the method must be treated as part |
| of a transaction. |
| |
| <br><br> |
| <p class="tips">According to the <a href="http://jcp.org/aboutJava/communityprocess/final/jsr318/index.html" target="_blank">EJB |
| Specification</a>, container-managed transactions are enabled by default for |
| session beans. Furthermore, if you examine the Javadoc for both of the above |
| annotations, you will rightly point out that <code>CONTAINER</code> is the default |
| <code>TransactionManagementType</code>, and <code>REQUIRED</code> is the default |
| <code>TransactionAttributeType</code>. In other words, neither of the two annotations |
| is required for your code to run properly. However, it is often helpful to explicitly |
| include default settings in your sources to improve readability.</p></li> |
| |
| <li>Currently, the <code>placeOrder</code> method returns the ID of the processed order. |
| In the event that the transaction fails and the order isn't processed, have the method |
| return '<code>0</code>'. Use a <code>try-catch</code> expression. |
| |
| <pre class="examplecode"> |
| @TransactionAttribute(TransactionAttributeType.REQUIRED) |
| public int placeOrder(String name, String email, String phone, String address, String cityRegion, String ccNumber, ShoppingCart cart) { |
| |
| <strong>try {</strong> |
| Customer customer = addCustomer(name, email, phone, address, cityRegion, ccNumber); |
| CustomerOrder order = addOrder(customer, cart); |
| addOrderedItems(order, cart); |
| return order.getId(); |
| <strong>} catch (Exception e) { |
| return 0; |
| }</strong></pre> |
| |
| <div class="feedback-box float-left" style="width: 683px;"> |
| |
| <h3>NetBeans Support for Code Templates</h3> |
| |
| <p>When you work in the editor, take advantage of the IDE's support for |
| code templates. Becoming proficient in using code templates ultimately |
| enables you to work more efficiently and reliably.</p> |
| |
| <br> |
| <p>For example, in the above step you can apply the <code>trycatch</code> |
| template by typing in '<code>trycatch</code>' then pressing Tab. The |
| template is added to your file.</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:630px"> |
| @TransactionAttribute(TransactionAttributeType.REQUIRED) |
| public int placeOrder(String name, String email, String phone, String address, String cityRegion, String ccNumber, ShoppingCart cart) { |
| |
| <strong>try { |
| |
| } catch (Exception e) { |
| }</strong> |
| Customer customer = addCustomer(name, email, phone, address, cityRegion, ccNumber); |
| CustomerOrder order = addOrder(customer, cart); |
| addOrderedItems(order, cart); |
| return order.getId();</pre></div> |
| |
| <p>You can then move the four existing lines into the <code>try</code> clause |
| by highlighting the lines, then holding Alt-Shift (Ctrl-Shift on Mac) and |
| pressing the up arrow key. When you are finished, press F while holding |
| Alt-Shift (Ctrl-Shift on Mac) to format the code.</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="width:630px"> |
| @TransactionAttribute(TransactionAttributeType.REQUIRED) |
| public int placeOrder(String name, String email, String phone, String address, String cityRegion, String ccNumber, ShoppingCart cart) { |
| |
| try { |
| <strong>Customer customer = addCustomer(name, email, phone, address, cityRegion, ccNumber); |
| CustomerOrder order = addOrder(customer, cart); |
| addOrderedItems(order, cart); |
| return order.getId();</strong> |
| } catch (Exception e) { |
| }</pre></div> |
| |
| <p>It is also possible to view and edit existing code templates, and add |
| new templates in the IDE. Choose Tools > Options (NetBeans > |
| Preferences on Mac) to open the Options window. Select Editor > |
| Code Templates.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/code-templates.png" |
| class="margin-around b-all" title="View default code templates and define new templates in the Options window" |
| alt="Options window - Code Templates" style="width:660px"/> |
| |
| <br> |
| <p class="tips">If you'd like to see more templates, consult the Keyboard Shortcuts Card. |
| The Keyboard Shortcuts Card provides a list of commonly-used code templates |
| and keyboard shortcuts. Choose Help > Keyboard Shortcuts Card from the |
| main menu.</p> |
| |
| </div> |
| <br style="clear: both;"/></li> |
| |
| <li>Add the following code. Explanation follows. |
| |
| <pre class="examplecode"> |
| @PersistenceContext(unitName = "AffableBeanPU") |
| private EntityManager em; |
| <strong>@Resource |
| private SessionContext context;</strong> |
| |
| @TransactionAttribute(TransactionAttributeType.REQUIRED) |
| public int placeOrder(String name, String email, String phone, String address, String cityRegion, String ccNumber, ShoppingCart cart) { |
| |
| try { |
| Customer customer = addCustomer(name, email, phone, address, cityRegion, ccNumber); |
| CustomerOrder order = addOrder(customer, cart); |
| addOrderedItems(order, cart); |
| return order.getId(); |
| } catch (Exception e) { |
| <strong>context.setRollbackOnly();</strong> |
| return 0; |
| } |
| }</pre> |
| |
| Unfortunately, placing the three methods in the <code>try</code> clause |
| means that if one of them fails during runtime, the engine immediately |
| jumps to the <code>catch</code> clause, thus skipping any rollback operations |
| that would normally follow. |
| |
| <br><br> |
| <p class="tips">You can test this by commenting out the <code>em.flush()</code> |
| line you previously added. This way, you know that the first two methods |
| (<code>addCustomer</code> and <code>addOrder</code>) process successfully, |
| but the third method (<code>addOrderedItems</code>) fails. Run the project |
| and submit the checkout form in the browser. Since the transaction doesn't |
| roll back, the customer and order records are written to the database, but |
| any ordered items are not. This leads to a situation where the database is |
| corrupt.</p> |
| |
| To overcome this, you explicitly set the transaction for rollback in the |
| <code>catch</code> clause. The above <code>@Resource</code> annotation is |
| applied to grab an instance of the EJB's current <code>SessionContext</code>. |
| The transaction is marked for rollback using the <code>setRollbackOnly</code> |
| method.</li> |
| |
| <li>Run the project and step through the business process flow. When you submit |
| an order, return to the IDE and examine the server log. You'll see output |
| similar to the following: |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/transaction/transaction-output.png" |
| rel="lytebox" title="Persistence provider output can be examined in the server log"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/transaction-output.png" |
| class="margin-around b-all" style="width:688px" alt="Output window - server output" |
| title="Click to enlarge"></a> |
| |
| <p class="tips">Press Shift-Esc on the Output window to maximize it.</p> |
| |
| As shown in the above image, the green text indicates output from EclipseLink. |
| Recall how in <a href="#entity-session">Adding Entity Classes and Session Beans</a> |
| you set EclipseLink's logging level to <code>FINEST</code> in the persistence unit. |
| Being able to examine this output is key to understanding how the persistence provider |
| interacts with the database and is a great help when you need to debug your project.</li> |
| </ol> |
| |
| <p>You've now successfully integrated the transaction into the <code>AffableBean</code> project. |
| You can <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot8.zip">download |
| snapshot 8</a> to examine code that completes the request-response cycle when a checkout |
| form is submitted. The snapshot implements a <code>getOrderDetails</code> method in the |
| <code>OrderManager</code>, which gathers all details pertaining to the placed order. If |
| the transaction succeeds, the <code>ControllerServlet</code> places order details in the |
| request scope, destroys the user's <code>cart</code> object, terminates the session, and |
| forwards the request to the confirmation view. If the transaction fails, the <code>ControllerServlet</code> |
| flags an error and forwards the response to the checkout view, enabling the user to attempt |
| a resubmit.</p> |
| |
| <div class="indent"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/checkout-page.png" |
| alt="Checkout page displayed with process failure message" class="margin-around b-all" style="width:708px" |
| title="Upon transaction failure, the checkout page redisplays with error message"> |
| </div> |
| |
| |
| <br> |
| <h2 id="validate">Validating and Converting User Input</h2> |
| |
| <p>Also included in |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot8.zip">snapshot |
| 8</a> are implementations for client and server-side validation for the checkout form. |
| Form validation is the process of checking that a form has been filled in correctly |
| before it is processed. This not only aids users by providing meaningful feedback for |
| fields with invalid entries, but it also serves to thwart any malicious attempts to |
| submit content that could adversely affect processing or storage.</p> |
| |
| <p>There are two primary methods for validating forms: server-side (in our case, using Java), |
| and client-side (using JavaScript). Both methods are usually essential for providing |
| a pleasant user experience, as well as robust security for your application. Client-side |
| validation is useful for offering immediate feedback to the user without the need to |
| initiate a round-trip between the browser and server. As such, it can stem network traffic |
| and decrease the server load. Modern forms of client-side validation are often implemented |
| to provide immediate, "as-you-type", field-specific feedback to the user. Client-side |
| JavaScript is run on the browser, and browsers generally allow JavaScript to be disabled. |
| For this reason alone, your application cannot rely on client-side validation as the sole |
| means of guarding against malformed or nefarious input. Server-side validation checks should |
| therefore be performed when form data reaches the server. Data is extracted from the request |
| and checked prior to being processed and/or stored. If a validation error is detected, |
| the server responds by returning the form to the user with an appropriate message. If all |
| data passes validation, data is converted to a different format if required.</p> |
| |
| <ul> |
| <li><a href="#client">Client-Side Validation</a></li> |
| <li><a href="#server">Server-Side Validation</a></li> |
| <li><a href="#data">Data Conversion</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="client">Client-Side Validation</h3> |
| |
| <p>For the <code>AffableBean</code> application, client-side validation is provided by a |
| popular <a href="http://plugins.jquery.com/project/validate" target="_blank">jQuery |
| plugin</a>. jQuery is a cross-browser JavaScript library designed to simplify client-side |
| scripting of HTML.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/client-side-validation.png" |
| alt="jQuery field validation displayed on checkout form" class="margin-around b-all" |
| title="Field validation messages appear upon clicking 'submit purchase'"> |
| |
| <p><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot8.zip">Snapshot |
| 8</a> includes a <code>js</code> folder that contains the jQuery core library |
| (<code>jquery-1.4.2.js</code>) as well as the script for the validation plugin |
| (<code>jquery.validate.js</code>). The core library is referenced in the application |
| <code>header.jspf</code> file, while the validation plugin script is referenced |
| directly in <code>checkout.jsp</code> since it is only required by that file. Within |
| <code>checkout.jsp</code>, the plugin is customized to suit the checkout form based |
| on <a href="http://docs.jquery.com/Plugins/Validation/validate#toptions" target="_blank">available |
| documentation</a>. |
| |
| <pre class="examplecode" style="margin-top: 0"> |
| <script type="text/javascript"> |
| |
| $(document).ready(function(){ |
| $("#checkoutForm").validate({ |
| rules: { |
| name: "required", |
| email: { |
| required: true, |
| email: true |
| }, |
| phone: { |
| required: true, |
| number: true, |
| minlength: 9 |
| }, |
| address: { |
| required: true |
| }, |
| creditcard: { |
| required: true, |
| creditcard: true |
| } |
| } |
| }); |
| }); |
| </script></pre> |
| |
| <p>The IDE provides support for jQuery by enabling you to invoke code completion and documentation |
| in the editor when pressing Ctrl-Space.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/jquery-editor-support.png" |
| alt="jQuery documentation popup window in editor" class="margin-around b-all" style="width:688px" |
| title="Press Ctrl-Space on JavaScript code to invoke jQuery documentation"> |
| |
| <p>When you code in JavaScript, the IDE lets you specify which browsers your application is |
| targeting. Open the Options window (Choose Tools > Options; NetBeans > Preferences |
| on Mac), select Miscellaneous, then select the JavaScript tab.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/javascript-window.png" |
| alt="Options window - JavaScript pane" class="margin-around b-all" |
| title="Specify targetted browsers for your application in the Options window"> |
| |
| <p>If the function you are calling documentation on does not support all of your targeted browsers, |
| the documentation popup flags a warning. For example in the image below, Internet Explorer version |
| 5.5 has been included in the application's targeted browsers.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/ie-55.png" |
| alt="JavaScript documentation popup" class="margin-around b-all" |
| title="Documentation popup warns of method calls to non-compatible browser versions"> |
| |
| |
| <h3 id="server">Server-Side Validation</h3> |
| |
| <p>The purpose of server-side validation is to ensure that each piece of data is in a |
| format that is ready for further processing or is acceptable for storage. By "format", |
| we mean both the data type as well as the size of the piece of data. The generated JPA |
| entity classes are guaranteed to map their properties to the appropriate data types of |
| the corresponding database table columns. When relying on these entity classes, we need |
| to not only make sure that user data can be applied to create (or update) entity classes, |
| but that the size of the data is appropriate for the data types of the database columns.</p> |
| |
| <p>To illustrate an example, consider the checkout form's credit card number field. Client-side |
| validation checks that the entered data does not include letters.<sup><a href="#footnote2Transaction" |
| id="2Transaction" style="text-decoration:none">[2]</a></sup> Because the <code>maxlength</code> |
| attribute in the HTML markup is set to <code>19</code>, users cannot enter more than 19 characters |
| into this field. Server-side validation also places a limit at 19 characters. Keep in mind |
| that the data type of the <code>cc_number</code> column in the database's <code>customer</code> |
| table is: <code>VARCHAR(19)</code> (Refer to step 3 of <a href="data-model.html#addProperties">Designing |
| the Data Model: Adding Entity Properties</a>.) Now, consider what would happen if the data |
| type of the <code>cc_number</code> column is set to <code>VARCHAR(16)</code>, and a user |
| enters a number that is 19 characters long. When the checkout form is submitted, the |
| <code>creditcard</code> parameter is extracted from the request and converted into a |
| <code>String</code> so that it becomes the <code>ccNumber</code> property in a newly |
| created <code>Customer</code> object. Because 16 is the maximum number of characters |
| the database column will hold, the database server will either truncate the number to |
| 16 characters or produce a <code>MysqlDataTruncation</code> error, depending on the SQL |
| mode set for the server. (For more information on the <code>VARCHAR</code> data type, |
| see <a href="http://dev.mysql.com/doc/refman/5.1/en/char.html" target="_blank">10.4.1. |
| The CHAR and VARCHAR Types</a>.) In this manner, by not having client and server-side |
| validation properly handle the size (i.e., length) of the data received for a credit |
| card number, we risk a failed attempt at placing an order, or perhaps even worse, a |
| truncated credit card number, which obviously won't allow payment.</p> |
| |
| <p>Server-side validation in the <code>AffableBean</code> project is implemented by means of |
| a <code>Validator</code> class. The <code>ControllerServlet</code> creates a <code>Validator</code> |
| object and calls its <code>validateForm</code> method on the user data:</p> |
| |
| <pre class="examplecode" style="margin-top: 0"> |
| // validate user data |
| boolean validationErrorFlag = false; |
| validationErrorFlag = validator.validateForm(name, email, phone, address, cityRegion, ccNumber, request); |
| |
| // if validation error found, return user to checkout |
| if (validationErrorFlag == true) { |
| request.setAttribute("validationErrorFlag", validationErrorFlag); |
| userPath = "/checkout"; |
| |
| // otherwise, save order to database |
| } else { |
| |
| ... |
| }</pre> |
| |
| <p>If a validation error is found (i.e., if <code>validateForm</code> returns <code>true</code>), |
| a flag is raised in the form of a request-scoped attribute, and the server sends the |
| checkout page back to the client. When the flag is detected in <code>checkout.jsp</code>, |
| a new table row is created to display error messages at the top of the table.</p> |
| |
| <pre class="examplecode" style="margin-top: 0"> |
| <form id="checkoutForm" action="<c:url value='purchase'/>" method="post"> |
| <table id="checkoutTable"> |
| <c:if test="${!empty validationErrorFlag}"> |
| <tr> |
| <td colspan="2" style="text-align:left"> |
| <span class="error smallText">Please provide valid entries for the following field(s): |
| |
| <c:if test="${!empty nameError}"> |
| <br><span class="indent"><strong>name</strong> (e.g., Bilbo Baggins)</span> |
| </c:if> |
| <c:if test="${!empty emailError}"> |
| <br><span class="indent"><strong>email</strong> (e.g., b.baggins@hobbit.com)</span> |
| </c:if> |
| <c:if test="${!empty phoneError}"> |
| <br><span class="indent"><strong>phone</strong> (e.g., 222333444)</span> |
| </c:if> |
| <c:if test="${!empty addressError}"> |
| <br><span class="indent"><strong>address</strong> (e.g., KorunnĂ 56)</span> |
| </c:if> |
| <c:if test="${!empty cityRegionError}"> |
| <br><span class="indent"><strong>city region</strong> (e.g., 2)</span> |
| </c:if> |
| <c:if test="${!empty ccNumberError}"> |
| <br><span class="indent"><strong>credit card</strong> (e.g., 1111222233334444)</span> |
| </c:if> |
| |
| </span> |
| </td> |
| </tr> |
| </c:if> |
| |
| ... |
| </table> |
| </form></pre> |
| |
| <p>You can test server-side validation by temporarily disabling JavaScript in your browser.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/transaction/server-side-validation.png" |
| alt="Server-side validation displayed on checkout form" class="margin-around b-all" |
| title="Temporarily disable JavaScript in your browser to test server-side validation"> |
| |
| <p class="alert">The provided implementation of server-side validation here serves merely to |
| demonstrate how server-side validation can be set up in your project. The actual validation |
| logic contained in the <code>Validator</code> class does not perform anything beyond the |
| most basic of checks and should certainly not be used in a production environment!</p> |
| |
| |
| <h3 id="data">Data Conversion</h3> |
| |
| <p>Sometimes, after data has passed validation, you may need to convert it into a different |
| format. For example, this might apply to dates when users are allowed to enter them manually, |
| or numbers that have been received as <code>String</code> objects but require calculation. |
| This important step is referred to as server-side <em>data conversion</em>.</p> |
| |
| <p>Although not implemented in the <code>AffableBean</code> application, consider again the |
| checkout form's credit card number field. Both client and server-side validation allows |
| for both formats of the following number:</p> |
| |
| <pre class="examplecode">1111222233334444</pre> |
| |
| and: |
| |
| <pre class="examplecode">1111-2222-3333-4444</pre> |
| |
| <p>Because of the ambiguous nature in which this piece of user data is acquired, it might |
| be necessary to remove any hyphens ('<code>-</code>') or other non-numeric characters |
| prior to processing payment. This step would likely occur before the data is placed |
| in storage.</p> |
| </div> |
| |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Integrating Transactional Business Logic">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <h2 id="seeAlsoTransaction">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Resources</h3> |
| |
| <ul> |
| <li><a href="../javaee-intro.html" target="_blank">Introduction to Java EE Technology</a></li> |
| <li><a href="../javaee-gettingstarted.html" target="_blank">Getting Started with Java EE Applications</a></li> |
| <li><a href="https://netbeans.org/projects/www/downloads/download/shortcuts.pdf">Keyboard Shortcuts & Code Templates Card</a></li> |
| <li><a href="../../../trails/java-ee.html" target="_blank">Java EE & Java Web Learning Trail</a></li> |
| </ul> |
| |
| <h3>External Resources</h3> |
| |
| <ul> |
| <li><a href="http://jcp.org/aboutJava/communityprocess/final/jsr318/index.html" target="_blank">JSR 318: EJB 3.1 Final Release</a> [Specification Download]</li> |
| <li><a href="http://download.oracle.com/docs/cd/E17410_01/javaee/6/tutorial/doc/bncih.html" target="_blank">Java EE 6 Tutorial: Transactions</a></li> |
| <li><a href="http://www.manning.com/panda/" target="_blank">EJB 3 in Action</a> [Book]</li> |
| <li><a href="http://en.wikipedia.org/wiki/Database_transaction" target="_blank">Database Transaction</a> [Wikipedia]</li> |
| <li><a href="http://en.wikipedia.org/wiki/Ejb" target="_blank">Enterprise JavaBean</a> [Wikipedia]</li> |
| <li><a href="http://en.wikipedia.org/wiki/ACID" target="_blank">ACID</a> [Wikipedia]</li> |
| <li><a href="http://jquery.com/" target="_blank">jQuery</a></li> |
| <li><a href="http://en.wikipedia.org/wiki/Jquery" target="_blank">jQuery</a> [Wikipedia]</li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2>References</h2> |
| |
| <ol> |
| <li id="footnote1Transaction"><a href="#1Transaction" style="text-decoration:none">^</a> This <em>all or nothing</em> concept |
| can be further extrapolated into the four defining characteristics of transactions: <em>atomicity</em>, |
| <em>consistency</em>, <em>isolation</em>, and <em>durability</em> (ACID). For more information, see: |
| <a href="http://en.wikipedia.org/wiki/ACID" target="_blank">ACID</a> [Wikipedia].</li> |
| |
| <li id="footnote2Transaction"><a href="#2Transaction" style="text-decoration:none">^</a> Actually, for credit card number entries, |
| validation typically ensures that the entered string conforms to the Luhn algorithm, which is a simple |
| method of differentiating between valid numbers and a collection of random digits. This applies to the |
| <a href="http://plugins.jquery.com/project/validate" target="_blank">jQuery validation plugin</a> as |
| well. For more information, see |
| <a href="http://en.wikipedia.org/wiki/Luhn_algorithm" target="_blank">Luhn algorithm</a> [Wikipedia].</li> |
| </ol> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="language">The NetBeans E-commerce Tutorial - Adding Language Support</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><strong>Adding Language Support</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#resourceBundles">Understanding Resource Bundles</a></li> |
| <li><a href="#multilingual">Making Pages Multilingual</a></li> |
| <li><a href="#toggle">Implementing a Language Toggle</a></li> |
| <li><a href="#seeAlsoLanguage">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>The goal of this tutorial unit is to demonstrate how to enable language support |
| for a web application. "Language support" here refers to the ability |
| to display page views according to the customer-specified languages. Within the |
| context of the <code>AffableBean</code> application, we have agreed to provide |
| support for both English and Czech, as per the previously outlined |
| <a href="design.html#requirements">customer requirements</a>.</p> |
| |
| <p>In order to accomplish this, you rely on Java's support for internationalization. |
| You create a <em>resource bundle</em> for each language and let the Java runtime |
| environment determine the appropriate language for incoming client requests. You |
| also implement a 'language toggle' to enable users to switch the languages manually.</p> |
| |
| <p>The NetBeans IDE provides special support for localizing application content. This |
| includes a Customizer dialog that enables you to add new locales to an existing |
| resource bundle base name, as well as a special Properties editor that lets you |
| view and edit key-value pairs for all locales in a table layout. These are both |
| utilized in this tutorial.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans |
| E-commerce Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left;"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#glassFishLanguage">GlassFish server</a></td> |
| <td class="tbltd1">v3 or Open Source Edition 3.0.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL database server</a></td> |
| <td class="tbltd1">version 5.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot8.zip">AffableBean |
| project</a></td> |
| <td class="tbltd1">snapshot 8</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot9.zip">AffableBean |
| project</a></td> |
| <td class="tbltd1">snapshot 9</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><strong class="notes">Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which are |
| required for the application you build in this tutorial.</li> |
| |
| <li id="glassFishLanguage">The NetBeans IDE Java Bundle also includes the GlassFish server, |
| which you require for this tutorial. You could |
| <a href="http://glassfish.dev.java.net/public/downloadsindex.html" target="_blank">download |
| the GlassFish server independently</a>, but the version provided with the |
| NetBeans download has the added benefit of being automatically registered with |
| the IDE.</li> |
| |
| <li>You can follow this tutorial unit without having completed previous units. To |
| do so, see the <a href="#setup">setup instructions</a>, which describe how |
| to prepare the database and establish connectivity between the IDE, GlassFish, |
| and MySQL.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="resourceBundles">Understanding Resource Bundles</h2> |
| |
| <p>In Java, a resource bundle is a representation of the |
| <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/ResourceBundle.html" target="_blank"><code>java.util.ResourceBundle</code></a> |
| class. As stated in the Javadoc,</p> |
| |
| <blockquote style="margin-top: 0"> |
| <em>Resource bundles contain locale-specific objects. When your program needs |
| a locale-specific resource, a String for example, your program can load it |
| from the resource bundle that is appropriate for the current user's locale. |
| In this way, you can write program code that is largely independent of the |
| user's locale isolating most, if not all, of the locale-specific information |
| in resource bundles. |
| |
| <br><br> |
| This allows you to write programs that can:</em> |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><em>be easily localized, or translated, into different languages</em></li> |
| <li><em>handle multiple locales at once</em></li> |
| <li><em>be easily modified later to support even more locales</em></li> |
| </ul> |
| </blockquote> |
| |
| <p>From the Javadoc, you can also note that the <code>ResourceBundle</code> is parent |
| to both <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/ListResourceBundle.html" target="_blank"><code>ListResourceBundle</code></a> |
| and <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/PropertyResourceBundle.html" target="_blank"><code>PropertyResourceBundle</code></a>. |
| In this tutorial we utilize the <code>PropertyResourceBundle</code>, which manages |
| resources as text files that use the <code>.properties</code> extension and contain |
| locale-specific information in the form of key-value pairs. With new each translation, |
| a new version of the resource bundle is created by appending the locale identifier |
| to the base name using an underscore ('<code>_</code>'). For example, snippets from |
| two of the resource bundles you create in this tutorial look as follows:</p> |
| |
| <p><strong>messages_en.properties</strong></p> |
| |
| <pre class="examplecode" style="margin-top:0"> |
| meats=meats |
| bakery=bakery</pre> |
| |
| <p><strong>messages_cs.properties</strong></p> |
| |
| <pre class="examplecode" style="margin-top:0"> |
| meats=maso |
| bakery=peÄŤivo</pre> |
| |
| <p>In the above example, '<code>messages</code>' represents the base name, and the locale |
| identifier is the two-letter code which is appended using an underscore. (i.e., '<code>en</code>' |
| for English, '<code>cs</code>' for Czech). The two-letter codes are derived from the |
| international <a href="http://en.wikipedia.org/wiki/ISO_639" target="_blank">ISO 639</a> |
| standard, which lists codes that represent the names of languages. The ISO 639 standard |
| is adopted by the <a href="http://www.w3.org/International/" target="_blank">W3C |
| Internationalization Activity</a> and is used by all major browsers (these are the codes |
| understood in the <code>Accept-Language</code> HTTP header). It is also internalized in the |
| <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/Locale.html" target="_blank"><code>java.util.Locale</code></a> |
| class.</p> |
| |
| |
| <br> |
| <h2 id="multilingual">Making Pages Multilingual</h2> |
| |
| <p>Returning to the <code>AffableBean</code> application, after continued discussions with |
| the customer you've agreed on the following implementation details:</p> |
| |
| <ul style="margin: 0 0 0 -.7em" id="impDeets"> |
| <li>The website initially displays based on the preferred language of the user's |
| browser.</li> |
| |
| <li>If the browser's preferred language is neither English nor Czech, the site |
| displays text in English.</li> |
| |
| <li>The user has the option of changing the language by means of a 'language toggle' |
| in the page header.</li> |
| |
| <li>When using the language toggle to change the language, the user remains in the |
| same page view.</li> |
| |
| <li>The language toggle should not appear for the confirmation page, as a user will |
| already have selected his or her language prior to checkout.</li> |
| </ul> |
| |
| <p>In order to implement the above points, divide the task into two parts. Start by |
| creating basic bilingual support for page views. Once bilingual support is in place, |
| implement the language toggle that enables users to manually switch languages.</p> |
| |
| <p>There are three basic steps that you need to follow to incorporate multilingual support |
| into your web pages.</p> |
| |
| <ol style="margin: 0"> |
| <li>Create a resource bundle for each language you plan to support.</li> |
| |
| <li>Register the resource bundle with the application by setting a context parameter |
| in the <code>web.xml</code> deployment descriptor.</li> |
| |
| <li>In page views, replace 'hard-coded' text with <code><fmt:message></code> tags |
| that reference keys in the resource bundles.</li> |
| </ol> |
| |
| <p>The following exercise demonstrates how to integrate English and Czech language support |
| into the <code>AffableBean</code> welcome page by applying the above three steps, and |
| finishes by showing how to test for browser language support using Firefox.</p> |
| |
| <ol> |
| <li><a href="#createResource">Create Resource Bundles</a></li> |
| <li><a href="#register">Register the Resource Bundle with the Application</a></li> |
| <li><a href="#replace">Replace 'Hard-Coded' Text with <code><fmt:message></code> Tags</a></li> |
| <li><a href="#test">Test Supported Languages</a></li> |
| </ol> |
| |
| <div class="indent"> |
| <h3 id="createResource">Create Resource Bundles</h3> |
| |
| <ol> |
| <li>Open the <code>AffableBean</code> project <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot8.zip">snapshot |
| 8</a> in the IDE. Click the Open Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/open-project-btn.png" |
| alt="Open Project button"> ) button and use the wizard to navigate to the location |
| on your computer where you downloaded the project.</li> |
| |
| <li>Click the Run Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) button to run the project and ensure that it is properly |
| configured with your database and application server. |
| |
| <br><br> |
| <p class="alert">If you receive an error when running the project, revisit the |
| <a href="#setup">setup instructions</a>, which describe how to prepare the |
| database and establish connectivity between the IDE, GlassFish, and MySQL.</p></li> |
| |
| <li>Begin by creating a default resource bundle to contain text used in page views. Click |
| the New File ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/new-file-btn.png" |
| alt="New File button"> ) button in the IDE's toolbar. (Alternatively, press Ctrl-N; |
| ⌘-N on Mac.)</li> |
| |
| <li>Under Categories select Other, then under File Types select Properties File. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/new-file-wzd.png" |
| class="margin-around b-all" alt="New File wizard" |
| title="Create a new resource bundle using the File wizard"> |
| |
| <br> |
| Note that the wizard provides a description for the selected file type: |
| |
| <blockquote> |
| <em>Creates a resource bundle (<code>.properties</code>) file suitable for internationalizing |
| applications by separating out all human-visible text strings from your code. Resource |
| bundle files can also be used to collect other types of strings, such as properties for |
| Ant scripts. The created resource bundle contains only one locale, but you can add additional |
| locales from the created file's contextual menu. The bundle can be edited in a text file |
| (property-file format) for a specific locale or in a table that displays information for |
| all locales.</em> |
| </blockquote></li> |
| |
| <li>Click Next. In the Name and Location step, name the file <code>messages</code> and type |
| in <code>src/java/resources</code> in the Folder field. This will instruct the wizard |
| to place the resource bundle in a new package named <code>resources</code>. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/new-properties-file-wzd.png" |
| class="margin-around b-all" alt="New Properties File wizard" |
| title="Specify the name and location of the resource bundle"></li> |
| |
| <li>Click Finish. The <code>messages.properties</code> resource bundle is generated and opens |
| in the editor. |
| |
| <br><br> |
| Note that the new <code>messages.properties</code> file name does not have a language |
| code appended to it, as was previously described. This is because this file will be used |
| as the <em>default</em> resource bundle. The default resource bundle is applied when the |
| Java runtime environment does not find a direct match for the requested locale.</li> |
| |
| <li>Open the project's <code>index.jsp</code> file in the editor and note that the following |
| text is currently used: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>Greeting:</strong> <code>Welcome to the online home of the Affable Bean Green Grocer.</code></li> |
| |
| <li><strong>Introductory Message:</strong> <code>Enjoy browsing and learning more about our |
| unique home delivery service bringing you fresh organic produce, dairy, meats, breads |
| and other delicious and healthy items to your doorstep.</code></li> |
| </ul> |
| |
| Also, note that we'll need language-specific names for the four categories that display |
| when <code>index.jsp</code> renders in the browser. Since these names are currently taken |
| from the database, we can use them as keys in the resource bundle. |
| |
| <br><br> |
| Recall that one of the <a href="#impDeets">implementation details</a> outlined above states |
| that "<em>if the browser's preferred language is neither English nor Czech, the site |
| displays text in English.</em>" Therefore, the values that we apply to the |
| <code>messages.properties</code> file will be in English.</li> |
| |
| <li>In the <code>messages.properties</code> file, begin adding key-value pairs for the text used |
| in the welcome page. Add the following content. |
| |
| <pre class="examplecode"> |
| # welcome page |
| greeting=Welcome to the online home of the Affable Bean Green Grocer. |
| introText=Our unique home delivery service brings you fresh organic produce, dairy, meats, breads and other delicious and healthy items direct to your doorstep. |
| |
| # categories |
| dairy=dairy |
| meats=meats |
| bakery=bakery |
| fruit\ &\ veg=fruit & veg</pre> |
| |
| Comments are added using a number sign ('<code>#</code>'). Also, because the <code>fruit & veg</code> |
| category name contains spaces, it is necessary to escape the space characters using a backslash |
| ('<code>\</code>') in order to apply the name as a resource bundle key. |
| |
| <br><br> |
| We are now finished with the default resource bundle for the application's welcome page. |
| Let's continue by creating resource bundles for the customer-specified languages.</li> |
| |
| <li>In the Projects window, expand the Source Packages node, then right-click the <code>resources</code> |
| > <code>messages.properties</code> file node and choose Customize. The Customizer dialog |
| opens.</li> |
| |
| <li>In the Customizer dialog, click the Add Locale button. In the New Locale dialog that |
| displays, enter '<code>en</code>' in the Language Code combo box, then click OK. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/new-locale-dialog.png" |
| class="margin-around b-all" alt="New Locale dialog" |
| title="The New Locale dialog enables you to add a new locale to an existing resource bundle base name"> |
| |
| <br> |
| <p class="tips">A <em>locale</em> can be defined by both a language and a geographic region. |
| The optional country code which can be used to specify the region can be applied to define |
| formatting for dates, time, numbers, and currency. For more information, see the technical |
| article, <a href="http://java.sun.com/developer/technicalArticles/J2SE/locale/" target="_blank">Understanding |
| Locale in the Java Platform</a>.</p></li> |
| |
| <li>Click the Add Locale button again, then enter '<code>cs</code>' in the Language Code combo |
| box and click OK. The Customizer dialog displays as follows. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/customizer-dialog.png" |
| class="margin-around b-all" alt="New Locale dialog" |
| title="The New Locale dialog enables you to add a new locale to an existing resource bundle base name"></li> |
| |
| <li>Click Close. In the Projects window, note that your resource bundles look as follows. You can |
| expand a resource bundle to view the keys it contains. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/projects-window.png" |
| class="margin-around b-all" alt="Resource bundles displayed in Projects window" |
| title="View resource bundles and the keys they contain in the Projects window"></li> |
| |
| <li>Right-click any of the three resource bundles and choose Open. The Properties editor opens, |
| enabling you to view and edit key-value pairs for all locales in a table layout. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/language/properties-editor.png" |
| rel="lytebox" title="Use the Properties editor to view and edit key-value pairs for all locales" |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/properties-editor.png" |
| class="margin-around b-all" alt="Properties editor for resource bundles" style="width:688px" |
| title="Click to enlarge"></a> |
| |
| <p class="tips">Press Shift-Esc to maximize the window in the IDE.</p> |
| |
| Note that when you add a new locale using the Customizer dialog, as you did for English and |
| Czech in the previous steps, the keys and values of the default resource bundle are copied |
| to the new locale.</li> |
| |
| <li>Modify the values for the Czech resource bundle. You can do this by <em>either</em> clicking |
| into the table cells for each row and typing your entries directly <em>or</em> selecting the |
| cell you want to edit and typing into the <strong>Value</strong> field located at the bottom |
| of the Properties editor. |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>greeting:</strong> <code>VÄ‚Âtejte vĂ‚Â našem domácÄ‚Âm on-line obchodÄ› Affable Bean Green Grocer.</code></li> |
| <li><strong>introText:</strong> <code>Naše jedineÄŤná dodávková sluĹľba Vám zajistÄ‚Â dopravu ÄŤerstvÄ‚Ëťch organickÄ‚Ëťch produktĹŻ, mlĂ©ÄŤnÄ‚Ëťch vÄ‚ËťrobkĹŻ, uzenin, peÄŤiva a dalšĂÂch delikates a zdravÄ‚Ëťch vÄ‚ËťrokĹŻ aĹľ ke dveĹ™ĂÂm.</code></li> |
| <li><strong>dairy:</strong> <code>mléčné výrobky</code></li> |
| <li><strong>meats:</strong> <code>maso</code></li> |
| <li><strong>bakery:</strong> <code>peÄŤivo</code></li> |
| <li><strong>fruit & veg:</strong> <code>ovoce a zeleniny</code></li> |
| </ul> |
| |
| <p class="tips">You can also add a comment to each key-value pair. Any text you enter into |
| the <strong>Comment</strong> field in the Properties editor is added to the resource |
| bundle text file above the key-value pair as a comment (i.e., following a '<code>#</code>' |
| sign).</p></li> |
| |
| <li>Double-click the <code>messages_cs.properties</code> file node in the Projects window. Note |
| that the text file has been updated according to your changes in the Properties editor. |
| |
| <pre class="examplecode"> |
| # welcome page |
| greeting=VÄ‚Âtejte vĂ‚Â našem domácÄ‚Âm on-line obchodÄ› Affable Bean Green Grocer. |
| introText=Naše jedineÄŤná dodávková sluĹľba Vám zajistÄ‚Â dopravu ÄŤerstvÄ‚Ëťch organickÄ‚Ëťch produktĹŻ, mlĂ©ÄŤnÄ‚Ëťch vÄ‚ËťrobkĹŻ, uzenin, peÄŤiva a dalšĂÂch delikates a zdravÄ‚Ëťch vÄ‚ËťrokĹŻ aĹľ ke dveĹ™ĂÂm. |
| |
| # categories |
| dairy=mléčné výrobky |
| meats=maso |
| bakery=peÄŤivo |
| fruit\ &\ veg=ovoce a zeleniny</pre></li> |
| </ol> |
| |
| <p>We now have the following resource bundles defined:</p> |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li>default (English)</li> |
| <li>Czech</li> |
| <li>English</li> |
| </ul> |
| |
| <p>You might assume that if the default bundle is in English, then there is no need to |
| create a resource bundle explicitly for English. However, consider the following scenario: |
| a client browser's list of preferred languages includes both Czech and English, with |
| English taking precedence over Czech. If the application doesn't provide a resource |
| bundle for English but does for Czech, pages sent to that browser will be in Czech |
| (since a Czech bundle was defined). This is clearly not the desired behavior for that |
| browser.</p> |
| |
| |
| <h3 id="register">Register the Resource Bundle with the Application</h3> |
| |
| <p>The purpose of this step is to inform JSTL's format (i.e., |
| <a href="http://download.oracle.com/docs/cd/E17802_01/products/products/jsp/jstl/1.1/docs/tlddocs/fmt/tld-summary.html" target="_blank"><code>fmt</code></a>) |
| tag library where it can locate any resource bundles existing in the application. You |
| accomplish this by instructing the application to create a |
| <a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/jstl/1.1/docs/api/javax/servlet/jsp/jstl/fmt/LocalizationContext.html" target="_blank"><code>LocalizationContext</code></a> |
| using the existing resource bundles. This can be done by setting a context parameter |
| in the application's <code>web.xml</code> deployment descriptor.</p> |
| |
| <p class="tips">The topic of setting context parameters is also covered in |
| <a href="connect-db.html#param">Connecting the Application to the Database</a>.</p> |
| |
| <ol> |
| <li>In the Projects window, expand the Configuration Files node, then double-click |
| <code>web.xml</code> to open it in the editor.</li> |
| |
| <li>Under the deployment descriptor's General tab, expand the Context Parameters |
| category.</li> |
| |
| <li>Click the Add button, then in the Add Context Parameter dialog enter the following |
| values. |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>Parameter Name:</strong> <code>javax.servlet.jsp.jstl.fmt.localizationContext</code></li> |
| <li><strong>Parameter Value:</strong> <code>resources.messages</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/add-context-parameter.png" |
| class="margin-around b-all" alt="Add Context Parameter dialog" |
| title="Add context parameters under the General tab for web.xml"> |
| |
| <p class="tips">The <code>LocalizationContext</code> class belongs to the |
| <code>javax.servlet.jsp.jstl.fmt</code> package. You can verify this by viewing |
| the <a href="http://java.sun.com/products/jsp/jstl/1.1/docs/api/index.html" target="_blank">JSTL |
| 1.1 API Reference</a> online.</p></li> |
| |
| <li>Click OK. The new context parameter is added to the table of existing context parameters |
| under the General tab.</li> |
| |
| <li>Click the deployment descriptor's XML tab. Note that the following entry has been |
| added to the file: |
| |
| <pre class="examplecode"> |
| <context-param> |
| <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name> |
| <param-value>resources.messages</param-value> |
| </context-param></pre></li> |
| </ol> |
| |
| |
| <h3 id="replace">Replace Hard-Coded Text with <code><fmt:message></code> Tags</h3> |
| |
| <p>In order to apply the localized text of resource bundles to your web pages, you reference |
| the keys from the key-value pairs you created. You can reference the keys using JSTL's |
| <code><fmt:message></code> tags.</p> |
| |
| <ol> |
| <li>Open the project's <code>index.jsp</code> page in the editor. (If already opened, |
| press Ctrl-Tab to switch to the file.)</li> |
| |
| <li>Delete instances of hard-coded text that display in the page's left column, and |
| in their place enter <code><fmt:message></code> tags using the <code>key</code> |
| attribute to specify the resource bundle key. The page's left column will look as |
| follows. |
| |
| <pre class="examplecode"> |
| <div id="indexLeftColumn"> |
| <div id="welcomeText"> |
| <p style="font-size: larger"><strong><fmt:message key='greeting'/></strong></p> |
| |
| <p><strong><fmt:message key='introText'/></strong></p> |
| </div> |
| </div></pre></li> |
| |
| <li>Add <code><fmt:message></code> tags for the four category names, but use |
| the <code>${category.name}</code> expression as the value for the <code>key</code> |
| attribute. Since the category name is also used as the value for the <code><img></code> |
| tag's <code>alt</code> attribute, follow the same procedure. The page's right |
| column will look as follows. |
| |
| <pre class="examplecode"> |
| <div id="indexRightColumn"> |
| <c:forEach var="category" items="${categories}"> |
| <div class="categoryBox"> |
| <a href="<c:url value='category?${category.id}'/>"> |
| <span class="categoryLabel"></span> |
| <span class="categoryLabelText"><strong><fmt:message key='${category.name}'/></strong></span> |
| |
| <img src="${initParam.categoryImagePath}${category.name}.jpg" |
| alt="<strong><fmt:message key='${category.name}'/></strong>" class="categoryImage"> |
| </a> |
| </div> |
| </c:forEach> |
| </div></pre></li> |
| |
| <li>Finally, ensure that you have the <code>fmt</code> tag library declared in the |
| web page. Enter the following at the top of the file: |
| |
| <pre class="examplecode"><%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %></pre> |
| |
| <p class="notes"><strong>Note:</strong> Here you add the tag library declaration |
| to the top of the <code>index.jsp</code> file. However, when you begin using |
| <code><fmt></code> tags elsewhere in the project, it may make more sense |
| to remove the tag library declaration from individual page views, and add it |
| to the header (<code>header.jspf</code>) file. This practice is adopted in |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot9.zip">snapshot |
| 9</a> (and later snapshots).</p> |
| </li> |
| </ol> |
| |
| <p>You've now completed the tasks necessary for providing bilingual support for the |
| application's welcome page. The following step demonstrates how to test the language |
| support in your browser.</p> |
| |
| |
| <h3 id="test">Test Supported Languages</h3> |
| |
| <p>You could theoretically test for the following scenarios involving the application's |
| supported languages, as well as an unsupported language (e.g., Korean):</p> |
| |
| <div class="indent"> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Use-case</th> |
| <th class="tblheader" scope="col">Outcome</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 1. Browser has no preferred language</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 2. Browser prefers only English</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 3. Browser prefers only Czech</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 4. Browser prefers only Korean</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 5. Browser prefers Korean and English; Korean takes precedence</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 6. Browser prefers Korean and English; English takes precedence</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 7. Browser prefers Korean and Czech; Korean takes precedence</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 8. Browser prefers Korean and Czech; Czech takes precedence</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"> 9. Browser prefers English and Czech; English takes precedence</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">10. Browser prefers English and Czech; Czech takes precedence</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">11. Browser prefers, in the following order, English, Czech, Korean</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">12. Browser prefers, in the following order, English, Korean, Czech</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">13. Browser prefers, in the following order, Czech, English, Korean</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">14. Browser prefers, in the following order, Czech, Korean, English</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">15. Browser prefers, in the following order, Korean, English, Czech</td> |
| <td class="tbltd1">English displays</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">16. Browser prefers, in the following order, Korean, Czech, English</td> |
| <td class="tbltd1">Czech displays</td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <br> |
| <p>Rather than stepping through all 16 scenarios, we'll demonstrate how to examine scenario 3 above, in which |
| the browser's preferred language is Czech, using the Firefox browser.</p> |
| |
| <ol> |
| <li>In Firefox, choose Tools > Options (Firefox > Preferences on Mac). In the window that |
| displays, click the Content tab. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/firefox-content.png" |
| class="margin-around b-all" alt="Firefox options - Content tab" |
| title="Examine your browser's preferred languages"></li> |
| |
| <li>Under the Languages heading, click Choose.</li> |
| |
| <li>Select any language that is currently listed in the provided text area, then click Remove. |
| (You should remember your language list and reinstate languages after completing this tutorial.)</li> |
| |
| <li>Click the 'Select Language to Add' drop-down and select <code>Czech [cs]</code>. Then |
| click the Add button. The Czech language is added to the text area. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/firefox-languages.png" |
| class="margin-around b-all" alt="Firefox options - General tab" |
| title="Specify your browser's preferred languages"></li> |
| |
| <li>Click OK, then press Esc to close Firefox' Options window.</li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ). When the welcome page opens in your browser, note |
| that text is displayed in Czech. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/czech-text.png" |
| class="margin-around b-all" alt="Czech text displayed in welcome page" style="width:688px" |
| title="The displayed language is determined by your browser's language preferences"></li> |
| </ol> |
| </div> |
| |
| |
| <br> |
| <h2 id="toggle">Implementing a Language Toggle</h2> |
| |
| <p>Now that basic Czech-English language support is in place, continue by implementing the language |
| toggle in the application's page views. We can divide this task into three parts:</p> |
| |
| <ul> |
| <li><a href="#toggleDisplay">Create Toggle Display and Synchronize with the Browser's Preferred Language</a></li> |
| <li><a href="#handleRequest">Implement Functionality to Handle a Request from the Language Toggle</a></li> |
| <li><a href="#keepTrack">Enable the Application to Keep Track of the Originating Page View</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="toggleDisplay">Create Toggle Display and Synchronize with the Browser's Preferred Language</h3> |
| |
| <ol> |
| <li>Use the Go to File dialog to open the <code>header</code> JSP fragment in the editor. Press |
| Alt-Shift-O (Ctrl-Shift-O on Mac), then type '<code>h</code>' in the dialog and click OK. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/go-to-file-dialog.png" |
| class="margin-around b-all" alt="Go to File dialog" |
| title="Use the Go to File dialog to quickly open project resources in the editor"></li> |
| |
| <li>In the <code>header.jspf</code> file, locate the first <code><div class="headerWidget"></code> |
| tag (line 56), and replace the <code>[ language toggle ]</code> placeholder text with the |
| following HTML markup. |
| |
| <pre class="examplecode"> |
| <div class="headerWidget"> |
| |
| <strong><%-- language selection widget --%> |
| english | <div class="bubble"><a href="chooseLanguage?language=cs">česky</a></div></strong> |
| </div></pre> |
| |
| This markup implements the language toggle's appearance when English is the displayed |
| language. In other words, the toggle provides a link allowing the user to select the |
| Czech (i.e., '<code>ÄŤesky</code>') option. The link is used to send a request for |
| <code>chooseLanguage</code>, and creates a query string (<code>?language=cs</code>) that |
| specifies the requested language code. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> Recall that in Unit 5, <a href="page-views-controller.html#controller">Preparing |
| the Page Views and Controller Servlet</a>, you set the <code>ControllerServlet</code> |
| to handle the <code>/chooseLanguage</code> URL pattern.</p> |
| |
| <p class="tips">Snapshot 8 includes the <a href="http://jquery.com/" target="_blank">jQuery</a> |
| JavaScript library and takes advantage of various UI effects to enhance the appearance |
| and behavior of the website. Aside from a |
| <a href="http://plugins.jquery.com/project/validate" target="_blank">jQuery plugin |
| for client-side validation</a> (discussed in the <a href="transaction.html#client">previous |
| tutorial unit</a>), the snapshot implements an easing effect for category headings in |
| the welcome page, as well as for category buttons in the category page. Configuration |
| is included in <code>header.jspf</code> of the project snapshot. Rounded corners are |
| implemented using CSS3's <a href="http://www.w3.org/TR/css3-background/#corners" |
| target="_blank">border-radius</a> property (applied in <code>affablebean.css</code>).</p></li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) to see what the toggle looks like in the browser. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/language-toggle.png" |
| class="margin-around b-all" alt="Language toggle in browser" |
| title="Run the project to view the language toggle"> |
| |
| <br> |
| Currently, the language toggle appears as in the above image regardless of what language |
| the page displays in. In the next step, you integrate JSTL logic into the toggle so that |
| it renders according to the language displayed on the page.</li> |
| |
| <li id="step4">Modify the toggle implementation as follows. |
| |
| <pre class="examplecode"> |
| <div class="headerWidget"> |
| |
| <%-- language selection widget --%> |
| <strong><c:choose> |
| <c:when test="${pageContext.request.locale.language ne 'cs'}"> |
| english |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="en"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">english</a></div> |
| </c:otherwise> |
| </c:choose> | |
| |
| <c:choose> |
| <c:when test="${pageContext.request.locale.language eq 'cs'}"> |
| ÄŤesky |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="cs"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">česky</a></div> |
| </c:otherwise> |
| </c:choose></strong> |
| </div></pre> |
| |
| In the above implementation, you rely on conditional tags from JSTL's <code>core</code> |
| tag library to display the left and right portions of the toggle according to the language |
| used by the request locale. What is the "language used by the request locale"? |
| When a request is made, the browser passes a list of preferred locales in the <code>Accept-Language</code> |
| HTTP header. The Java runtime environment on the server reads the list and determines |
| the best match based on the locales defined by the application's resource bundles. This |
| match is then recorded in the <code>ServletRequest</code> object, and can be accessed |
| using the <code>getLocale</code> method. For example, you could access the preferred |
| locale from a servlet with the following statement. |
| |
| <pre class="examplecode">request.getLocale();</pre> |
| |
| <p class="tips">You can use the IDE's HTTP Monitor (Window > Debugging > HTTP |
| Server Monitor) to examine HTTP headers for client requests. In order to use the |
| HTTP Monitor, you need to first activate it for the server you are using. Unit 8, |
| <a href="#manage-sessions">Managing Sessions</a> provides a demonstration |
| under the sub-section, <a href="manage-sessions.html#http-monitor">Examining |
| Client-Server Communication with the HTTP Monitor</a>.</p> |
| |
| <p>To determine the language of the preferred locale, you use the <code>Locale</code> |
| class' <code>getLanguage</code> method. Again, from a servlet you could access the |
| language of the client request's preferred locale with the following.</p> |
| |
| <pre class="examplecode">request.getLocale().getLanguage();</pre> |
| |
| <p>Returning to the code you just added to the <code>header.jspf</code> fragment, |
| you utilize the <code>pageContext.request</code> implicit object to access the |
| <code>ServletRequest</code> for the given client request. Using dot notation, you |
| then proceed to call the same methods as you would from a servlet. In the above |
| example, accessing the "language used by the request locale" is as simple |
| as:</p> |
| |
| <pre class="examplecode">${pageContext.request.locale.language}</pre> |
| |
| <p class="notes"><strong>Note:</strong> The above implementation uses <code><c:url></code> |
| tags to set up the toggle link. This is done in order to properly encode the request |
| URL in the event that URL rewriting is used as a means for session tracking. Unit 8, |
| <a href="manage-sessions.html#encodeUrl">Managing Sessions</a> provides a brief |
| explanation of how the <code><c:url></code> tags can be used.</p></li> |
| |
| <li>Add a basic language test to the <code>header.jspf</code> file. This will enable us to |
| check whether the toggle is properly rendering according to the client request's preferred |
| language. Enter the following after the page's <code><body></code> tag. |
| |
| <pre class="examplecode"> |
| <body> |
| |
| <strong><%-- Language test --%> |
| <p style="text-align: left;"><strong>tests:</strong> |
| <br> |
| <code>\${pageContext.request.locale.language}</code>: ${pageContext.request.locale.language} |
| </p></strong> |
| |
| <div id="main"></pre></li> |
| |
| <li>Ensure that you have set Czech as your browser's preferred language. (If you are |
| following this tutorial unit sequentially, you've already done this. If not, refer |
| to the steps outlined above in <a href="#test">Test Supported Languages</a>.)</li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) and examine the application welcome page in the browser. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/language-test.png" |
| class="margin-around b-all" style="width:688px" alt="Language test and welcome page displayed in browser" |
| title="Language toggle displays according to request's preferred language"> |
| |
| <br> |
| If your browser's preferred language is set to Czech, you can note the following: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li>The test that we introduced in the previous step indicates that '<code>cs</code>' |
| is the preferred language.</li> |
| |
| <li>Czech text is displayed in the page.</li> |
| |
| <li>The language toggle provides a link enabling the user to select English.</li> |
| </ul> |
| </li> |
| </ol> |
| |
| |
| <h3 id="handleRequest">Implement Functionality to Handle a Request from the Language Toggle</h3> |
| |
| <p>Now that the toggle is in place and it appears according to the language displayed |
| in the page, let's continue by adding code to the <code>ControllerServlet</code> |
| that handles the request sent when a user clicks the link in the language toggle.</p> |
| |
| <p>As indicated in the current language toggle implementation from <a href="#step4">step 4</a> |
| above, the requested URL with query string looks as follows:</p> |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>English:</strong> <code>chooseLanguage?language=en</code></li> |
| <li><strong>Czech:</strong> <code>chooseLanguage?language=cs</code></li> |
| </ul> |
| |
| <p>Our goal is to register the language choice, and then display both the page view and |
| language toggle based on the chosen language. We can accomplish this by extracting |
| the <code>language</code> parameter from the query string and creating a session-scoped |
| <code>language</code> attribute that remembers the language selected by the user. Then |
| we'll return to the <code>header.jspf</code> fragment and apply the |
| <a href="http://download-llnw.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/fmt/setLocale.html" target="_blank"><code><fmt:setLocale></code></a> |
| tag to set the page language based on the user's choice. With the <code><fmt:setLocale></code> |
| tag we can manually switch the language used in the page display. We'll also modify |
| the language toggle so that if the <code>language</code> attribute has been set, the |
| toggle's appearance is determined according to the <code>language</code> attribute's |
| value.</p> |
| |
| <ol> |
| <li>Open the <code>ControllerServlet</code> in the editor. Use the Go To File dialog |
| - press Alt-Shift-O (Ctrl-Shift-O on Mac), then type '<code>controller</code>' and |
| click OK. In the opened file, locate the portion of the <code>doGet</code> method |
| that handles the <code>chooseLanguage</code> request (line 126).</li> |
| |
| <li>Delete the <code>// TODO: Implement language request</code> comment and enter code |
| to extract the <code>language</code> parameter from the request query string. |
| |
| <pre class="examplecode"> |
| // if user switches language |
| } else if (userPath.equals("/chooseLanguage")) { |
| |
| <strong>// get language choice |
| String language = request.getParameter("language");</strong> |
| }</pre></li> |
| |
| <li>Place the <code>language</code> parameter in the request scope. Add the following. |
| |
| <pre class="examplecode"> |
| // if user switches language |
| } else if (userPath.equals("/chooseLanguage")) { |
| |
| // get language choice |
| String language = request.getParameter("language"); |
| |
| <strong>// place in request scope |
| request.setAttribute("language", language);</strong> |
| }</pre></li> |
| |
| <li>As a temporary measure, have the application forward the response to the |
| <code>index.jsp</code> welcome page when the language toggle link is clicked. |
| Add the following code. |
| |
| <pre class="examplecode"> |
| // if user switches language |
| } else if (userPath.equals("/chooseLanguage")) { |
| |
| // get language choice |
| String language = request.getParameter("language"); |
| |
| // place in request scope |
| request.setAttribute("language", language); |
| |
| <strong>// forward request to welcome page |
| try { |
| request.getRequestDispatcher("/index.jsp").forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| return;</strong> |
| }</pre> |
| Naturally, forwarding the user to the welcome page regardless of what page |
| he or she is on is not an ideal way to handle the language toggle's behavior. |
| We'll return to this matter in the next sub-section, <a href="#keepTrack">Enable |
| the Application to Keep Track of the Originating Page View</a>. For the meantime |
| however, this will allow us to examine the results of the current language |
| toggle implementation when running the project.</li> |
| |
| <li>Switch to the <code>header.jspf</code> fragment (If the file is already opened |
| in the editor, press Ctrl-Tab and choose the file.) and apply the |
| <a href="http://download-llnw.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/fmt/setLocale.html" target="_blank"><code><fmt:setLocale></code></a> |
| tag to set the page language based on the new <code>language</code> variable. |
| Add the following. |
| |
| <pre class="examplecode"> |
| <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> |
| <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> |
| <strong><%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> |
| |
| <%-- Set language based on user's choice --%> |
| <c:if test="${!empty language}"> |
| <fmt:setLocale value="${language}" scope="session" /> |
| </c:if></strong> |
| |
| |
| <%@page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> |
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
| "http://www.w3.org/TR/html4/loose.dtd"></pre> |
| |
| Since the <code>language</code> variable is only created when the user clicks the |
| link in the language toggle, you perform a test using |
| <a href="http://download-llnw.oracle.com/javaee/5/jstl/1.1/docs/tlddocs/c/if.html" target="_blank"><code><c:if></code></a> |
| tags to determine whether the variable exists before attempting to set the language. |
| When applying the <code><fmt:setLocale></code> tag, you set its scope to |
| <code>session</code> as you want the user-selected language to take precedence |
| for the remainder of his or her session on the website. Also, since this is the |
| first time the <code>fmt</code> library is used in the header, you declare the tag |
| library. |
| |
| <br><br> |
| <p class="tips">You can read the EL expression <code>${!empty language}</code> as, |
| "False if the <code>language</code> variable is null or an empty string." |
| See the |
| <a href="http://download-llnw.oracle.com/javaee/5/tutorial/doc/bnahq.html#bnaim" target="_blank">Java |
| EE 5 Tutorial: Examples of EL Expressions</a> for other available examples.</p></li> |
| |
| <li>Modify the language toggle implementation so that if a value has been set by the |
| <code><fmt:setLocale></code> tag, the toggle displays according to the language |
| specified by that value. (You can determine this value using the |
| <code>${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</code> expression.) |
| |
| <br><br> |
| Enclose the current implementation within <code><c:choose></code> tags, and |
| create logic similar to the current implementation in the event that the locale has |
| been manually set. (Changes are displayed in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <div class="headerWidget"> |
| |
| <%-- language selection widget --%> |
| <strong><c:choose> |
| <%-- When user hasn't explicitly set language, |
| render toggle according to browser's preferred locale --%> |
| <c:when test="${empty sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}"></strong> |
| <c:choose> |
| <c:when test="${pageContext.request.locale.language ne 'cs'}"> |
| english |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="en"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">english</a></div> |
| </c:otherwise> |
| </c:choose> | |
| |
| <c:choose> |
| <c:when test="${pageContext.request.locale.language eq 'cs'}"> |
| ÄŤesky |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="cs"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">česky</a></div> |
| </c:otherwise> |
| </c:choose> |
| <strong></c:when> |
| |
| <%-- Otherwise, render widget according to the set locale --%> |
| <c:otherwise> |
| <c:choose> |
| <c:when test="${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session'] ne 'cs'}"> |
| english |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="en"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">english</a></div> |
| </c:otherwise> |
| </c:choose> | |
| |
| <c:choose> |
| <c:when test="${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session'] eq 'cs'}"> |
| ÄŤesky |
| </c:when> |
| <c:otherwise> |
| <c:url var="url" value="chooseLanguage"> |
| <c:param name="language" value="cs"/> |
| </c:url> |
| <div class="bubble"><a href="${url}">česky</a></div> |
| </c:otherwise> |
| </c:choose> |
| </c:otherwise> |
| </c:choose></strong> |
| |
| </div></pre></li> |
| |
| <li>Before examining the project in a browser, add another test that displays the |
| value set by the <code><fmt:setLocale></code> tag. Add the following code |
| beneath the test you created earlier. |
| |
| <pre class="examplecode"> |
| <p style="text-align: left;"><strong>tests:</strong> |
| <br> |
| <code>\${pageContext.request.locale.language}</code>: ${pageContext.request.locale.language} |
| <strong><br> |
| <code>\${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</code>: ${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</strong> |
| </p></pre> |
| |
| <p class="tips"><code>javax.servlet.jsp.jstl.fmt.locale.session</code> is the <em>string |
| literal</em> key for the <code>Locale</code> set by the <code><fmt:setLocale></code> |
| tag. You can verify this by clicking in the editor's left margin to set a breakpoint ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/breakpoint-badge.png" |
| alt="Breakpoint badge"> ) on the new test, then running the debugger ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/debug-project-btn.png" |
| alt="Debug Project button"> ) on the project. When you click the toggle link to change |
| languages in the browser, examine the Variables window (Alt-Shift-1; Ctrl-Shift-1 on |
| Mac) when the debugger suspends on the breakpoint. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/language/variables-window.png" |
| rel="lytebox" title="Run debugger and view variable and expression values in the Variables window" |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/variables-window.png" |
| class="margin-around b-all" style="width:654px" alt="Variables window" |
| title="Click to enlarge"></a> |
| |
| <br> |
| EL expressions presented in this tutorial primarily use dot (<code>.</code>) notation. The |
| format depicted in the expression above is known as <em>bracket</em> (<code>[]</code>) notation |
| whereby you enter the string literal key within quotes in order to extract the object's value: |
| |
| <div style="margin:-10px 0 0 43px"> |
| <pre class="examplecode" style="width:637px">${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</pre> |
| </div> |
| |
| <p style="margin-left:34px">Numerous EL resolver classes exist for the purpose of resolving expressions. |
| For example, when the above expression is encountered at runtime, the |
| <a href="http://download-llnw.oracle.com/javaee/6/api/javax/servlet/jsp/el/ImplicitObjectELResolver.html" target="_blank"><code>ImplicitObjectResolver</code></a> |
| first returns a <code>Map</code> that maps session-scoped attribute names to their values. (In the |
| above image of the Variables window, you can verify that session attributes are maintained in a |
| <a href="http://download-llnw.oracle.com/javase/6/docs/api/java/util/concurrent/ConcurrentHashMap.html" target="_blank"><code>ConcurrentHashMap</code></a>.) |
| In order to resolve the remainder of the expression, the |
| <a href="http://download-llnw.oracle.com/javaee/6/api/javax/el/MapELResolver.html" target="_blank"><code>MapELResolver</code></a> |
| is used to get the value of the key named '<code>javax.servlet.jsp.jstl.fmt.locale.session</code>'. |
| |
| <br><br> |
| For more information, refer to the Java EE 5 Tutorial: |
| <a href="http://download-llnw.oracle.com/javaee/5/tutorial/doc/bnahq.html#bnaif" target="_blank">Unified |
| Expression Language: Resolving Expressions</a>.</li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) and examine the application welcome page in the browser. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/toggle-page1.png" |
| class="margin-around b-all" style="width:688px" alt="Welcome page displayed in browser" |
| title="Welcome page displays according to browser's preferred language"> |
| |
| <br> |
| In the above image, the server identifies Czech (<code>cs</code>) as the browser's preferred |
| language from the <code>Accept-Language</code> HTTP header. This is indicated from the first |
| test. The page displays in Czech, and the language toggle enables the user to choose English. |
| The second test remains blank as the <code><fmt:setLocale></code> tag has not yet been |
| called.</li> |
| |
| <li>Click the toggle link for English. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/toggle-page2.png" |
| class="margin-around b-all" style="width:688px" alt="Welcome page displayed in browser" |
| title="Welcome page displays in English, according to toggle selection"> |
| |
| <br> |
| When clicking the toggle link, the default Czech language is overridden by means of the |
| <code><fmt:setLocale></code> tag implemented in the <code>header.jspf</code> file. |
| Although the browser's preferred language remains Czech, you see that the page now displays |
| according to the new language made available by the language toggle.</li> |
| |
| <li>Click the toggle link for Czech. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/toggle-page3.png" |
| class="margin-around b-all" style="width:688px" alt="Welcome page displayed in browser" |
| title="Welcome page displays in Czech, according to toggle selection"> |
| |
| <br> |
| Changing the language back to the browser's preferred language works as expected, however |
| note that the deciding factor is no longer the language detected from the <code>Accept-Language</code> |
| HTTP header, but is the language specified from the <code><fmt:setLocale></code> tag.</li> |
| |
| <li>Before continuing, remove the tests you added to the <code>header.jspf</code> file. |
| (Deleted code in <strong><strike>strike-through</strike></strong> text.) |
| |
| <pre class="examplecode"> |
| <body> |
| |
| <strong><strike><%-- Language tests --%></strike> |
| <strike><p style="text-align: left;"><strong>tests:</strong></strike> |
| <strike><br></strike> |
| <strike><code>\${pageContext.request.locale.language}</code>: ${pageContext.request.locale.language}</strike> |
| <strike><br></strike> |
| <strike><code>\${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</code>: ${sessionScope['javax.servlet.jsp.jstl.fmt.locale.session']}</strike> |
| <strike></p></strike></strong> |
| |
| <div id="main"></pre></li> |
| </ol> |
| |
| |
| <h3 id="keepTrack">Enable the Application to Keep Track of the Originating Page View</h3> |
| |
| <p>One of the <a href="#impDeets">implementation details</a> which you have agreed on with |
| the Affable Bean staff is that when the language toggle is used to change the language, |
| the user remains in the same page view. In our current implementation, the welcome page |
| is returned whenever the language toggle is clicked. A more user-friendly approach would |
| be to provide the application with a means of tracking the request page view, and forwarding |
| the request to that page view when the language toggle link is clicked.</p> |
| |
| <p>We can accomplish this by setting a session-scoped <code>view</code> attribute within each |
| of the page views, then referencing this attribute in the <code>ControllerServlet</code> |
| in order to determine where to forward the request. There are however several caveats |
| to consider when dealing with the language toggle in the confirmation page. These are |
| discussed and dealt with in steps 7-11 below.</p> |
| |
| <p>Begin this exercise with <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot9.zip">snapshot |
| 9</a> of the <code>AffableBean</code> project. This snapshot includes completed English |
| and Czech resource bundles for all page views, all page views have been modified to use |
| text from the resource bundles, and the language toggle is presented in a state corresponding |
| to this point in the tutorial.</p> |
| |
| <ol> |
| <li>Open <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot9.zip">snapshot |
| 9</a> in the IDE. Click the Open Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/open-project-btn.png" |
| alt="Open Project button"> ) button and use the wizard to navigate to the location |
| on your computer where you downloaded the project.</li> |
| |
| <li>Click the Run Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) button to run the project. When navigating through the site, |
| note that when you click the language toggle from any of the page views, you are returned |
| to the application's welcome page. |
| |
| <br><br> |
| <p class="alert">If you receive an error when running the project, revisit the |
| <a href="#setup">setup instructions</a>, which describe how to prepare the |
| database and establish connectivity between the IDE, GlassFish, and MySQL.</p></li> |
| |
| <li>Use <a href="http://download.oracle.com/docs/cd/E17802_01/products/products/jsp/jstl/1.1/docs/tlddocs/c/set.html" target="_blank"><code><c:set></code></a> |
| tags to set a session-scoped <code>view</code> attribute for each of the page views. |
| Open each of the page views in the editor and add the following code to the top of |
| each file. |
| |
| <h4>index.jsp</h4> |
| |
| <pre class="examplecode"> |
| <%-- Set session-scoped variable to track the view user is coming from. |
| This is used by the language mechanism in the Controller so that |
| users view the same page when switching between English and Czech. --%> |
| <c:set var='view' value='/index' scope='session' /></pre> |
| |
| <h4>category.jsp</h4> |
| |
| <pre class="examplecode"> |
| <%-- Set session-scoped variable to track the view user is coming from. |
| This is used by the language mechanism in the Controller so that |
| users view the same page when switching between English and Czech. --%> |
| <c:set var='view' value='/category' scope='session' /></pre> |
| |
| <h4>cart.jsp</h4> |
| |
| <pre class="examplecode"> |
| <%-- Set session-scoped variable to track the view user is coming from. |
| This is used by the language mechanism in the Controller so that |
| users view the same page when switching between English and Czech. --%> |
| <c:set var='view' value='/cart' scope='session' /></pre> |
| |
| <h4>checkout.jsp</h4> |
| |
| <pre class="examplecode"> |
| <%-- Set session-scoped variable to track the view user is coming from. |
| This is used by the language mechanism in the Controller so that |
| users view the same page when switching between English and Czech. --%> |
| <c:set var='view' value='/checkout' scope='session' /></pre> |
| |
| Based on customer-agreed <a href="#impDeets">implementation details</a>, we |
| do not need to provide a means of switching languages on the confirmation page |
| view. From a usability perspective, a user will have already selected his or |
| her preferred language prior to checkout. From an implementation perspective, |
| recall that we destroy the user session upon a successfully completed order. |
| (Refer back to the final paragraph in <a href="#manage-sessions">Managing |
| Sessions</a>, which describes how to apply the <code>invalidate</code> method |
| to explicitly terminate a user session.) If the Affable Bean staff were to insist |
| on allowing customers to view their orders bilingually, you would need to consider |
| the following scenarios, dependent on whether you destroy the user session |
| upon displaying the confirmation page: |
| |
| <ol style="margin: 5px 0 0 0em; list-style-type:lower-alpha"> |
| <li><strong>Session destroyed:</strong> Would be necessary to take |
| extra measures to ensure that a <code>chooseLanguage</code> request |
| from the confirmation page refers to the appropriate order, and can |
| display customer-sensitive details in a secure fashion.</li> |
| |
| <li><strong>Session maintained:</strong> Would risk enabling users |
| to mistakenly place double orders on their shopping cart. Also, by |
| not terminating user sessions when they are no longer needed, an |
| unnecessary load may be placed on the server.</li> |
| </ol></li> |
| |
| <li>Open the <code>ControllerServlet</code> in the editor. (If already opened, |
| press Ctrl-Tab and choose the file.) In the opened file, locate the portion |
| of the <code>doGet</code> method that handles the <code>chooseLanguage</code> |
| request (line 126). |
| |
| <br><br> |
| Note that currently <code>chooseLanguage</code> requests are forwarded to |
| the <code>index.jsp</code> welcome page. |
| |
| <pre class="examplecode"> |
| // if user switches language |
| } else if (userPath.equals("/chooseLanguage")) { |
| |
| // get language choice |
| String language = request.getParameter("language"); |
| |
| // place in session scope |
| session.setAttribute("language", language); |
| |
| <strong>// forward request to welcome page |
| try { |
| request.getRequestDispatcher("/index.jsp").forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| return;</strong> |
| }</pre></li> |
| |
| <li>Use the <code>view</code> session attribute to forward the request back |
| to the originating page view. Make the following changes (in <strong>bold</strong>). |
| |
| <pre class="examplecode"> |
| // if user switches language |
| } else if (userPath.equals("/chooseLanguage")) { |
| |
| // get language choice |
| String language = request.getParameter("language"); |
| |
| // place in request scope |
| request.setAttribute("language", language); |
| |
| <strong>String userView = (String) session.getAttribute("view"); |
| |
| if ((userView != null) && |
| (!userView.equals("/index"))) { // index.jsp exists outside 'view' folder |
| // so must be forwarded separately |
| userPath = userView; |
| } else { |
| |
| // if previous view is index or cannot be determined, send user to welcome page</strong> |
| try { |
| request.getRequestDispatcher("/index.jsp").forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| } |
| return; |
| <strong>}</strong> |
| }</pre> |
| |
| In the above implementation, you extract the value of the <code>view</code> attribute |
| and, provided that the view: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li>can be identified (i.e., the value is not null),</li> |
| |
| <li>does not originate from the welcome page (<code>index.jsp</code> does not |
| reside in the same location as other page views, and therefore cannot be |
| resolved using the <code>doGet</code> method's way of forwarding requests)</li> |
| </ul> |
| |
| <span class="indent">...you set it to the <code>doGet</code> method's <code>userPath</code> |
| variable, and forward the request using the method's existing <code>RequestDispatcher</code>:</span> |
| |
| <pre class="examplecode"> |
| // use RequestDispatcher to forward request internally |
| String url = "/WEB-INF/view" + userPath + ".jsp"; |
| |
| try { |
| request.getRequestDispatcher(url).forward(request, response); |
| } catch (Exception ex) { |
| ex.printStackTrace(); |
| }</pre></li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) to test it in the browser. When you navigate to the |
| category, cart or checkout pages, switch languages using the language toggle. |
| When you do so, you now remain within the same page view.</li> |
| |
| <li>In the browser, complete an order so that the application forwards you to the |
| confirmation page. When you click the language toggle from the confirmation page, |
| note that you are sent back to the website's welcome page. |
| |
| <br><br> |
| Implementation-wise, you may consider this to be sufficient. However, the Affable |
| Bean staff have explicitly asked you to remove the language toggle from this page |
| view. One way to accomplish this is to perform a test to determine whether the request |
| <em>servlet path</em> contains '<code>/confirmation</code>'. |
| |
| <br><br> |
| Switch to the <code>header.jspf</code> file in the editor and surround the language |
| toggle with the following test. You can use JSTL's functions (i.e., |
| <a href="http://download.oracle.com/docs/cd/E17802_01/products/products/jsp/jstl/1.1/docs/tlddocs/fn/tld-summary.html" target="_blank"><code>fn</code></a>) |
| library to perform string operations. |
| |
| <pre class="examplecode"> |
| <div class="headerWidget"> |
| |
| <strong><%-- If servlet path contains '/confirmation', do not display language toggle --%> |
| <c:if test="${!fn:contains(pageContext.request.servletPath,'/confirmation')}"></strong> |
| |
| <%-- language selection widget --%> |
| <c:choose> |
| |
| ... |
| </c:choose> |
| |
| <strong></c:if></strong> |
| </div></pre> |
| |
| Examine the above code snippet and note the following points: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li>The servlet path can be accessed from the <code>HttpServletRequest</code> |
| using the <a href="http://download.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#getServletPath%28%29" target="_blank"><code>getServletPath</code></a> |
| method. Because we use a <code>RequestDispatcher</code> to forward the request |
| to the confirmation page (<code>ControllerServlet</code>, line 158), the servlet |
| path becomes: |
| |
| <pre class="examplecode" style="width: 651px">/WEB-INF/view/confirmation.jsp</pre></li> |
| |
| <li>Using the <code>pageContext.request.servletPath</code> EL expression is |
| comparable to calling <code>request.getServletPath()</code> from a servlet.</li> |
| |
| <li>The <a href="http://download.oracle.com/docs/cd/E17802_01/products/products/jsp/jstl/1.1/docs/tlddocs/fn/contains.fn.html" target="_blank"><code>fn:contains()</code></a> |
| function allows you to test if an input string contains the specified substring.</li> |
| |
| <li>The <code>fn</code> tag library has already been declared for you at the top of |
| in the <code>header.jspf</code> file in snapshot 9: |
| |
| <pre class="examplecode" style="width: 651px"><%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %></pre></li> |
| </ul></li> |
| |
| <li>Run the project again and step through to the confirmation page. Note that the page |
| no longer displays the language toggle. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/language/confirmation-page.png" |
| class="margin-around b-all" style="width:688px" alt="Confirmation page displayed in browser" |
| title="Language toggle no longer displays in confirmation page"></li> |
| |
| <li>In the browser, step through to the confirmation page but switch languages once along the |
| way using the language toggle. Note that when you complete an order, the confirmation page |
| inadvertently switches back to the originally displayed language. You may rightly identify |
| the cause: upon a successfully completed order, the <code>ControllerServlet</code> destroys |
| the user session and consequently the session-scoped locale that was set using the |
| <code><fmt:setLocale></code> tag is also lost. |
| |
| <br><br> |
| To remedy this, open the <code>ControllerServlet</code> and locate the <code>invalidate()</code> |
| method which is used to destroy user sessions (approximately line 259). |
| |
| <br><br> |
| <p class="tips">Use the editor's quick search facility: press Ctrl-F (⌘-F on Mac) |
| and type in '<code>invalidate</code>'.</p></li> |
| |
| <li>Add code that extracts the session-scoped locale value prior to destroying the user session |
| and resets the request-scoped <code>language</code> attribute to the locale value after the |
| session has been destroyed. (Changes in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| // if order processed successfully send user to confirmation page |
| if (orderId != 0) { |
| |
| <strong>// in case language was set using toggle, get language choice before destroying session |
| Locale locale = (Locale) session.getAttribute("javax.servlet.jsp.jstl.fmt.locale.session"); |
| String language = ""; |
| |
| if (locale != null) { |
| |
| language = (String) locale.getLanguage(); |
| }</strong> |
| |
| // dissociate shopping cart from session |
| cart = null; |
| |
| // end session |
| session.invalidate(); |
| |
| <strong>if (!language.isEmpty()) { // if user changed language using the toggle, |
| // reset the language attribute - otherwise |
| request.setAttribute("language", language); // language will be switched on confirmation page! |
| }</strong> |
| |
| // get order details |
| Map orderMap = orderManager.getOrderDetails(orderId); |
| |
| ... |
| userPath = "/confirmation"; |
| }</pre></li> |
| |
| <li>Run the project and again, step through to the confirmation page but switch languages |
| once along the way using the language toggle. Note that when you complete an order, |
| the confirmation page now displays in the language you selected.</li> |
| </ol> |
| </div> |
| |
| <p>You have now successfully integrated language support into the <code>AffableBean</code> |
| application according to customer specification. You've factored out all text from page views, |
| placed it into resource bundles, and have applied JSTL's <code>fmt</code> tag library to |
| use resource bundle content based on the user's preferred language. You also implemented |
| a language toggle that enables users to switch between English and Czech, and override their |
| browser's default language choice. Download and examine |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot10.zip">snapshot |
| 10</a> to compare your work with the state of the project at the end of this tutorial unit.</p> |
| |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Adding Language Support">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <br> |
| <h2 id="seeAlsoLanguage">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Resources</h3> |
| |
| <ul> |
| <li><a href="../javaee-intro.html" target="_blank">Introduction to Java EE Technology</a></li> |
| <li><a href="../javaee-gettingstarted.html" target="_blank">Getting Started with Java EE Applications</a></li> |
| <li><a href="https://netbeans.org/projects/www/downloads/download/shortcuts.pdf">Keyboard Shortcuts & Code Templates Card</a></li> |
| <li><a href="../../../trails/java-ee.html" target="_blank">Java EE & Java Web Learning Trail</a></li> |
| </ul> |
| |
| <h3>External Resources</h3> |
| |
| <ul> |
| <li><a href="http://download.oracle.com/docs/cd/E17409_01/javase/tutorial/i18n/index.html" target="_blank">The Java Tutorials: Internationalization</a></li> |
| <li><a href="http://download.oracle.com/docs/cd/E17477_01/javaee/5/tutorial/doc/bnaxu.html" target="_blank">Java EE 5 Tutorial: Internationalizing and Localizing Web Applications</a></li> |
| <li><a href="http://java.sun.com/developer/technicalArticles/Intl/MultilingualJSP/index.html" target="_blank">Developing Multilingual Web Applications Using JavaServer Pages Technology</a></li> |
| <li><a href="http://java.sun.com/developer/technicalArticles/J2SE/locale/" target="_blank">Internationalization: Understanding Locale in the Java Platform</a></li> |
| <li><a href="http://java.sun.com/developer/technicalArticles/Intl/ResourceBundles/" target="_blank">Java Internationalization: Localization with ResourceBundles</a></li> |
| <li><a href="http://www.ibm.com/developerworks/java/library/j-jstl0415/" target="_blank">A JSTL primer, Part 3: Presentation is everything</a></li> |
| <li><a href="http://java.sun.com/javase/technologies/core/basic/intl/" target="_blank">Java Internationalization</a> [Technology Homepage]</li> |
| <li><a href="http://en.wikipedia.org/wiki/Internationalization_and_localization" target="_blank">Internationalization and localization</a> [Wikipedia]</li> |
| <li><a href="http://www.loc.gov/standards/iso639-2/php/code_list.php" target="_blank">ISO 639-2 Language Code List</a> [Library of Congress]</li> |
| <li><a href="http://www.w3.org/International/articlelist#language" target="_blank">W3C Internationalization Activity: Articles, best practices & tutorials: Language</a></li> |
| <li><a href="http://jquery.com/" target="_blank">jQuery</a></li> |
| </ul> |
| </div> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="security">The NetBeans E-commerce Tutorial - Securing the Application</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><strong>Securing the Application</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#examineSnapshot">Examining the Project Snapshot</a></li> |
| <li><a href="#formBased">Setting up Form-Based Authentication</a></li> |
| <li><a href="#usersGroups">Creating Users, Groups and Roles</a></li> |
| <li><a href="#secureTransport">Configuring Secure Data Transport</a></li> |
| <li><a href="#seeAlsoSecurity">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>This tutorial unit focuses on web application security. When securing web applications, |
| there are two primary concerns that need to be addressed:</p> |
| |
| <ol style="margin: 0 0 0 325px"> |
| <li>Preventing unauthorized users from gaining access to protected content.</li> |
| <li>Preventing protected content from being read while it is being transmitted.</li> |
| </ol> |
| |
| <p>The first concern, <em>access control</em>, is typically a two-step process that |
| involves (1) determining whether a user is who he or she claims to be (i.e., |
| <em>authentication</em>), and then (2) either granting or denying the user |
| access to the requested resource (i.e., <em>authorization</em>). A simple and |
| common way to implement access control for web applications is with a login |
| form that enables the server to compare user credentials with a pre-existing list |
| of authenticated users.</p> |
| |
| <p>The second concern, protecting data while it is in transit, typically involves |
| using Transport Layer Security (TLS), or its predecessor, Secure Sockets Layer |
| (SSL), in order to encrypt any data communicated between the client and server.</p> |
| |
| <p>Upon reviewing the Affable Bean staff's <a href="design.html#requirements">list of |
| requirements</a>, we'll need to secure the application in the following ways:</p> |
| |
| <ul style="margin-left: 320px"> |
| <li>Set up a login form for the administration console that enables staff |
| members access to the console's services, and blocks unauthorized users.</li> |
| |
| <li>Configure secure data transport for both the customer checkout process, and |
| for any data transmitted to and from the administration console.</li> |
| </ul> |
| |
| <p>In order to implement the above, we'll take advantage of NetBeans' visual editor |
| for the <code>web.xml</code> deployment descriptor. We'll also work in the |
| GlassFish Administration Console to configure a "user group" that |
| corresponds to Affable Bean staff members, and verify SSL support.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans |
| E-commerce Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left;"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#glassFishSecurity">GlassFish server</a></td> |
| <td class="tbltd1">v3 or Open Source Edition 3.0.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL database server</a></td> |
| <td class="tbltd1">version 5.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot10.zip">AffableBean |
| project</a></td> |
| <td class="tbltd1">snapshot 10</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><strong class="notes">Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which are |
| required for the application you build in this tutorial.</li> |
| |
| <li id="glassFishSecurity">The NetBeans IDE Java Bundle also includes the GlassFish server, |
| which you require for this tutorial. You could |
| <a href="http://glassfish.dev.java.net/public/downloadsindex.html" target="_blank">download |
| the GlassFish server independently</a>, but the version provided with the |
| NetBeans download has the added benefit of being automatically registered with |
| the IDE.</li> |
| |
| <li>You can follow this tutorial unit without having completed previous units. To |
| do so, see the <a href="#setup">setup instructions</a>, which describe how |
| to prepare the database and establish connectivity between the IDE, GlassFish, |
| and MySQL.</li> |
| |
| <li>Java EE security is an expansive topic that spans well beyond the scope of this |
| tutorial unit. In order to fully appreciate the range of implementation options |
| that are available to you, refer to the <a href="http://download.oracle.com/javaee/6/tutorial/doc/gijrp.html" |
| target="_blank">Java EE 6 Tutorial, Part VII: Security</a>. This unit provides |
| ample references to relevant sub-sections within the Java EE Tutorial.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="examineSnapshot">Examining the Project Snapshot</h2> |
| |
| <p>The beginning state of the snapshot helps to illustrate the need for security |
| in the application.</p> |
| |
| <ol style="margin-top:0"> |
| <li>Open the <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_snapshot10.zip">project |
| snapshot</a> for this tutorial unit in the IDE. Click the Open Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/open-project-btn.png" |
| alt="Open Project button"> ) button and use the wizard to navigate to the location |
| on your computer where you downloaded the project.</li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) to ensure that it is properly configured with your database |
| and application server. |
| |
| <br><br> |
| <p class="alert">If you receive an error when running the project, revisit the |
| <a href="#setup">setup instructions</a>, which describe how to prepare the |
| database and establish connectivity between the IDE, GlassFish, and MySQL.</p></li> |
| |
| <li>Test the application's functionality in your browser. This snapshot provides an |
| implementation of the administration console, as specified in the |
| <a href="design.html#requirements">customer requirements</a>. To examine the |
| administration console, enter the following URL in your browser: |
| |
| <pre class="examplecode">http://localhost:8080/AffableBean<strong>/admin/</strong></pre> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/admin-console.png" |
| class="margin-around b-all" style="width:688px" alt="AffableBean administration console displayed in a browser" |
| title="Append the application's default URL with '/admin' to view the administration console in a browser"> |
| |
| <br> |
| The administration console enables you to view all customers and orders contained |
| in the database. When you click either of the links in the left panel, the page will |
| update to display a table listing customers or orders, depending on your choice. (The |
| 'log out' link currently does not "log out" an authenticated user.) |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> The customers and orders that you see displayed |
| in the administration console are dependent on the data stored in your database. You can |
| create new records by stepping through the checkout process in the website. Alternatively, |
| you can run the <a href="https://netbeans.org/project_downloads/samples/Samples/JavaEE/ecommerce/affablebean_sample_data.sql">affablebean_sample_data.sql</a> |
| script on your <code>affablebean</code> database to have your data correspond to the |
| records displayed in the following screenshots. (If you need help with this task, refer |
| to step 2 in the <a href="#setup">setup instructions</a>.)</p> |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/admin-console-customers.png" |
| class="margin-around b-all" style="width:688px" alt="AffableBean administration console displaying all customer records" |
| title="Click the 'view all customers' link to view all customer records in a table"> |
| |
| <br> |
| You can view details for each customer record by hovering your mouse and selecting an individual |
| record. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/customer-selected.png" |
| class="margin-around b-all" alt="Customer record selected in administration console" |
| title="Hover your mouse over a customer record and click to view customer details"> |
| |
| <br> |
| Likewise, you can view an order summary for each customer either by selecting an order from the |
| administration console's "orders" table, or by clicking the "view order summary" |
| link in a "customer details" display. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/view-order-summary.png" |
| class="margin-around" alt="'view order summary' link being hovered over in a 'customer details' view" |
| title="Click 'view order summary' from a customer details display in order to view a customer's order details"> |
| |
| <br> |
| Naturally, none of this information should be available to an anonymous site visitor. In the |
| coming steps, you'll create login and error pages, so that when an unauthenticated user attempts |
| to access the administration console, he or she will be directed to the login page. Upon successful |
| login, the user is then redirected to the administration console's menu; upon login failure, the |
| error page is displayed.</li> |
| |
| <li id="adminConsole">Examine the project snapshot in the Projects window. |
| |
| <table> |
| <tr> |
| <td> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/projects-window.png" |
| class="margin-around b-all" alt="Projects window displaying resources for administration console" |
| title="The AdminServlet forwards requests to resources within the web/admin folder"></td> |
| |
| <td class="valign-top"> |
| |
| <p style="margin: 20px 0 0 5px">This implementation of the administration console |
| primarily relies on the following project resources: |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>An <strong><code>admin</code></strong> directory within the project's webroot, |
| which contains all page view files.</li> |
| |
| <li>An <strong><code>AdminServlet</code></strong>, contained in the <code>controller</code> |
| package, which forwards requests to page views within the <code>admin</code> |
| directory.</li> |
| </ul> |
| |
| <p style="margin: 20px 0 0 5px">Also, the following files have been modified from the previous snapshot:</p> |
| |
| <ul style="margin: 10px 0 0 -.7em"> |
| <li><strong><code>WEB-INF/web.xml</code>:</strong> Contains a new <code><jsp-property-group></code> |
| that includes the header and footer fragments for page views contained in the <code>admin</code> |
| directory.</li> |
| |
| <li><strong><code>css/affablebean.css</code>:</strong> Includes new style definitions for |
| elements in the administration console</li> |
| </ul> |
| |
| <p style="margin-left:5px">If you have been following the NetBeans E-commerce Tutorial |
| sequentially, you'll find that there is nothing contained in the implementation for |
| the administration console which hasn't already been covered in previous units. |
| Essentially, the <code>AdminServlet</code> processes requests from the <code>admin/index.jsp</code> |
| page, EJBs and entity classes are employed to retrieve information from the database, |
| and the information is then forwarded back to the <code>admin/index.jsp</code> page |
| to be displayed.</p> |
| </td> |
| </tr> |
| </table> |
| </li> |
| |
| <li style="margin-top:-10px">In the browser, return to the customer website by clicking the Affable Bean |
| logo in the upper left corner of the web page. Step through the entire <a href="design.html#business">business |
| process flow</a> of the application and note that the checkout process is handled over a non-secure channel. |
| |
| <br><br> |
| When customers reach the checkout page, they are expected to submit sensitive personal information |
| in order to complete their orders. Part of your task in this tutorial unit is to ensure that this |
| data is sent over a secure channel. Because the administration console also enables authenticated |
| users to view customers' personal information, it too needs to be configured so that data is sent |
| over the Internet securely.</li> |
| </ol> |
| |
| |
| <br> |
| <h2 id="formBased">Setting up Form-Based Authentication</h2> |
| |
| <p>In this section, you set up <em>form-based authentication</em> for the <code>AffableBean</code> |
| administration console. Form-based authentication enables the server to authenticate users based |
| on the credentials they enter into a login form. With these credentials, the server is able to |
| make a decision on whether to grant the user access to protected resources. In order to implement |
| this, you'll create login and error pages, and will rely on <em>declarative security</em> by |
| entering security settings in the application's <code>web.xml</code> deployment descriptor.</p> |
| |
| <p>Before you begin implementing a form-based authentication mechanism for the <code>AffableBean</code> |
| application, the following background information is provided to help clarify the security terms |
| relevant to our scenario.</p> |
| |
| <ul> |
| <li><a href="#declarativeSecurity">Declarative and Programmatic Security</a></li> |
| <li><a href="#authenticationMech">Choosing an Authentication Mechanism</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="declarativeSecurity">Declarative and Programmatic Security</h3> |
| |
| <p>With <em>declarative security</em>, you specify all security settings for your |
| application, including authentication requirements, access control, and security |
| roles, using annotations and/or deployment descriptors. In other words, the security |
| for your application is in a form that is external to the application, and relies |
| on the mechanisms provided by the Java EE container for its management.</p> |
| |
| <p>With <em>programmatic security</em>, your classes, entities, servlets, and page views |
| manage security themselves. In this case, security logic is integrated directly |
| into your application, and is used to handle authentication and authorization, and |
| ensure that data is sent over a secure network protocol when necessary.</p> |
| |
| <p>For the <code>AffableBean</code> application, we'll use declarative security by |
| declaring all security information in the <code>web.xml</code> deployment descriptor.</p> |
| |
| <p class="tips">For more information on declarative and programmatic security types, |
| see the <a href="http://download.oracle.com/javaee/6/tutorial/doc/bncat.html" |
| target="_blank">Java EE 6 Tutorial: Overview of Web Application Security</a>.</p> |
| |
| |
| <h3 id="authenticationMech">Choosing an Authentication Mechanism</h3> |
| |
| <p>An <em>authentication mechanism</em> is used to determine how a user gains access to |
| restricted content. The Java EE platform supports various authentication mechanisms, |
| such as <em>HTTP basic authentication</em>, <em>form-based authentication</em>, and |
| <em>client authentication</em>. The authentication mechanism behind our login form |
| will be <em>form-based authentication</em>. You'll learn what form-based authentication |
| is when you begin <a href="#loginForm">setting up the login form</a> for the |
| <code>AffableBean</code> administration console below.</p> |
| |
| <p class="tips">See the Java EE 6 Tutorial: |
| <a href="http://download.oracle.com/javaee/6/tutorial/doc/gkbaa.html#gkbsa" |
| target="_blank">Specifying Authentication Mechanisms</a> for further information.</p> |
| </div> |
| |
| <br> |
| <p>Form-based authentication has the advantage of enabling the developer to design the |
| appearance of the login form so that it better suits the application which it belongs to. |
| Our implementation for the form-based authentication mechanism can be divided into two |
| steps. Begin by creating page views for the required login form and error message. Then |
| add entries to the <code>web.xml</code> deployment descriptor to inform the servlet |
| container that the application requires form-based authentication for access to the |
| resources that comprise the administration console.</p> |
| |
| <ol style="margin: 0 0 0 -.7em"> |
| <li><a href="#createPages">Create Pages for Login and Login Failure</a></li> |
| <li><a href="#addSecurity">Add Security Entries to the Deployment Descriptor</a></li> |
| </ol> |
| |
| <div class="indent"> |
| <h3 id="createPages">Create Pages for Login and Login Failure</h3> |
| |
| <p>In form-based authentication, the process of authentication and authorization is |
| shown in the following four steps:</p> |
| |
| <ol style="margin: 0 0 0 -.7em"> |
| <li>The client sends a request to the server for a protected resource.</li> |
| |
| <li>The server recognizes that a protected resource has been requested, and returns |
| the login page to the client.</li> |
| |
| <li>The client sends username and password credentials using the provided form.</li> |
| |
| <li>The server processes the credentials, and if an authorized user is identified |
| the protected resource is returned, otherwise the error page is returned.</li> |
| </ol> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/form-based-authentication.png" |
| class="margin-around" |
| alt="Diagram depicting process flow of form-based authentication" |
| title="Authentication and authorization take place in a four-step process using form-based authentication"> |
| |
| <p class="tips">For more information on form-based authentication, see the Java EE 6 Tutorial: |
| <a href="http://download.oracle.com/javaee/6/tutorial/doc/gkbaa.html#bncbq" target="_blank">Form-Based |
| Authentication</a>.</p> |
| |
| <br> |
| <p id="template">The <code>j_security_check</code> keyword represents the destination in |
| the servlet container that handles authentication and authorization. When implementing |
| the HTML login form, you apply it as the value for the form's <code>action</code> attribute. |
| You also apply the "<code>j_username</code>" and "<code>j_password</code>" |
| keywords, as in the following template:</p> |
| |
| <pre class="examplecode"> |
| <form action="<strong>j_security_check</strong>" method=post> |
| |
| <p>username: <input type="text" name="<strong>j_username</strong>"></p> |
| |
| <p>password: <input type="password" name="<strong>j_password</strong>"></p> |
| |
| <p><input type="submit" value="submit"></p> |
| </form></pre> |
| |
| <br> |
| <p>Perform the following steps.</p> |
| |
| <ol style="margin-top: 0"> |
| <li>In the Projects window, right-click the <code>admin</code> folder node and choose New > JSP.</li> |
| |
| <li>Name the file <code>login</code>, then click Finish. The new <code>login.jsp</code> file is created |
| and opens in the editor.</li> |
| |
| <li>Repeat the previous two steps to create a new <code>error.jsp</code> file. In the New JSP wizard, |
| name the file <code>error</code>. When you finish, you'll have two new files listed in the Projects |
| window. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/projects-window-jsp.png" |
| class="margin-around b-all" alt="New login and error JSP files displayed in Projects window" |
| title="New JSP file nodes displayed in Projects window"></li> |
| |
| <li>Open the project's web deployment descriptor. Press Alt-Shift-O (Ctrl-Shift-O on Mac) |
| and in the Go to File dialog, type '<code>web</code>', then click OK. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/go-to-file.png" |
| class="margin-around b-all" alt="Go to File dialog" |
| title="Use the Go to File dialog to quickly open files in the editor"></li> |
| |
| <li>In the editor, scroll to the bottom of the <code>web.xml</code> file and note the |
| <code><jsp-property-group></code> entry created for JSP pages in the administration |
| console. Add the new login and error JSP pages as <code><url-pattern></code> |
| entries. (Changes in <strong>bold</strong>.) |
| |
| <pre class="examplecode"> |
| <jsp-property-group> |
| <description>JSP configuration for the admin console</description> |
| <url-pattern>/admin/index.jsp</url-pattern> |
| <strong><url-pattern>/admin/login.jsp</url-pattern> |
| <url-pattern>/admin/error.jsp</url-pattern></strong> |
| <include-prelude>/admin/jspf/header.jspf</include-prelude> |
| <include-coda>/admin/jspf/footer.jspf</include-coda> |
| </jsp-property-group></pre> |
| |
| This step ensures that when these two pages are returned to a client, they |
| will be prepended and appended with the defined <code>header.jspf</code> and |
| <code>footer.jspf</code> fragments, respectively. |
| |
| <br><br> |
| <p class="tips">You can equally configure the <code><jsp-property-group></code> |
| entry from the <code>web.xml</code>'s visual editor. Click the Pages tab along |
| the top of the editor, and enter the URL patterns into the respective JSP |
| Property Group.</p></li> |
| |
| <li>Press Ctrl-Tab to switch to the <code>login.jsp</code> file in the editor. |
| Delete the entire template contents for the file, then enter the following |
| HTML form. |
| |
| <pre class="examplecode"> |
| <form action="<strong>j_security_check</strong>" method=post> |
| <div id="loginBox"> |
| <p><strong>username:</strong> |
| <input type="text" size="20" name="<strong>j_username</strong>"></p> |
| |
| <p><strong>password:</strong> |
| <input type="password" size="20" name="<strong>j_password</strong>"></p> |
| |
| <p><input type="submit" value="submit"></p> |
| </div> |
| </form></pre> |
| |
| Note that the HTML form is based on the <a href="#template">template provided above</a>. |
| Here, you use the "<code>j_security_check</code>" keyword as the value for the |
| form's <code>action</code> attribute, and the "<code>j_username</code>" and |
| "<code>j_password</code>" keywords as the values for the <code>name</code> |
| attribute of the username and password text fields. The style of the form is implemented |
| by encapsulating the form widgets within a <code><div></code> element, then defining |
| a set of rules for the <code>loginBox</code> ID in <code>affablebean.css</code>.</li> |
| |
| <li>Press Ctrl-Tab and switch to the <code>error.jsp</code> file in the editor. Delete the |
| entire template contents for the file, then enter the following. |
| |
| <pre class="examplecode"> |
| <div id="loginBox"> |
| |
| <p class="error">Invalid username or password.</p> |
| |
| <p>Return to <strong><a href="login.jsp">admin login</a></strong>.</p> |
| |
| </div></pre> |
| |
| The above content includes a simple message indicating that login has failed, and |
| provides a link that allows the user to return to the login form.</li> |
| </ol> |
| |
| <h3 id="addSecurity">Add Security Entries to the Deployment Descriptor</h3> |
| |
| <p>In order to instruct the servlet container that form-based authentication is to be |
| used, you add entries to the <code>web.xml</code> deployment descriptor. This is |
| essentially a three-step process, which can be followed by specifying settings under |
| the three headings in the <code>web.xml</code> file's Security tab. These are: (1) |
| Login Configuration, (2) Security Roles, and (3) Security Constraints.</p> |
| |
| <ol> |
| <li>Open the project's <code>web.xml</code> file in the editor. (If it is already opened, |
| you can press Ctrl-Tab and select it.)</li> |
| |
| <li>Click the Security tab along the top of the editor. The IDE's visual editor enables |
| you to specify security settings under the Security tab.</li> |
| |
| <li>Expand the Login Configuration heading, select Form, then enter the following |
| details: |
| |
| <ul style="margin: 10px 0 0 -.7em"> |
| <li><strong>Form Login Page:</strong> <code>/admin/login.jsp</code></li> |
| <li><strong>Form Error Page:</strong> <code>/admin/error.jsp</code></li> |
| <li><strong>Realm Name:</strong> <code>file</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/login-configuration.png" |
| class="margin-around b-all" style="width:688px" |
| alt="Visual editor for web.xml - Security tab" |
| title="Specify security settings for the application using the IDE's web.xml visual editor"></li> |
| |
| <li>Click the XML tab along the top of the editor and verify the changes made to |
| the deployment descriptor. The following entry has been added to the bottom of |
| the file: |
| |
| <pre class="examplecode"> |
| <login-config> |
| <auth-method>FORM</auth-method> |
| <realm-name>file</realm-name> |
| <form-login-config> |
| <form-login-page>/admin/login.jsp</form-login-page> |
| <form-error-page>/admin/error.jsp</form-error-page> |
| </form-login-config> |
| </login-config></pre> |
| |
| This entry informs the servlet container that form-based authentication is used, |
| the realm named <code>file</code> should be checked for user credentials, and specifies |
| the whereabouts of the login and error pages.</li> |
| |
| <li id="securityRole">Click the Security tab again, then expand the Security Roles heading |
| and click Add.</li> |
| |
| <li>In the Add Security Role dialog, type in <code>affableBeanAdmin</code> for the role |
| name, then click OK. The new role entry is added beneath Security Roles.</li> |
| |
| <li>Click the XML tab to examine how the file has been affected. Note that the following |
| entry has been added: |
| |
| <pre class="examplecode"> |
| <security-role> |
| <description/> |
| <role-name>affableBeanAdmin</role-name> |
| </security-role></pre> |
| |
| Here we've specified the name of a security role used with the application. We'll |
| need to associate this role with the protected resources that define the administration |
| console (under the Security Constraints heading below), and later we'll |
| <a href="#defineRoles">create this role on the GlassFish server</a>.</li> |
| |
| <li>Click the Security tab again, then click the Add Security Constraint button.</li> |
| |
| <li>Type in <code>Admin</code> for the Display Name, then under Web Resource Collection |
| click the Add button. Enter the following details, then when you are finished, click OK. |
| |
| <ul style="margin: 10px 0 0 -.7em"> |
| <li><strong>Resource Name:</strong> <code>Affable Bean Administration</code></li> |
| <li><strong>URL Pattern(s):</strong> <code>/admin/*</code></li> |
| <li><strong>HTTP Method(s):</strong> <code>All HTTP Methods</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/add-web-resource.png" |
| class="margin-around b-all" alt="Add Web Resource dialog" |
| title="Specify which resources need to be protected using the Add Web Resource dialog"></li> |
| |
| <li id="enableAuthConstraint">Under the new Admin security constraint, select the Enable |
| Authentication Constraint option and click the Edit button next to the Role Name(s) |
| text field.</li> |
| |
| <li>In the dialog that displays, select the <code>affableBeanAdmin</code> role in the |
| left column, then click Add. The role is moved to the right column. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/edit-role-names.png" |
| class="margin-around b-all" alt="Edit Role Names dialog" |
| title="Specify roles to be associated with an authentication constraint"></li> |
| |
| <li>Click OK. The role is added to the Role Name(s) text field. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/security-tab.png" |
| class="margin-around b-all" style="width:688px" alt="Visual editor for web.xml - Security tab" |
| title="Security constraints include specifying the web resource collection, and role(s) that are granted access to the collection"></li> |
| |
| <li>Click the XML tab to examine how the file has been affected. Note that the following |
| entry has been added: |
| |
| <pre class="examplecode"> |
| <security-constraint> |
| <display-name>Admin</display-name> |
| <web-resource-collection> |
| <web-resource-name>Affable Bean Administration</web-resource-name> |
| <description/> |
| <url-pattern>/admin/*</url-pattern> |
| </web-resource-collection> |
| <auth-constraint> |
| <description/> |
| <role-name>affableBeanAdmin</role-name> |
| </auth-constraint> |
| </security-constraint></pre> |
| |
| In these previous six steps, you've created a security constraint that specifies which |
| resources need to be protected, and identifies the role(s) that are granted access to them. |
| Since the administration console implementation is essentially everything contained |
| within the application's <code>admin</code> folder, you use a wildcard (<code>*</code>). |
| Although you've specified that all HTTP methods should be protected, you could have |
| equally selected just GET and POST, since these are the only two that are handled by |
| the <code>AdminServlet</code>. As previously mentioned, the <code>affableBeanAdmin</code> |
| role that we declared still needs to be created on the GlassFish server.</li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) to examine how the application now handles access to the |
| administration console.</li> |
| |
| <li>When the application opens in the browser, attempt to access the administration console |
| by entering the following URL into the browser's address bar: |
| |
| <pre class="examplecode">http://localhost:8080/AffableBean<strong>/admin/</strong></pre> |
| |
| When you attempt to access the administration console, the login page is now presented. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/login-form.png" |
| class="margin-around b-all" style="width:688px" alt="Browser display of login page" |
| title="Unauthenticated attempts to access the administration console are redirected to the login page"></li> |
| |
| <li>Click the 'submit' button to attempt login. You see the error page displayed. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/error-page.png" |
| class="margin-around b-all" style="width:688px" alt="Browser display of error page" |
| title="Error page is displayed when the server is unable to authenticate a user"> |
| </li> |
| </ol> |
| </div> |
| |
| |
| <br> |
| <h2 id="usersGroups">Setting up Users, Groups and Roles</h2> |
| |
| <p>Much of our security implementation is dependent on configuration between the application |
| and the GlassFish server we are using. This involves setting up <em>users</em>, <em>groups</em>, |
| and <em>roles</em> between the two, and using one of the preconfigured security policy |
| domains, or <em>realms</em>, on the server. Start by reading some background information |
| relevant to our scenario, then proceed by configuring users, groups and roles between |
| the application and the GlassFish server.</p> |
| |
| <ul> |
| <li><a href="#understandUsers">Understanding Users, Groups, and Roles</a></li> |
| <li><a href="#understandRealms">Understanding Realms on the GlassFish Server</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="understandUsers">Understanding Users, Groups, and Roles</h3> |
| |
| <p>A <em>user</em> is a unique identity recognized by the server. You define users on the |
| server so that it can be able to determine who should have access to protected resources. |
| You can optionally cluster users together into a <em>group</em>, which can be understood |
| as a set of authenticated users. In order to specify which users and/or groups have access |
| to protected resources, you create <em>roles</em>. As stated in the Java EE 6 Tutorial,</p> |
| |
| <blockquote style="margin-top: 0"> |
| <em>A role is an abstract name for the permission to access a particular set of resources |
| in an application. A role can be compared to a key that can open a lock. Many people |
| might have a copy of the key. The lock doesn’t care who you are, only that you have |
| the right key.</em> |
| </blockquote> |
| |
| <p>The role that a user or group is assigned to is what specifically allows the server to |
| determine whether protected resources can be accessed. Users and groups can be assigned |
| to multiple roles. As will be demonstrated below, you accomplish this by defining the |
| role in the application, then mapping it to users and groups on the server. </p> |
| |
| <p>The relationship between users, groups, and roles, and the process in which you establish |
| them in the application and on the server, is presented in the following diagram.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/groups-users-roles.png" |
| id="usersRolesGroupsDiagram" class="margin-around" |
| alt="Diagram depicting relationship of users, groups and roles between the application and server" |
| title="Users, groups, and roles need to be set up and mapped between the application and server"> |
| |
| <p class="tips">For more information on groups, users, and roles, see |
| <a href="http://download.oracle.com/javaee/6/tutorial/doc/bnbxj.html" target="_blank">Working |
| with Realms, Users, Groups, and Roles</a> in the Java EE 6 Tutorial.</p> |
| |
| |
| <h3 id="understandRealms">Understanding Realms on the GlassFish Server</h3> |
| |
| <p>When you define users and groups on the server, you do so by entering details into |
| a security policy domain, otherwise known as a <em>realm</em>. A realm protects user |
| credentials (e.g., user names and passwords) through an authentication scheme. For |
| example, user credentials can be stored in a local text file, or maintained in a |
| certificate database.</p> |
| |
| <p>The GlassFish server provides three preconfigured realms by default. These are the |
| <code>file</code>, <code>admin-realm</code>, and <code>certificate</code> realms. |
| Briefly, the <code>file</code> realm stores user credentials in a local text file |
| named <code>keyfile</code>. The <code>admin-realm</code> also stores credentials |
| in a local text file, and is reserved for server administrator users. The |
| <code>certificate</code> realm, the server stores user credentials in a certificate |
| database.</p> |
| |
| <p>When defining users, groups and roles for the <code>AffableBean</code> administration |
| console, we'll use the server's preconfigured <code>file</code> realm.</p> |
| </div> |
| |
| <br> |
| <p>In order to set up users, groups and roles to satisfy the form-based authentication |
| mechanism we've created, perform the following three steps corresponding to the |
| <a href="#usersRolesGroupsDiagram">diagram above</a>.</p> |
| |
| <ol style="margin: 0 0 0 -.7em"> |
| <li><a href="#createUsers">Create Users and/or Groups on the Server</a></li> |
| <li><a href="#defineRoles">Define Roles in the Application</a></li> |
| <li><a href="#mapApplication">Map Roles to Users and/or Groups</a></li> |
| </ol> |
| |
| <div class="indent"> |
| <h3 id="createUsers">Create Users and/or Groups on the Server</h3> |
| |
| <p>In this step, we'll use the GlassFish Administration Console to create a user named |
| <code>nbuser</code> within the preexisting <code>file</code> security realm. We'll |
| also assign the new <code>nbuser</code> to a <em>group</em> that we'll create called |
| <code>affableBeanAdmin</code>.</p> |
| |
| <ol> |
| <li>Open the Services window (Ctrl-5; ⌘-5 on Mac) and expand the Servers node |
| so that the GlassFish server node is visible.</li> |
| |
| <li>Ensure that the GlassFish server is running. If the server is running, a small green |
| arrow is displayed next to the GlassFish icon ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/gf-server-running-node.png" |
| alt="GlassFish server node in Services window"> ). If you need to start it, right-click |
| the server node and choose Start.</li> |
| |
| <li>Right-click the GlassFish server node and choose View Admin Console. The login form |
| for the GlassFish Administration Console opens in a browser.</li> |
| |
| <li>Log into the Administration Console by typing <code>admin</code> / <code>adminadmin</code> |
| for the username / password.</li> |
| |
| <li>In the Tree which displays in the left column of the Administration Console, expand |
| the Configuration > Security > Realms nodes, then click the <code>file</code> realm. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/file-realm.png" |
| class="margin-around b-all" alt="Tree displayed in GlassFish Administration Console" |
| title="Expand the Configuration > Security > Realms nodes to view existing security realms"></li> |
| |
| <li>In the main panel of the GlassFish Administration Console, under Edit Realm, click |
| the Manage Users button.</li> |
| |
| <li>Under File Users, click the New button.</li> |
| |
| <li>Under New File Realm User, enter the following details: |
| |
| <ul style="margin: 10px 0 0 -.7em"> |
| <li><strong>User ID:</strong> <code>nbuser</code></li> |
| <li><strong>Group List:</strong> <code>affableBeanAdmin</code></li> |
| <li><strong>New Password:</strong> <code>secret</code></li> |
| <li><strong>Confirm New Password:</strong> <code>secret</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/new-file-realm-user.png" |
| class="margin-around b-all" alt="New File Realm User panel in GlassFish Administration Console" |
| title="Enter new user and group details in the New File Realm User panel"> |
| |
| <br> |
| Here, we are creating a user for the <code>file</code> security realm, which |
| we've randomly named <code>nbuser</code>. We have also assigned the new user |
| to a randomly named <code>affableBeanAdmin</code> group. Remember the <code>secret</code> |
| password you set, as you will require it to later log into the <code>AffableBean</code> |
| administration console.</li> |
| |
| <li>Click OK. The new <code>nbuser</code> user is now listed under File Users in the |
| GlassFish Administration Console. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/nbuser-file-realm.png" |
| class="margin-around b-all" alt="File Users panel displaying newly created user and group" |
| title="All users and groups pertaining to the 'file' realm are displayed under File Users"> |
| |
| <br> |
| Optionally close the browser window for the GlassFish Administration Console, or |
| leave it open for the time being. You will need to return to the Administration Console |
| in the <a href="#mapApplication">Map Roles to Users and/or Groups</a> step below. |
| </li> |
| </ol> |
| |
| |
| <h3 id="defineRoles">Define Roles in the Application</h3> |
| |
| <p>By "defining roles in the application," you specify which roles have access |
| to EJB session beans, servlets, and/or specific methods that they contain. You can accomplish this |
| declaratively by creating entries in the deployment descriptor, or using annotations. |
| For the <code>AffableBean</code> administration console, we've actually already |
| completed this step when we <a href="#enableAuthConstraint">added the <code>affableBeanAdmin</code> |
| role to the security constraint</a> that we created when implementing form-based |
| authentication. However, in more complicated scenarios you may have multiple roles, |
| each with varying degrees of access. In such cases, implementation requires a more |
| fine-grained access control.</p> |
| |
| <p>The Java EE 6 API includes various security annotations that you can use in place of the |
| XML entries you add to deployment descriptors. The availability of annotations primarily |
| aims to offer ease of development and flexibility when coding. One common method is to use |
| annotations within classes, but override them when necessary using deployment descriptors.</p> |
| |
| <ul> |
| <li><a href="#secureServlet">Using Security Annotations in Servlets</a></li> |
| <li><a href="#secureEJB">Using Security Annotations in EJBs</a></li> |
| </ul> |
| |
| |
| <h4 id="secureServlet">Using Security Annotations in Servlets</h4> |
| |
| <p>The following table lists some of the annotations available to you when applying roles |
| to servlets.</p> |
| |
| <div class="indent"> |
| <table style="width:722px"> |
| <tbody> |
| <tr> |
| <th class="tblheader" colspan="3">Servlet 3.0 Security Annotations (specified in <a href="http://www.jcp.org/en/jsr/detail?id=315" target="_blank">JSR 315</a>)</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code><a href="http://download.oracle.com/javaee/6/api/javax/servlet/annotation/ServletSecurity.html" target="_blank">@ServletSecurity</a></code></td> |
| <td class="tbltd1">Used to specify security constraints to be enforced by a Servlet container on HTTP protocol messages.</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code><a href="http://download.oracle.com/javaee/6/api/javax/servlet/annotation/HttpConstraint.html" target="_blank">@HttpConstraint</a></code></td> |
| <td class="tbltd1">Used within the <code>ServletSecurity</code> annotation to represent the security constraints to be applied to all HTTP protocol methods.</td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <br> |
| <p>If we wanted to apply the Servlet 3.0 annotations to declare the <code>affableBeanAdmin</code> role |
| on the <code>AdminServlet</code>, we could do so as follows. (Changes in <strong>bold</strong>.)</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="margin-top:0; width:700px"> |
| @WebServlet(name = "AdminServlet", |
| urlPatterns = {"/admin/", |
| "/admin/viewOrders", |
| "/admin/viewCustomers", |
| "/admin/customerRecord", |
| "/admin/orderRecord", |
| "/admin/logout"}) |
| <strong>@ServletSecurity( @HttpConstraint(rolesAllowed = {"affableBeanAdmin"}) )</strong> |
| public class AdminServlet extends HttpServlet { ... }</pre></div> |
| |
| <p>In this case, we could then remove the corresponding entry in the <code>web.xml</code> |
| deployment descriptor. (Removed content displayed as <strike><strong>strike-through</strong></strike> text.)</p> |
| |
| <div class="indent"> |
| <pre class="examplecode" style="margin-top:0; width:700px"> |
| <login-config> |
| <auth-method>FORM</auth-method> |
| <realm-name>file</realm-name> |
| <form-login-config> |
| <form-login-page>/admin/login.jsp</form-login-page> |
| <form-error-page>/admin/error.jsp</form-error-page> |
| </form-login-config> |
| </login-config> |
| |
| <strike><strong><security-constraint></strong></strike> |
| <strike><strong><display-name>Admin</display-name></strong></strike> |
| <strike><strong><web-resource-collection></strong></strike> |
| <strike><strong><web-resource-name>Affable Bean Administration</web-resource-name></strong></strike> |
| <strike><strong><description/></strong></strike> |
| <strike><strong><url-pattern>/admin/*</url-pattern></strong></strike> |
| <strike><strong></web-resource-collection></strong></strike> |
| <strike><strong><auth-constraint></strong></strike> |
| <strike><strong><description/></strong></strike> |
| <strike><strong><role-name>affableBeanAdmin</role-name></strong></strike> |
| <strike><strong></auth-constraint></strong></strike> |
| <strike><strong></security-constraint></strong></strike> |
| |
| <strike><strong><security-role></strong></strike> |
| <strike><strong><description/></strong></strike> |
| <strike><strong><role-name>affableBeanAdmin</role-name></strong></strike> |
| <strike><strong></security-role></strong></strike></pre></div> |
| |
| |
| <h4 id="secureEJB">Using Security Annotations in EJBs</h4> |
| |
| <p>The following table lists some of the annotations available to you when applying roles to EJBs.</p> |
| |
| <div class="indent"> |
| <table style="width:722px"> |
| <tbody> |
| <tr> |
| <th class="tblheader" colspan="3">EJB Security Annotations (specified in <a href="http://www.jcp.org/en/jsr/detail?id=250" target="_blank">JSR 250</a>)</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code><a href="http://download.oracle.com/javaee/6/api/javax/annotation/security/DeclareRoles.html" target="_blank">@DeclareRoles</a></code></td> |
| <td class="tbltd1">Used by application to declare roles. It can be specified on a class.</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code><a href="http://download.oracle.com/javaee/6/api/javax/annotation/security/RolesAllowed.html" target="_blank">@RolesAllowed</a></code></td> |
| <td class="tbltd1">Specifies the list of roles permitted to access method(s) in an application.</td> |
| </tr> |
| </tbody> |
| </table> |
| </div> |
| |
| <br> |
| <p>To demonstrate the use of EJB security annotations, we'll apply the <code>@RolesAllowed</code> |
| annotation to a method that should only be called when a user has been identified as belonging |
| to the <code>affableBeanAdmin</code> role.</p> |
| |
| <ol> |
| <li>Reexamine the <a href="#adminConsole">snapshot implementation for the <code>AffableBean</code> |
| administration console</a>. Note that in the <code>CustomerOrderFacade</code> session bean, |
| a new <code>findByCustomer</code> method enables the <code>AdminServlet</code> to access a |
| specified <code>Customer</code>.</li> |
| |
| <li>Open the <code>CustomerOrderFacade</code> bean in the editor, then add the <code>@RolesAllowed</code> |
| annotation to the <code>findByCustomer</code> method. |
| |
| <pre class="examplecode" style="width:680px"> |
| <strong>@RolesAllowed("affableBeanAdmin")</strong> |
| public CustomerOrder findByCustomer(Object customer) { ... }</pre></li> |
| |
| <li>Press Ctrl-Shift-I (⌘-Shift-I on Mac) to fix imports. An import statement |
| for <code>javax.annotation.security.RolesAllowed</code> is added to the top of |
| the class. |
| |
| <br><br> |
| The <code>findByCustomer</code> method is only called by the <code>AdminServlet</code>, |
| which is previously authenticated into the <code>affableBeanAdmin</code> role using |
| our implementation of form-based authentication. The use of the <code>@RolesAllowed</code> |
| annotation here is not strictly necessary - its application simply guarantees that the |
| method can only be called by a user who has been authenticated in the <code>affableBeanAdmin</code> |
| role.</li> |
| </ol> |
| |
| |
| <h3 id="mapApplication">Map Roles to Users and/or Groups</h3> |
| |
| <p>We have so far accomplished the following:</p> |
| |
| <ul> |
| <li>Defined the <code>affableBeanAdmin</code> role for our form-based authentication |
| mechanism (either in the <code>web.xml</code> deployment descriptor, or as an |
| annotation in the <code>AdminServlet</code>).</li> |
| |
| <li>Created a user named <code>nbuser</code> on the GlassFish server, and associated |
| it with a group named <code>affableBeanAdmin</code>.</li> |
| </ul> |
| |
| <p>It is no coincidence that the group and role names are the same. While it is not |
| necessary that these names be identical, this makes sense if we are only creating |
| one-to-one matching between roles and groups. In more complicated scenarios, you |
| can map users and groups to multiple roles providing access to different resources. |
| In such cases, you would give unique names to groups and roles.</p> |
| |
| <p>In order to map the <code>affableBeanAdmin</code> role to the <code>affableBeanAdmin</code> |
| group, you have a choice of performing one of two actions. You can either create a |
| <code><security-role-mapping></code> entry in GlassFish' <code>sun-web.xml</code> |
| deployment descriptor. (In the Projects window, <code>sun-web.xml</code> is located |
| within the project's Configuration Files). This would look as follows:</p> |
| |
| |
| <div class="indent"> |
| <pre class="examplecode" style="margin-top:0; width:700px"> |
| <security-role-mapping> |
| <role-name>affableBeanAdmin</role-name> |
| <group-name>affableBeanAdmin</group-name> |
| </security-role-mapping></pre> |
| </div> |
| |
| <p>This action explicitly maps the <code>affableBeanAdmin</code> role to the |
| <code>affableBeanAdmin</code> group. Otherwise, you can enable GlassFish' Default |
| Principal To Role Mapping service so that roles are automatically assigned to groups |
| of the same name.</p> |
| |
| <p>The following steps demonstrate how to enable the Default Principal To Role Mapping |
| service in the GlassFish Administration Console.</p> |
| |
| <ol style="margin-top: 0"> |
| <li>Open the Services window (Ctrl-5; ⌘-5 on Mac) and expand the Servers node |
| so that the GlassFish server node is visible.</li> |
| |
| <li>Ensure that the GlassFish server is running. If the server is running, a small green |
| arrow is displayed next to the GlassFish icon ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/gf-server-running-node.png" |
| alt="GlassFish server node in Services window"> ). If you need to start it, right-click |
| the server node and choose Start.</li> |
| |
| <li>Right-click the GlassFish server node and choose View Admin Console. The login form |
| for the GlassFish Administration Console opens in a browser.</li> |
| |
| <li>Log into the Administration Console by typing <code>admin</code> / <code>adminadmin</code> |
| for the username / password.</li> |
| |
| <li>In the Tree which displays in the left column of the Administration Console, expand |
| the Configuration node, then click the Security node.</li> |
| |
| <li>In the main panel of the Administration Console, select the Default Principal To Role |
| Mapping option. |
| |
| <br> |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/security/gf-admin-console-security.png" rel="lytebox" |
| title="With the Default Principal To Role Mapping option enabled, roles and groups of the same name are automatically mapped" |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/gf-admin-console-security.png" |
| class="margin-around b-all" style="width: 688px" title="Click to enlarge" alt="GlassFish Administration Console - Security panel"> |
| </a> |
| |
| <br> |
| <p class="tips">The Java EE 6 Tutorial defines the term <em>principal</em> as, "An |
| entity that can be authenticated by an authentication protocol in a security service |
| that is deployed in an enterprise. A principal is identified by using a principal |
| name and authenticated by using authentication data." See |
| <a href="http://download.oracle.com/javaee/6/tutorial/doc/bnbxj.html#bnbxq" target="_blank">Working |
| with Realms, Users, Groups, and Roles: Some Other Terminology</a> for more information.</p></li> |
| |
| <li>Click the Save button. |
| |
| <br><br> |
| At this stage, you have taken the necessary steps to enable you to log into the |
| <code>AffableBean</code> administration console using the <code>nbuser</code> / |
| <code>secret</code> username / password combination that you set earlier.</li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ). When the application opens in the browser, attempt |
| the access the administration console by entering the following URL into the browser's |
| address bar: |
| |
| <pre class="examplecode">http://localhost:8080/AffableBean<strong>/admin/</strong></pre></li> |
| |
| <li>When the login page displays, enter the username and password you set earlier in the |
| GlassFish Administration Console (<code>nbuser</code> / <code>secret</code>), then click |
| 'submit'. |
| |
| <br><br> |
| Using form-based authentication, the server authenticates the client using the username |
| and password credentials sent from the form. Because the <code>nbuser</code> belongs to |
| the <code>affableBeanAdmin</code> group, and that group is associated with the |
| <code>affableBeanAdmin</code> role, access is granted to the administration console.</li> |
| |
| <li>Click the 'log out' link provided in the administration console. The <code>nbuser</code> |
| is logged out of the administration console, and you are returned to the login page. |
| |
| <br><br> |
| The <code>AdminServlet</code> handles the '<code>/logout</code>' URL pattern by invalidating |
| the user session: |
| |
| <pre class="examplecode"> |
| // if logout is requested |
| if (userPath.equals("/admin/logout")) { |
| session = request.getSession(); |
| <strong>session.invalidate();</strong> // terminate session |
| response.sendRedirect("/AffableBean/admin/"); |
| return; |
| }</pre> |
| Calling <code>invalidate()</code> terminates the user session. As a consequence, the |
| authenticated user is dissociated from the active session and would need to login in |
| again in order to access protected resources.</li> |
| </ol> |
| </div> |
| |
| |
| <br> |
| <h2 id="secureTransport">Configuring Secure Data Transport</h2> |
| |
| <p>There are two instances in the <code>AffableBean</code> application that require a secure connection |
| when data is transmitted over the Internet. The first is when a user initiates the checkout process. |
| On the checkout page, a user must fill in his or her personal details to complete an order. This |
| sensitive data must be protected while it is sent to the server. The second instance occurs when |
| a user logs into the administration console, as the console is used to access sensitive data, i.e., |
| customer and order details.</p> |
| |
| <p>Secure data transport is typically implemented using Transport Layer Security (TLS) or Secure Sockets |
| Layer (SSL). HTTP is applied on top of the TLS/SSL protocol to provide both encrypted communication |
| and secure identification of the server. The combination of HTTP with TLS or SSL results in an HTTPS |
| connection, which can readily be identified in a browser's address bar (e.g., |
| <code><strong>https</strong>://</code>).</p> |
| |
| <p>The GlassFish server has a secure (HTTPS) service enabled by default. This service uses a self-signed |
| digital certificate, which is adequate for development purposes. Your production server however would |
| require a certificate signed by a trusted third-party Certificate Authority (CA), such as |
| <a href="http://www.verisign.com" target="_blank">VeriSign</a> or <a href="http://www.thawte.com/" |
| target="_blank">Thawte</a>.</p> |
| |
| <p class="tips">You can find the generated certificate in: |
| <code><em><gf-install-dir></em>/glassfish/domains/domain1/config/keystore.jks</code></p> |
| |
| <p>Begin this section by verifying that GlassFish' HTTPS service is enabled. Then configure the application |
| so that a secure HTTPS connection is applied to the checkout process and administration console.</p> |
| |
| <ul> |
| <li><a href="#verifyHTTPS">Verify HTTPS Support on the Server</a></li> |
| <li><a href="#configureSecure">Configure Secure Connection in the Application</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="verifyHTTPS">Verify HTTPS Support on the Server</h3> |
| |
| <ol> |
| <li>Open the Services window (Ctrl-5; ⌘-5 on Mac) and expand the Servers node |
| so that the GlassFish server node is visible.</li> |
| |
| <li>Ensure that the GlassFish server is running. If the server is running, a small green |
| arrow is displayed next to the GlassFish icon ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/gf-server-running-node.png" |
| alt="GlassFish server node in Services window"> ). If you need to start it, right-click |
| the server node and choose Start.</li> |
| |
| <li>Switch to your browser and type the following URL into the browser's address bar: |
| |
| <pre class="examplecode">https://localhost:8181/</pre> |
| |
| The browser displays a warning, indicating that the server is presenting you with |
| a self-signed certificate. In Firefox for example, the warning looks as follows. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/ff-untrusted-connection.png" |
| class="margin-around b-all" title="Firefox provides warnings for self-signed certificates" |
| alt="Firefox warning for self-signed certificates"></li> |
| |
| <li>Enable your browser to accept the self-signed certificate. With Firefox, click the Add |
| Exception button displayed in the warning. The following pane displays, allowing you to |
| view the certificate. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/ff-confirm-security-exception.png" |
| class="margin-around b-all" alt="Firefox window for confirming a security exception" |
| title="Firefox enables you to view the digital certificate before confirming the security exception"> |
| |
| <br> |
| Click Confirm Security Exception. A secure connection is established on port 8181, and |
| your local development server, GlassFish, is then able to display the following page. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/gf-https.png" |
| class="margin-around b-all" title="GlassFish provides a secure connection by default on port 8181" |
| alt="Browser welcome message for GlassFish webroot" id="serverWelcomePage"> |
| |
| <br> |
| <p class="tips">Aside from the HTTPS protocol displayed in the browser's address bar, Firefox |
| indicates that a secure connection is established with the blue background behind |
| <code>localhost</code> in the address bar. Also, a lock ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/firefox-lock-icon.png" |
| alt="Firefox lock icon"> ) icon displays in the lower right corner of the browser. |
| You can click the lock icon for secure pages to review certificate details.</p> |
| |
| The following optional steps demonstrate how you can identify this security support in |
| the GlassFish Administration Console.</li> |
| |
| <li>Open the GlassFish Administration Console in the browser. (Either type '<code>http://localhost:4848/</code>' |
| in your browser, or click the '<code>go to the Administration Console</code>' link in the GlassFish |
| server's welcome page, as displayed in the <a href="#serverWelcomePage">image above</a>.)</li> |
| |
| <li>In the Tree which displays in the left column of the Administration Console, expand the |
| Configuration > Network Config nodes, then click the Network Listeners node. |
| |
| <br><br> |
| The main panel displays the three network listeners enabled by default on the GlassFish server. |
| <code>http-listener-2</code>, which has been configured to listen over port 8181, is the network |
| listener used for secure connections. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/network-listeners.png" |
| class="margin-around b-all" alt="Network Listeners panel displayed in GlassFish Administration Console" |
| title="View all HTTP listeners from the Network Listeners panel"> |
| |
| <br> |
| <p class="tips">For more information on network listeners, see the Oracle GlassFish Server 3.0.1 |
| Administration Guide: |
| <a href="http://docs.sun.com/app/docs/doc/821-1751/giuri?l=en&a=view" target="_blank">About |
| HTTP Network Listeners</a>.</p></li> |
| |
| <li>Under the Name column, click the link for <code>http-listener-2</code>. In the main panel, note |
| that the Security checkbox is selected. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/edit-network-listener.png" |
| class="margin-around b-all" alt="Edit Network Listener panel in GlassFish Administration Console" |
| title="Security is enabled for the 'http-listener-2' network listener"></li> |
| |
| <li>Click the SSL tab. Note that TLS is selected. In the lower portion of the SSL panel, you see the |
| Cipher Suites that are available for the connection. As stated in the Oracle GlassFish Server 3.0.1 |
| Administration Guide, <a href="http://docs.sun.com/app/docs/doc/821-1751/ablnk" target="_blank">Chapter |
| 11: Administering System Security</a>, |
| |
| <blockquote> |
| <em>A cipher is a cryptographic algorithm used for encryption or decryption. SSL and TLS |
| protocols support a variety of ciphers used to authenticate the server and client to |
| each other, transmit certificates, and establish session keys. Some ciphers are stronger |
| and more secure than others. Clients and servers can support different cipher suites. |
| During a secure connection, the client and the server agree to use the strongest cipher |
| that they both have enabled for communication, so it is usually sufficient to enable |
| all ciphers.</em> |
| </blockquote> |
| |
| At this stage, you have an understanding of how the GlassFish server supports secure connections |
| out-of-the-box. Naturally, you could set up your own network listener, have it listen on a port |
| other than 8181, enable SSL 3 instead of TLS (or both), or generate and sign your own digital |
| certificates using Java's <a href="http://download.oracle.com/javase/6/docs/technotes/tools/solaris/keytool.html" |
| target="_blank"><code>keytool</code></a> management utility. You can find instructions on how to |
| accomplish all of these tasks from the following resources: |
| |
| <ul style="margin: 10px 0 0 -.7em"> |
| <li>The Java EE 6 Tutorial, <a href="http://download.oracle.com/javaee/6/tutorial/doc/bnbxw.html" target="_blank">Establishing a Secure Connection Using SSL</a></li> |
| <li>Oracle GlassFish Server 3.0.1 Administration Guide, <a href="http://docs.sun.com/app/docs/doc/821-1751/ablnk" target="_blank">Chapter 11: Administering System Security</a></li> |
| <li>Oracle GlassFish Server 3.0.1 Administration Guide, <a href="http://docs.sun.com/app/docs/doc/821-1751/ablsw" target="_blank">Chapter 16: Administering Internet Connectivity</a></li> |
| </ul> |
| </li> |
| </ol> |
| |
| |
| <h3 id="configureSecure">Configure Secure Connection in the Application</h3> |
| |
| <p>This example demonstrates how to specify a secure connection using both XML in the web deployment |
| descriptor, as well as Servlet 3.0 annotations directly in a servlet. You begin by creating an |
| <code><security-constraint></code> entry in <code>web.xml</code> for the customer checkout |
| process. Then, to create a secure connection for access to the administration console, you specify |
| a <code>TransportGuarantee</code> constraint for the <code>@HttpConstraint</code> annotation in |
| the <code>AdminServlet</code>.</p> |
| |
| <ol> |
| <li>Open the project's <code>web.xml</code> file in the editor. (If it is already opened, |
| you can press Ctrl-Tab and select it.)</li> |
| |
| <li>Click the Security tab along the top of the editor, then click the Add Security Constraint button.</li> |
| |
| <li>Type in <code>Checkout</code> for the Display Name, then under Web Resource Collection |
| click the Add button. Enter the following details, then when you are finished, click OK. |
| |
| <ul style="margin: 10px 0 0 -.7em"> |
| <li><strong>Resource Name:</strong> <code>Checkout</code></li> |
| <li><strong>URL Pattern(s):</strong> <code>/checkout</code></li> |
| <li><strong>HTTP Method(s):</strong> <code>Selected HTTP Methods</code> (<code>GET</code>)</li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/add-web-resource2.png" |
| class="margin-around b-all" alt="Add Web Resource dialog" |
| title="Specify which resources need to be protected using the Add Web Resource dialog"> |
| |
| <p class="notes"><strong>Note:</strong> Recall that the <code>/checkout</code> URL pattern is |
| handled by the <code>ControllerServlet</code>'s <code>doGet</code> method, and forwards the |
| user to the checkout page.</p></li> |
| |
| <li>Under the new Checkout security constraint, select the Enable User Data Constraint option, |
| then in the Transport Guarantee drop-down, select <code>CONFIDENTIAL</code>. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/checkout-security-constraint.png" |
| class="margin-around b-all" style="width:688px" alt="Checkout security constraint displayed under Security tab" |
| title="Use the web.xml visual editor to specify security settings for the application"> |
| |
| <p class="tips">When you choose <code>CONFIDENTIAL</code> as a security constraint, you are |
| instructing the server to encrypt data using TLS/SSL so that it cannot be read while in |
| transit. For more information, see the Java EE 6 Tutorial, |
| <a href="http://download.oracle.com/javaee/6/tutorial/doc/gkbaa.html#bncbm" |
| target="_blank">Specifying a Secure Connection</a>.</p></li> |
| |
| <li>Click the XML tab along the top of the editor. Note that the following |
| <code><security-constraint></code> entry has been added. |
| |
| <pre class="examplecode"> |
| <security-constraint> |
| <display-name>Checkout</display-name> |
| <web-resource-collection> |
| <web-resource-name>Checkout</web-resource-name> |
| <url-pattern>/checkout</url-pattern> |
| <http-method>GET</http-method> |
| </web-resource-collection> |
| <user-data-constraint> |
| <description/> |
| <transport-guarantee>CONFIDENTIAL</transport-guarantee> |
| </user-data-constraint> |
| </security-constraint></pre> |
| |
| Configuration for the customer checkout process is now complete. To ensure that a |
| secure connection is applied for access to the administration console, simply specify |
| that any requests handled by the <code>AdminServlet</code> are transmitted over a |
| secure channel.</li> |
| |
| <li>Open the <code>AdminServlet</code>. Press Alt-Shift-O (Ctrl-Shift-O on Mac) |
| and in the Go to File dialog, type '<code>admin</code>', then click OK.</li> |
| |
| <li>Use the <a href="http://download.oracle.com/javaee/6/api/javax/servlet/annotation/HttpConstraint.html" |
| target="_blank"><code>@HttpConstraint</code></a> annotation's <code>transportGuarantee</code> |
| element to specify a <code>CONFIDENTIAL</code> security constraint. Make the following |
| change (in <strong>bold</strong>). |
| |
| <pre class="examplecode"> |
| @WebServlet(name = "AdminServlet", |
| urlPatterns = {"/admin/", |
| "/admin/viewOrders", |
| "/admin/viewCustomers", |
| "/admin/customerRecord", |
| "/admin/orderRecord", |
| "/admin/logout"}) |
| @ServletSecurity( |
| @HttpConstraint(<strong>transportGuarantee = TransportGuarantee.CONFIDENTIAL,</strong> |
| rolesAllowed = {"affableBeanAdmin"}) |
| ) |
| public class AdminServlet extends HttpServlet { ... }</pre></li> |
| |
| <li>Press Ctrl-Shift-I (⌘-Shift-I on Mac) to fix imports. An import statement |
| for <code>javax.servlet.annotation.ServletSecurity.TransportGuarantee</code> is |
| added to the top of the class.</li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) to examine the application's behavior in a browser.</li> |
| |
| <li>In the browser, step through the <code>AffableBean</code> website by selecting |
| a product category and adding several items to your shopping cart. Then click the |
| 'proceed to checkout' button. The website now automatically switches to a secure |
| channel when presenting the checkout page. You see the HTTPS protocol displayed |
| in the browser's address bar, and the port is changed to 8181. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/secure-checkout.png" |
| class="margin-around b-all" alt="Browser address bar showing HTTPS protocol for checkout request" |
| title="The browser address bar indicates that a secure connection is established for customer checkout"> |
| |
| <br> |
| Also, in Firefox, note the lock ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/firefox-lock-icon.png" |
| alt="Firefox lock icon"> ) icon displayed in the lower right corner of the browser.</li> |
| |
| <li>Investigate security for the administration console. Type in the following URL into the browser's |
| address bar: |
| |
| <pre class="examplecode">http://localhost:8080/AffableBean/admin/</pre> |
| |
| The website now automatically switches to a secure |
| channel when presenting the checkout page. You see the HTTPS protocol displayed |
| in the browser's address bar, and the port is changed to 8181. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/secure-admin.png" |
| class="margin-around b-all" alt="Browser address bar showing HTTPS protocol for checkout request" |
| title="The browser address bar indicates that a secure connection is established for customer checkout"> |
| |
| <p class="notes"><strong>Note:</strong> You way wonder at this point how it is possible |
| to switch from a secure connection back to a normal, unsecured one. This practice |
| however is not recommended. The <a href="http://download.oracle.com/javaee/6/tutorial/doc/gkbaa.html#bncbm" |
| target="_blank">Java EE 6 Tutorial</a> explains as follows:</p> |
| |
| <blockquote style="margin-top: 0"> |
| <em>If you are using sessions, after you switch to SSL you should never accept any |
| further requests for that session that are non-SSL. For example, a shopping site |
| might not use SSL until the checkout page, and then it might switch to using SSL |
| to accept your card number. After switching to SSL, you should stop listening to |
| non-SSL requests for this session. The reason for this practice is that the session |
| ID itself was not encrypted on the earlier communications. This is not so bad when |
| you’re only doing your shopping, but after the credit card information is stored |
| in the session, you don’t want a bad guy trying to fake the purchase transaction |
| against your credit card. This practice could be easily implemented using a filter.</em> |
| </blockquote></li> |
| </ol> |
| </div> |
| |
| <p>You have now successfully secured the <code>AffableBean</code> application according to the defined |
| customer requirements. You've set up a login form for the administration console to authorize or deny |
| access based on user credentials, and you configured the application and server to create a secure |
| connection for access to the administration console, as well as the customer checkout process.</p> |
| |
| <p>You can compare your work with the <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_complete.zip">completed |
| <code>AffableBean</code> project</a>. The completed project includes the security implementation |
| demonstrated in this unit, and also provides a basic implementation for web page error customization, |
| such as when a request for a nonexistent resource is made, and the server returns an HTTP 404 |
| 'Not Found' error message.</p> |
| |
| <div class="indent"> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/security/http-404.png" |
| class="margin-around b-all" style="width:728px" alt="Browser address bar showing HTTPS protocol for checkout request" |
| title="The browser address bar indicates that a secure connection is established for customer checkout"> |
| </div> |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Securing the Application">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <br> |
| <h2 id="seeAlsoSecurity">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Resources</h3> |
| |
| <ul> |
| <li><a href="../../web/security-webapps.html" target="_blank">Securing a Web Application</a></li> |
| <li><a href="../javaee-intro.html" target="_blank">Introduction to Java EE Technology</a></li> |
| <li><a href="../javaee-gettingstarted.html" target="_blank">Getting Started with Java EE Applications</a></li> |
| <li><a href="https://netbeans.org/projects/www/downloads/download/shortcuts.pdf">Keyboard Shortcuts & Code Templates Card</a></li> |
| <li><a href="../../../trails/java-ee.html" target="_blank">Java EE & Java Web Learning Trail</a></li> |
| </ul> |
| |
| <h3>External Resources</h3> |
| |
| <ul> |
| <li><a href="http://download.oracle.com/javaee/6/tutorial/doc/bnbwj.html" target="_blank">The Java EE 6 Tutorial, Chapter 24: Introduction to Security in the Java EE Platform</a></li> |
| <li><a href="http://download.oracle.com/javaee/6/tutorial/doc/bncas.html" target="_blank">The Java EE 6 Tutorial, Chapter 25: Getting Started Securing Web Applications</a></li> |
| <li><a href="http://download.oracle.com/javaee/6/tutorial/doc/bnbyk.html" target="_blank">The Java EE 6 Tutorial, Chapter 26: Getting Started Securing Enterprise Applications</a></li> |
| <li><a href="http://docs.sun.com/app/docs/doc/821-1751" target="_blank">Oracle GlassFish Server 3.0.1 Administration Guide</a></li> |
| <li><a href="http://java.sun.com/developer/technicalArticles/J2EE/security_annotation/" target="_blank">Security Annotations and Authorization in GlassFish and the Java EE 5 SDK</a></li> |
| <li><a href="http://www.infoq.com/news/2010/07/javaee6-security" target="_blank">Java EE 6: Application Security Enhancements</a></li> |
| <li><a href="http://refcardz.dzone.com/refcardz/getting-started-java-ee" target="_blank">Getting Started with Java EE Security</a> [RefCard]</li> |
| <li><a href="http://en.wikipedia.org/wiki/Https" target="_blank">HTTP Secure</a> [Wikipedia]</li> |
| <li><a href="http://en.wikipedia.org/wiki/Digital_certificate" target="_blank">Public key certificate</a> [Wikipedia]</li> |
| </ul> |
| </div> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="test-profile">The NetBeans E-commerce Tutorial - Testing and Profiling</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><strong>Testing and Profiling</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#test">Testing with JMeter</a></li> |
| <li><a href="#profile">Using the NetBeans Profiler</a></li> |
| <li><a href="#glassFishTune">Tuning the GlassFish Server</a></li> |
| <li><a href="#seeAlsoTestProfile">See Also</a></li> |
| </ul></li> |
| |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>Before delivering any application, it is important to ensure that it functions |
| properly, and that it can perform acceptably for the demands expected of it. Web |
| applications, especially e-commerce applications, by their very nature provide |
| concurrent access to shared resources. In other words, the servers on which they |
| are hosted must be able to respond to multiple users requesting the same resources |
| over the same period of time. Be mindful of this fact when during development |
| your application appears to behave correctly as you click through web pages in |
| your browser. How will the application perform when handling 100 users simultaneously? |
| Are there memory leaks that will degrade the server's performance after the |
| application has been running for long periods of time? What steps can you take |
| to ensure that your production server best handles traffic to your application?</p> |
| |
| <p>This tutorial unit is designed to introduce you to the IDE's support for testing |
| and profiling. You begin by installing the JMeter Kit plugin, which enables you to |
| create test plans and open them in <a href="http://jakarta.apache.org/jmeter/" |
| target="_blank">Apache JMeter</a> from the IDE. You then create a basic test plan |
| in JMeter, and proceed by exploring the tool's capacity for functional and |
| performance testing. Finally, you explore the IDE's Profiler, and use it to |
| examine GlassFish' memory consumption while you run the JMeter test plan against |
| the <code>AffableBean</code> application over an extended period of time. This unit |
| concludes by presenting various tips that enable you to tune the GlassFish server |
| for your application in a production environment.</p> |
| |
| <p>You can view a live demo of the application that you build in this tutorial: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans |
| E-commerce Tutorial Demo Application</a>.</p> |
| |
| <br style="clear:left;"> |
| |
| <br> |
| <table> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Software or Resource</th> |
| <th class="tblheader" scope="col">Version Required</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/downloads/index.html" target="_blank">NetBeans IDE</a></td> |
| <td class="tbltd1">Java bundle, 6.8 or 6.9</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" target="_blank">Java Development Kit (JDK)</a></td> |
| <td class="tbltd1">version 6</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#glassFishTestProfile">GlassFish server</a></td> |
| <td class="tbltd1">v3 or Open Source Edition 3.0.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="#jmeter">JMeter</a></td> |
| <td class="tbltd1">2.2 or more recent</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="http://dev.mysql.com/downloads/mysql/" target="_blank">MySQL database server</a></td> |
| <td class="tbltd1">version 5.1</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_complete.zip">AffableBean |
| project</a></td> |
| <td class="tbltd1">complete version</td> |
| </tr> |
| </tbody> |
| </table> |
| |
| <p><strong class="notes">Notes:</strong></p> |
| |
| <ul> |
| <li>The NetBeans IDE requires the Java Development Kit (JDK) to run properly. |
| If you do not have any of the resources listed above, the JDK should be |
| the first item that you download and install.</li> |
| |
| <li>The NetBeans IDE Java Bundle includes Java Web and EE technologies, which are |
| required for the application you build in this tutorial.</li> |
| |
| <li id="glassFishTestProfile">The NetBeans IDE Java Bundle also includes the GlassFish server, |
| which you require for this tutorial. You could |
| <a href="http://glassfish.dev.java.net/public/downloadsindex.html" target="_blank">download |
| the GlassFish server independently</a>, but the version provided with the |
| NetBeans download has the added benefit of being automatically registered with |
| the IDE.</li> |
| |
| <li>You can follow this tutorial unit without having completed previous units. To |
| do so, see the <a href="#setup">setup instructions</a>, which describe how |
| to prepare the database and establish connectivity between the IDE, GlassFish, |
| and MySQL.</li> |
| |
| <li id="jmeter"><strong>You do not need to download JMeter for its use in this tutorial.</strong> |
| Instead, you install the NetBeans JMeter Kit plugin, which includes the JMeter |
| distribution. You will therefore require an Internet connection at the point |
| when you install the plugin in the tutorial. JMeter can be downloaded independently |
| from <a href="http://jakarta.apache.org/site/downloads/downloads_jmeter.cgi" |
| target="_blank">http://jakarta.apache.org/site/downloads/downloads_jmeter.cgi</a>.</li> |
| |
| <li>The JMeter Kit plugin for NetBeans 6.8 installs JMeter version 2.2 (released |
| June 2006). The plugin for NetBeans 6.9 installs JMeter version 2.4 (released |
| July 2010). There is a significant difference between these two versions.</li> |
| </ul> |
| |
| |
| <h2 id="test">Testing with JMeter</h2> |
| |
| <p>Begin by examining the <code>AffableBean</code> tutorial application. Then install the |
| JMeter Kit plugin using the IDE's Plugins Manager. Launch JMeter from the IDE, and |
| proceed by creating a test plan based on the tutorial <a href="design.html#mockups">use-case</a>. |
| Finally, explore some of JMeter's facilities for functional and load testing.</p> |
| |
| <ul> |
| <li><a href="#install">Install the JMeter Kit Plugin</a></li> |
| <li><a href="#createTestPlan">Create a Test Plan</a></li> |
| <li><a href="#loadTest">Load Testing</a></li> |
| <li><a href="#stressTest">Stress Testing</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="install">Install the JMeter Kit Plugin</h3> |
| |
| <ol> |
| <li>Open the <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_complete.zip"><code>AffableBean</code> |
| project</a> in the IDE. Click the Open Project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/open-project-btn.png" |
| alt="Open Project button"> ) button and use the wizard to navigate to the location |
| on your computer where you downloaded the project.</li> |
| |
| <li>Run the project ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) to ensure that it is properly configured with your database |
| and application server. |
| |
| <br> |
| <p class="alert margin-around">If you receive an error when running the project, revisit the |
| <a href="#setup">setup instructions</a>, which describe how to prepare the |
| database and establish connectivity between the IDE, GlassFish, and MySQL. |
| If you want to log into the project's administration console (not required in |
| this tutorial unit), you'll need to create a user named <code>nbuser</code> on |
| the GlassFish server. This task is described in Unit 11, |
| <a href="security.html#createUsers">Securing the Application: Create Users and/or |
| Groups on the Server</a>.</p></li> |
| |
| <li>Open the IDE's Plugins Manager by choosing Tools > Plugins from the main menu. |
| Select the Available Plugins tab, then type in '<code>jmeter</code>' into the Search |
| field. When you see JMeter Kit displayed from the filtered results, select it by |
| clicking the checkbox under the Install column. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/plugins-manager.png" |
| class="margin-around b-all" style="width:688px" alt="JMeter Kit displayed under Available Plugins in the Plugins Manager" |
| title="JMeter Kit is a NetBeans certified plugin available in the Plugins Manager"></li> |
| |
| <li>Click Install. The IDE's installer informs you that two plugins will be installed: |
| The JMeter Kit and the Load Generator, which provides a generic infrastructure for |
| load generator engines registered in the IDE. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/ide-installer.png" |
| class="margin-around b-all" alt="JMeter Kit and Load Generator listed in the IDE's Plugin Installer" |
| title="Plugins dependencies are automatically included during installation"></li> |
| |
| <li>Click Next. Accept the license agreement, then click Install. |
| |
| <br> |
| <p class="alert margin-around">You require an Internet connection to download the selected plugins.</p> |
| |
| The installer downloads, verifies, and installs the plugins. When installation |
| has successfully completed, click Finish to exit the installer, then click Close |
| to close the Plugins Manager.</li> |
| |
| <li>In the Projects window, note that a new Load Generator Scripts node displays in |
| your project. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/load-generator-scripts.png" |
| class="margin-around b-all" alt="Projects window displaying Load Generator Scripts node" |
| title="The Load Generator plugin enables you to access scripts from the Projects window"> |
| |
| <br> |
| If you open the Files window (Ctrl-2; ⌘-2 on Mac), you'll see a new <code>jmeter</code> |
| folder added to the project. (Recall that the Files window provides a directory-based view of |
| projects, i.e., it displays the folder structure of projects as they exist on your computer's |
| file system.) The <code>jmeter</code> folder corresponds to the Project window's Load Generator |
| Scripts node, and will contain any load scripts that you later add to the project.</li> |
| </ol> |
| |
| |
| <h3 id="createTestPlan">Create a Test Plan</h3> |
| |
| <p>To demonstrate how to create a test plan in JMeter, we'll base our plan on the |
| tutorial use-case, which was presented in <a href="design.html#mockups">Designing |
| the Application</a>. A list of user-initiated requests to the server, based on |
| the given use-case, might look something like the following:</p> |
| |
| <table id="useCase" style="width:742px"> |
| <tr> |
| <th width="558px" class="tblheader" scope="col">Use-Case</th> |
| <th class="tblheader" scope="col">Server Request</th> |
| </tr> |
| <tr class="tbltd0"> |
| <td><em>Customer visits the welcome page...</em></td> |
| <td><code>/AffableBean/</code></td> |
| </tr> |
| <tr class="tbltd1"> |
| <td><em>...and selects a product category.</em></td> |
| <td><code>/AffableBean/category</code></td> |
| </tr> |
| <tr class="tbltd0"> |
| <td><em>Customer browses products within the selected category page, |
| then adds a product to his or her shopping cart.</em></td> |
| <td><code>/AffableBean/addToCart</code></td> |
| </tr> |
| <tr class="tbltd1"> |
| <td><em>Customer continues shopping and selects a different category.</em></td> |
| <td><code>/AffableBean/category</code></td> |
| </tr> |
| <tr class="tbltd0"> |
| <td><em>Customer adds several products from this category to shopping cart.</em></td> |
| <td><code>/AffableBean/addToCart</code><br><code>/AffableBean/addToCart</code></td> |
| </tr> |
| <tr class="tbltd1"> |
| <td><em>Customer selects 'view cart' option...</em></td> |
| <td><code>/AffableBean/viewCart</code></td> |
| </tr> |
| <tr class="tbltd0"> |
| <td><em>...and updates quantities for cart products in the cart page.</em></td> |
| <td><code>/AffableBean/updateCart</code></td> |
| </tr> |
| <tr class="tbltd1"> |
| <td><em>Customer verifies shopping cart contents and proceeds to checkout.</em></td> |
| <td><code>/AffableBean/checkout</code></td> |
| </tr> |
| <tr class="tbltd0"> |
| <td><em>In the checkout page, customer views the cost of the order and other |
| information, fills in personal data, then submits his or her details.</em></td> |
| <td><code>/AffableBean/purchase</code></td> |
| </tr> |
| <tr class="tbltd1"> |
| <td><em>The order is processed and customer is taken to a confirmation page. |
| The confirmation page provides a unique reference number for tracking |
| the customer order, as well as a summary of the order.</em></td> |
| <td>(n/a)</td> |
| </tr> |
| </table> |
| |
| <p>Let's proceed by creating a JMeter test plan that follows the above list of requests.</p> |
| |
| <ol style="margin-top:0"> |
| <li>Click the New File ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/new-file-btn.png" |
| alt="New File button"> ) button in the IDE's toolbar. (Alternatively, press Ctrl-N; |
| ⌘-N on Mac.)</li> |
| |
| <li>Under Categories, select <strong>Load Testing Scripts</strong>. |
| |
| <br><br> |
| <p class="tips">Instead of scrolling to the bottom of the list, simply begin typing |
| '<code>load</code>'. As shown in the image below, the Load Testing Scripts |
| category displays. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/file-wizard-load.png" |
| class="margin-around b-all" alt="Load Generator Scripts category displayed in File wizard" |
| title="You can filter category entries by typing the category you are searching for"></p></li> |
| |
| <li>Expand the Load Testing Scripts category and select <strong>JMeter Plans</strong>. |
| Under File Types, select <strong>New JMeter Plan</strong>, then click Next.</li> |
| |
| <li>Name the plan <code>useCaseTest</code>, then click Finish. The new test plan |
| displays in the Projects window. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/use-case-test.png" |
| class="margin-around b-all" alt="New 'useCaseTest' test plan displayed in Projects window" |
| title="JMeter test plans display under Load Testing Scripts in the Projects window"></li> |
| |
| <li>To begin customizing the plan in JMeter, right-click the <code>useCaseTest.jmx</code> |
| node and choose External Edit. JMeter opens. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/jmeter.png" |
| class="margin-around b-all" style="width:688px" alt="NetBeans template plan displayed in JMeter" |
| title="NetBeans template plan is provided when opening JMeter" id="testPlanPanel"> |
| |
| <p class="notes"><strong>Note:</strong> The NetBeans template plan includes various |
| user-defined variables, as shown in the above image. Usage of several of these |
| variables will become clear as we work with the test plan. For more information, |
| see the Apache JMeter User's Manual: |
| <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#User_Defined_Variables" |
| target="_blank">18.4.13 User Defined Variables</a>.</li> |
| |
| <li>Click the HTTP Request Defaults node in the left column. The |
| <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#HTTP_Request_Defaults" |
| target="_blank">HTTP Request Defaults</a> panel enables you to set default values for |
| all HTTP requests invoked from your test plan. Note that the entries for Server Name |
| and Port Number are <code>${nb.server}</code> and <code>${nb.port}</code>, respectively. |
| From the image above, you see that these equate to <code>localhost</code> and |
| <code>8080</code>, which you typically use when deploying NetBeans projects to |
| GlassFish.</li> |
| |
| <li>Click the Thread Group node in the left column. In JMeter, a "thread" refers |
| to a user. Let's rename the Thread Group to <code>AffableBean</code> <code>Users</code>. |
| Type '<code>AffableBean</code> <code>Users</code>' into the Name field under Thread Group. |
| |
| <br><br> |
| Let's begin recording requests for the test plan. To do so, we'll use JMeter's |
| <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#HTTP_Proxy_Server" |
| target="_blank">HTTP Proxy Server</a>. Instead of entering test plan requests |
| manually, we'll run the proxy server and have it record requests sent from the |
| browser. For large test plans this technique is invaluable.</li> |
| |
| <li>In the left column, right-click WorkBench and choose Add > Non-Test Elements > |
| HTTP Proxy Server.</li> |
| |
| <li>In the HTTP Proxy Server panel, change the port number from <code>8080</code> to another, |
| random number, for example <code>9090</code>. JMeter provides <code>8080</code> as |
| its default port number for the proxy server. However, the GlassFish server also occupies |
| the <code>8080</code> port, so we're modifying the proxy server's port number to avoid |
| a port conflict.</li> |
| |
| <li>In the Grouping drop-down list, select 'Put each group in a new controller'. Also, deselect |
| the 'Capture HTTP Headers' option. We do not require header information for each recorded |
| request. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/http-proxy-server.png" |
| class="margin-around b-all" style="width:688px" alt="JMeter HTTP Proxy Server - top panes" |
| title="Configure the proxy server"> |
| |
| <br> |
| Note that the 'Use Recording Controller' option is selected by default for the Target Controller |
| field. When you begin recording requests, they will be stored in the Recording Controller |
| that is listed in the left column. </li> |
| |
| <li>Switch to your browser and temporarily change its port number to <code>9090</code>. |
| |
| <br> |
| <p class="alert margin-around">If you have previously configured your browser's proxy, remember your settings |
| so that you may be able to reenter them after completing this exercise.</p> |
| |
| In Firefox, you can do this from the Options window (Preferences window on Mac). |
| |
| <ul style="margin-top:8px; list-style-type:lower-alpha"> |
| <li>Choose Tools > Options (Firefox > Preferences on Mac).</li> |
| |
| <li>Select the Advanced > Network tabs.</li> |
| |
| <li>Under the Connection heading, click Settings.</li> |
| |
| <li>Select the 'Manual proxy configuration' option, then type in <code>localhost</code> |
| and <code>9090</code> for the HTTP Proxy and Port fields, respectively.</li> |
| |
| <li>Remove the <code>127.0.0.1</code> and <code>localhost</code> entries in the |
| 'No Proxy for' field. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/firefox-proxy.png" |
| class="margin-around b-all" alt="Firefox Preferences window - proxy settings" id="ff-proxy-config" |
| title="Specify 'localhost:9090' and remove entries in the 'No Proxy for' field"></li> |
| |
| <li>Click OK.</li> |
| </ul> |
| </li> |
| |
| <li>Clear your browser's cache before you begin recording requests. You want to make sure |
| that the HTTP Proxy Server is able to record all resources required for displaying |
| pages in the Affable Bean website, including images, JavaScript scripts and CSS stylesheets. |
| |
| <br><br> |
| In Firefox, you can do this by pressing Ctrl-Shift-Del (⌘-Shift-Del on Mac) to |
| open the Clear Recent History dialog. Under 'Time range to clear', ensure that you've |
| selected a range that extends to the first time the browser accessed the Affable Bean |
| website. Select Cache, then click Clear Now. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/ff-clear-recent-history.png" |
| class="margin-around b-all" alt="Firefox Clear Recent History dialog" |
| title="Clear your browser's cache before proceeding with recording"></li> |
| |
| <li>Return to the JMeter Test Plan panel (<a href="#testPlanPanel">shown above</a>) and |
| change the values for <code>nb.users</code> and <code>nb.rampup</code> to <code>99</code>. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/user-defined-variables.png" |
| class="margin-around b-all" alt="User-defined variables in JMeter" |
| title="Double-click into User Defined Variables table to modify variables"> |
| |
| <br> |
| The reason this is recommended is that JMeter automatically inserts user-defined variables |
| throughout the test plan, wherever their values occur. So, for example, when the URL for |
| <code>/AffableBean/js/jquery-1.4.2.js</code> is encountered, it will be recorded as: |
| <code>AffableBean/js/jquery-1.4.<strong>${nb.users}</strong>.js</code>. Later, when we |
| modify the value and rerun the test plan, URLs such as this will also change, which is |
| not desired behavior. Here, we enter a random value (<code>99</code>), since we don't |
| expect it to occur in the URLs that we are about to record.</li> |
| |
| <li>Return to the HTTP Proxy Server panel, then at the bottom of the panel, click the Start |
| button. JMeter's proxy server is now listening on port 9090.</li> |
| |
| <li>Run the project ( <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-project-btn.png" |
| alt="Run Project button"> ) from the IDE. The project is deployed to GlassFish, and the |
| welcome page opens in the browser.</li> |
| |
| <li>Switch to JMeter and inspect the Recording Controller in the left column. All of the |
| requests generated for accessing the welcome page are listed under the Recording Controller |
| in a node named after the first request (i.e., <code>/AffableBean/</code>). |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/recording-controller.png" |
| class="margin-around b-all" alt="JMeter - Recording Controller in left column" |
| title="Request grouping for welcome page displayed under Recording Controller"> |
| |
| <br> |
| <p class="tips">If you inspect the <code>/AffableBean/</code> node, you'll note that it |
| is a <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#Simple_Controller" |
| target="_blank">Simple Controller</a>. Although dubbed a "Controller", the |
| Simple Controller doesn't offer any functionality beyond enabling you to group elements |
| together - as demonstrated here.</p></li> |
| |
| <li>Return to the browser and continue clicking through the website according to the use-case |
| <a href="#useCase">outlined above</a>. You can select any of the categories and products. |
| Stop when you reach the checkout page - the proxy server will not be able to record requests |
| sent over HTTPS.<sup><a href="#footnote1TestProfile" id="1TestProfile" style="text-decoration:none">[1]</a></sup> |
| |
| <br><br> |
| The elements within the Recording Controller will look as follows. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/recording-controller2.png" |
| class="margin-around b-all" alt="JMeter - Recording Controller in left column" |
| title="Requests according to use-case listed under Recording Controller"></li> |
| |
| <li>Stop the proxy server. Click the Stop button in JMeter's HTTP Proxy Server panel.</li> |
| |
| <li>In your browser, change the proxy configuration so that it no longer uses port 9090. |
| In Firefox for example, return to the proxy configuration window (<a href="#ff-proxy-config">displayed |
| above</a>) and select No Proxy.</li> |
| |
| <li>Manually create the request for <code>/AffableBean/purchase</code>. Perform the following |
| steps: |
| |
| <ol style="margin-top:8px; list-style-type:lower-alpha"> |
| <li>Click the Simple Controller in JMeter's left column, then press Ctrl-X (⌘-X |
| on Mac) to cut the element.</li> |
| |
| <li>Click the Recording Controller, then press press Ctrl-V (⌘-V on Mac) to paste |
| the element. The Simple Controller now displays beneath the <code>/AffableBean/checkout</code> |
| request.</li> |
| |
| <li>Click the Simple Controller node, then in its main panel rename the controller to |
| <code>/AffableBean/purchase</code>.</li> |
| |
| <li>Right-click the new <code>/AffableBean/purchase</code> node and choose Add > Sampler |
| > <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#HTTP_Request" |
| target="_blank">HTTP Request</a>.</li> |
| |
| <li>Click the new HTTP Request node, then in its main panel configure it as follows: |
| |
| <ul style="margin: 7px 0 0 -1.7em"> |
| <li><strong>Name:</strong> <code>/AffableBean/purchase</code></li> |
| <li><strong>Server Name or IP:</strong> <code>${nb.server}</code></li> |
| <li><strong>Port Number:</strong> <code>8181</code></li> |
| <li><strong>Protocol:</strong> <code>https</code></li> |
| <li><strong>Method:</strong> <code>POST</code></li> |
| <li><strong>Path:</strong> <code>/AffableBean/purchase</code></li> |
| </ul></li> |
| |
| <li>Under 'Send Parameters With the Request', click the Add button and create |
| the following entries: |
| |
| <table class="margin-around"> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Name</th> |
| <th class="tblheader" scope="col">Value</th> |
| <th class="tblheader" scope="col">Encode?</th> |
| <th class="tblheader" scope="col">Include Equals?</th> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>name</code></td> |
| <td class="tbltd1"><code>Benjamin Linus</code></td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>email</code></td> |
| <td class="tbltd1"><code>b.linus@lost.com</code></td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>phone</code></td> |
| <td class="tbltd1"><code>222756448</code></td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>address</code></td> |
| <td class="tbltd1"><code>DruĹľstevnĂ 77</code></td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>cityRegion</code></td> |
| <td class="tbltd1"><code>4</code></td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| </tr> |
| <tr> |
| <td class="tbltd1"><code>creditcard</code></td> |
| <td class="tbltd1"><code>4444222233331111</code></td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| <td class="tbltd1" style="text-align: center">✓</td> |
| </tr> |
| </tbody> |
| </table> |
| </li> |
| </ol> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/http-request.png" |
| class="margin-around b-all" style="margin-top:0; width:688px" alt="JMeter - HTTP Request panel" |
| title="Configure an HTTP Request for HTTPS connection"></li> |
| |
| <li>Now, add an <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#HTTP_Cookie_Manager" |
| target="_blank">HTTP Cookie Manager</a> to the test plan. Right-click the <code>AffableBean</code> |
| <code>Users</code> thread group node in JMeter's left column, then choose Add > Config Element |
| > HTTP Cookie Manager. |
| |
| <br><br> |
| Recall that the <code>AffableBean</code> application relies on a session-tracking mechanism |
| (i.e., cookies or URL-rewriting) to remember which shopping cart belongs to which request. |
| Therefore, we need to account for this in the test plan. JMeter acts as the client when sending |
| requests to the server, however unlike a browser, it doesn't have cookies "enabled by |
| default." We apply the HTTP Cookie Manager to the thread group so that the |
| <code>JSESSIONID</code> cookie can be passed between client and server. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> If you want to employ URL rewriting as the |
| session-tracking mechanism, you would need to add the |
| <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#HTTP_URL_Re-writing_Modifier" |
| target="_blank">HTTP URL Re-writing Modifier</a> to the thread group.</p></li> |
| |
| <li>Finally, add an element to the test plan that simulates a delay between user-initiated requests. |
| |
| <ol style="margin-top:8px; list-style-type:lower-alpha"> |
| <li>Right-click the <code>/AffableBean/</code> Simple Controller in the left column |
| and choose Add > Sampler > Test Action.</li> |
| |
| <li>In the main panel, specify the following: |
| |
| <ul style="margin-top:8px"> |
| <li><strong>Name:</strong> <code>user delay</code></li> |
| <li><strong>Duration (milliseconds):</strong> <code>${nb.interleave}</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/test-action.png" |
| class="margin-around b-all" alt="JMeter - Test Action panel" |
| title="Use a Test Action element to simulate a delay between user-initiated requests"></li> |
| |
| <li>In JMeter's left column, copy (Ctrl-C; ⌘-C on Mac) the new <code>user</code> <code>delay</code> |
| Test Action node, then paste it (Ctrl-V; ⌘-V on Mac) into each of the other Simple Controllers ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/simple-controller-node.png" |
| alt="Simple Controller icon"> ) that form the test plan, except for the final one |
| (<code>/AffableBean/purchase</code>). |
| |
| <br><br> |
| When you finish, the final six Simple Controllers and their contents will look as follows. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/user-delay.png" |
| class="margin-around b-all" alt="Test Action nodes shown in JMeter left column" |
| title="Use copy and paste functionality to place existing elements elsewhere in your test plan"> |
| </li> |
| </ol> |
| </li> |
| |
| <li>(<em>Optional</em>.) Clean up the test plan. You can remove the Loop Controller and |
| Constant Timer. (Right-click and choose Remove.) Also, move all of the Recording Controller's |
| child elements directly into the <code>AffableBean</code> <code>Users</code> thread group, |
| then remove the Recording Controller. When you finish, the test plan will look as follows. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/test-plan.png" |
| class="margin-around b-all" alt="Test plan displayed in JMeter left column" |
| title="Remove unnecessary items from test plan"> |
| </li> |
| </ol> |
| |
| |
| <h3 id="loadTest">Load Testing</h3> |
| |
| <p><a href="http://en.wikipedia.org/wiki/Load_testing" target="_blank">Load testing</a> a web |
| application involves making concurrent requests for resources, typically by simulating multiple |
| users, and then examining the server's behavior. We can use the test plan we created for this |
| purpose, and make adjustments to the number of users and other settings to determine how the |
| server behaves under the given work load.</p> |
| |
| <p>Load testing should be performed with specific goals in mind, such as determining the |
| <a href="http://en.wikipedia.org/wiki/Throughput" target="_blank">throughput</a> for |
| the anticipated average and peak numbers of users. It is also worthwhile to assess the |
| <em>response time</em> for requests, to ensure that site customers are not having to wait |
| too long to be served. In order to measure the response time, you need to take into account |
| the time during which data spends traveling over the Internet. One way to do this is to |
| compare test results between a local server, where network travel time is nearly non-existent, |
| and results from testing the production server remotely. The following example demonstrates |
| how you can perform tests using your local development server. Once you migrate an application |
| to the production server, you can simply change the value for the server variable set |
| under the test plan's User Defined Variables.</p> |
| |
| <p>The results recorded in this and the following sections were arrived at by running tests on |
| a computer with a 2.4 GHz Intel Core 2 Duo processor and 4 GB of memory. Naturally, the results |
| you get depend on your computer's performance, and will likely not match those displayed here.</p> |
| |
| <p class="alert">When you run load tests, you should be careful not to overload your computer. |
| If you set too many threads (i.e., users), do not place adequate delay between individual |
| requests, or continuously loop through the test plan, there is a chance that JMeter will |
| expend your computer’s processing capacity or memory. JMeter will then become unresponsive |
| and you may need to "force quit" the tool using your computer's task manager. It |
| is therefore recommended that you open the task manager in order to monitor the computer's |
| CPU and memory levels while the test is running. This will allow you to gauge the limits |
| of your computer in terms of running the test plan.</p> |
| |
| <ol> |
| <li>Open JMeter if it is not already opened. (In the IDE's Projects window, right-click |
| <code>useCaseTest.jmx</code> and choose External Edit.) |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> If you did not create the JMeter test plan in |
| the <a href="#createTestPlan">previous sub-section</a>, you can download the complete |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FuseCaseTest.jmx"><code>useCaseTest.jmx</code></a> |
| file and add it to your project. To add it to the <code>AffableBean</code> project, |
| copy it from your computer's file system (Ctrl-C; ⌘-C on Mac), then in the IDE, |
| open the Files window (Ctrl-2; ⌘-2 on Mac), right-click the <code>jmeter</code> |
| folder and choose Paste.</p></li> |
| |
| <li>Add several <em>listeners</em> to the test plan: |
| |
| <ul style="margin: 7px 0 0 -1.7em"> |
| <li>Right-click <code>AffableBean</code> <code>Users</code> and choose Add > |
| Listener > <strong>Summary Report</strong>.</li> |
| |
| <li>Right-click <code>AffableBean</code> <code>Users</code> and choose Add > |
| Listener > <strong>View Results Tree</strong>.</li> |
| |
| <li>Right-click <code>AffableBean</code> <code>Users</code> and choose Add > |
| Listener > <strong>Graph Results</strong>.</li> |
| </ul> |
| |
| In JMeter, you require a <em>listener</em> to record and display the results of your test plan. |
| The <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#Summary_Report" |
| target="_blank">Summary Report</a> displays a table, with each row corresponding to each |
| differently named request in your test. The |
| <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#View_Results_Tree" |
| target="_blank">View Results Tree</a> shows a tree of all sample responses, allowing you |
| to view response details for any sample. The |
| <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#Graph_Results" |
| target="_blank">Graph Results</a> listener displays a simple graph that plots all |
| sample times.</li> |
| |
| <li>Click the JMeter Template Plan node, then make the following changes to User Defined |
| Variables: |
| |
| <ul style="margin: 7px 0 0 -1.7em"> |
| <li><strong><code>nb.users</code>:</strong> <code>1</code></li> |
| <li><strong><code>nb.interleave</code>:</strong> <code>5000</code></li> |
| </ul> |
| |
| We begin the test by simulating just one user. The value for <code>nb.interleave</code> |
| is used in the <code>user</code> <code>delay</code> Test Action that we created, and |
| represents the duration of a pause in milliseconds. Therefore, the test will pause for |
| 5 seconds between each user-initiated request.</li> |
| |
| <li>Click the Summary Report node so that you are able to view the test results while the |
| test is running.</li> |
| |
| <li>Run the test plan. Choose Run > Start (Ctrl-R; ⌘-R on Mac) from the main menu. |
| |
| <br><br> |
| The test plan runs for approximately 50 seconds. Note that request samples are taken |
| every three seconds, during which you can watch as results are added and updated. Note |
| that values for the <code>Average</code>, <code>Min</code>, and <code>Max</code> columns |
| are represented in milliseconds. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/summary-report.png" |
| class="margin-around b-all" alt="JMeter - Summary Report" style="width:688px" |
| title="Summary Report displays results from the completed test plan"> |
| |
| <p>From the results displayed in the above image, we can observe that:</p> |
| |
| <ul style="margin: 7px 0 0 -1.7em"> |
| <li>The server, when loaded with a single user, provides a total <em>throughput</em> of |
| approximately 41 per minute. In other words, the server is capable of serving all |
| requests within the test plan 41 times within a minute. According to the |
| <a href="http://jakarta.apache.org/jmeter/usermanual/glossary.html#Throughput" |
| target="_blank">JMeter User's Manual</a>, the throughput is calculated as: |
| <code>(number</code> <code>of</code> <code>requests)/(total</code> <code>time)</code>, |
| and includes any delay inserted between samples, as it is supposed to represent |
| the load on the server. When we consider that the <code>user</code> <code>delay</code> |
| occurs for 5 seconds between each request (9 times in total, 9 * 5 seconds = 45 seconds), |
| we see that with the server would theoretically be utilized for only approximately |
| 15 seconds.</li> |
| |
| <li>The <code>AffableBean/checkout</code> request, recorded at 33 milliseconds, takes |
| much longer to process than most other requests. This is likely due to the fact that |
| the initial request is redirected to the HTTP + SSL protocol on port 8181. So there |
| are essentially two requests taking place.</li> |
| |
| <li>The <code>AffableBean/purchase</code> request, recorded at 147 milliseconds, takes |
| the most time to be served. This is likely due to both the write operations required |
| on the database, and the fact that client-server communication takes place over an |
| encrypted channel (i.e., using HTTPS).</li> |
| |
| <li>According to the <code>Error</code> <code>%</code> column, no errors occurred from |
| running the test. In other words, all server responses included an HTTP 200 status.</li> |
| |
| <li>The <code>Avg.</code> <code>Bytes</code> column represents the average size of the |
| sample response. We see that the JQuery core library (<code>jquery-1.4.2.js</code>) |
| is the largest file that is served in the test plan, at nearly 164 KB. Because the |
| file is served each time a new user accesses the site, it may be worth linking to |
| this file on a public <a href="http://en.wikipedia.org/wiki/Content_delivery_network" |
| target="_blank">content delivery network</a> (CDN) instead of maintaining it on the |
| server. "Unburdening" the server in this manner could have a notable |
| effect on its overall performance. |
| |
| <br><br> |
| <p class="tips">For further information, see the official jQuery documentation: |
| <a href="http://docs.jquery.com/Downloading_jQuery#CDN_Hosted_jQuery" target="_blank">CDN |
| Hosted jQuery</a>.</p></li> |
| </ul></li> |
| |
| <li>Click the View Results Tree node. Here you see the individual results from each of the sample |
| requests, listed in the order in which they occurred. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/view-results-tree.png" |
| class="margin-around b-all" alt="JMeter - View Results Tree" style="width:688px" |
| title="View Results Tree displays a tree of all sample responses listed in the order in which they occurred"> |
| |
| <br> |
| The green ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/jmeter-ok-icon.png" |
| alt="success icon"> ) icons indicate an HTTP status response of 200. In the above image, under |
| 'Sampler result' in the right panel, note that the Thread Name for the selected sample is |
| 'AffableBean Users 1-1'. The second '1' represents the thread (i.e., user) number. When testing |
| multiple threads, you can use View Results Tree listener to pinpoint exactly when each thread |
| makes a request within the test. Finally, in the image above, note that the 'HTML (download |
| embedded resources)' option is selected in the lower left corner. When you select the 'Response |
| data' tab in the right panel, JMeter attempts to render the response as it would display in a |
| browser. |
| |
| <br><br> |
| <p class="notes"><strong>Note:</strong> Red warning |
| ( <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/jmeter-warning-icon.png" |
| alt="warning icon"> ) icons indicate that requests are not being handled properly |
| (i.e., HTTP 404 status messages are being sent). While this begins to happen when a |
| server reaches its performance capacity, 404 status messages under a normal load |
| suggest that the application is not functionally stable. You should then check the |
| server log to determine why requests are failing, and make changes to your application. |
| |
| <br><br> |
| In the coming steps, we'll add an increasing number of users to the test, and examine the |
| server's overall throughput.</li> |
| |
| <li>Click the JMeter Template Plan node, then make the following changes to User Defined Variables: |
| |
| <ul style="margin: 7px 0 0 -1.7em"> |
| <li><strong><code>nb.users</code>:</strong> <code>20</code></li> |
| <li><strong><code>nb.rampup</code>:</strong> <code>20</code></li> |
| </ul> |
| |
| The <code>nb.rampup</code> variable is used in the <code>AffableBean</code> <code>Users</code> |
| Thread Group panel, and specifies the ramp-up period in seconds. In this case, if we test 20 |
| users and the ramp-up period is 20 seconds, then a new user will begin sending requests |
| every second.</li> |
| |
| <li>Clear the results from the previous test by choosing Run > Clear All (Ctrl-E; ⌘-E on Mac).</li> |
| |
| <li>Click the Graph Results node so that you are able to view the test results while the |
| test is running.</li> |
| |
| <li>Run the test plan. Choose Run > Start (Ctrl-R; ⌘-R on Mac) from the main menu. |
| When the test plan runs, make the following observations: |
| |
| <ul style="margin: 7px 0 0 -1.7em"> |
| <li>A green square displays in the upper right corner of the interface, indicating that |
| the test plan is running. Adjacent to the square is a ratio listing the number of |
| active threads against the total number of threads being tested. For example, |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/jmeter-active-threads.png" |
| class="b-all" style="margin:2px 0 -2px 0" alt="Green square with number of active threads"> demonstrates that |
| the test is running, and that there are currently 15 active threads of a total of 20. |
| Because of the ramp-up period, you should notice that the number of active threads |
| increases each second to 20, remains at 20 for some time, then gradually decreases |
| to zero, at which the square becomes gray indicating that the test has terminated.</li> |
| |
| <li>You can filter the graphs you wish to display by selecting the checkboxes above the |
| graph. For an explanation of Median and Deviation, refer to the |
| <a href="http://jakarta.apache.org/jmeter/usermanual/glossary.html" target="_blank">JMeter |
| User's Manual Glossary</a>. The image below displays graphs for Average and Throughput |
| only. The metric values provided at the bottom of the graph apply to the most recent sample.</li> |
| |
| <li>From the green line designating throughput, we see that the server was able to maintain |
| a nearly consistent value as the load increased to 20 users. Toward the end of the test, |
| as user number decreases, we see that the throughput slightly lessens. We can assume |
| that this is simply due to the fact that there are fewer requests per unit of time.</li> |
| |
| <li>While the vertical line of the graph represents time (in milliseconds), this doesn't |
| apply to the throughput measurement (nor the measurement for standard deviation, for |
| that matter). The throughput represents the number of requests the server processes |
| during the total time which the test plan runs. In the image below, note that the |
| throughput value listed at the bottom of the graph is: <code>577.496/minute</code>. |
| Switching to the Summary Report, the total throughput value is listed as: |
| <code>9.6/second</code>. The two values equate: <code>577.496/60 = 9.6</code>.</li> |
| |
| <li>The blue line, designating the average time (in milliseconds), increases dramatically |
| at the end of the test. If you examine the final request samples in the View Results |
| Tree, you can get an idea why. The final samples taken are all <code>/checkout</code> |
| and <code>/purchase</code> requests, which as we've already seen, take much longer than |
| the other requests in the test plan.</li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/graph-results.png" |
| class="margin-around b-all" alt="JMeter - Graph Results" style="width:688px" |
| title="Graph Results shows a graph that plots all sample times"> |
| </li> |
| </ol> |
| |
| |
| <h3 id="stressTest">Stress Testing</h3> |
| |
| <p>In the tests we've so far conducted, the throughput for a single user was calculated at 41/min, |
| and for 20 users it was 577/min. You can continue to increase the demand on the server to see |
| if it's possible to determine what the maximum throughput value can be, given your local setup. |
| This is an example of <a href="http://en.wikipedia.org/wiki/Stress_testing" target="_blank">stress |
| testing</a>, in which the system resources are purposely worked to their limits in order to |
| arrive at a maximum capacity value.</p> |
| |
| <p>You can adjust the User Defined Variables, then run the test plan and examine the results. |
| For example, experiment by increasing the number of users, or decreasing the ramp-up period |
| or delay between requests.</p> |
| |
| <p class="alert"><strong>Important:</strong> When stress testing, you should monitor your computer's |
| CPU and memory levels. If you see that JMeter is not able to record results under a specific |
| load and becomes unresponsive, you can try to stop the test by choosing Run > Stop (Ctrl-.; |
| ⌘-. on Mac). Otherwise, if JMeter does not respond, you may need to kill the JMeter |
| process from your computer's task manager.</p> |
| |
| <p>The following table lists results recorded in JMeter's |
| <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#Summary_Report" |
| target="_blank">Summary Report</a>, from increasing the number of users with each test run.</p> |
| |
| <table> |
| <tr> |
| <td style="vertical-align:top"> |
| <table class="margin-around" style="width:350px"> |
| <tbody> |
| <tr> |
| <th class="tblheader" scope="col">Users</th> |
| <th class="tblheader" scope="col">Ramp-up<br><small>(seconds)</small</th> |
| <th class="tblheader" scope="col">Average<br><small>(milliseconds)</small></th> |
| <th class="tblheader" scope="col">Throughput</th> |
| <th class="tblheader" scope="col">Error %</th> |
| </tr> |
| <tr> |
| <td class="tbltd1">1</td> |
| <td class="tbltd1">(n/a)</td> |
| <td class="tbltd1">11</td> |
| <td class="tbltd1">41/min</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">20</td> |
| <td class="tbltd1">20</td> |
| <td class="tbltd1">9</td> |
| <td class="tbltd1">577/min</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">50</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">8</td> |
| <td class="tbltd1">22.2/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">80</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">8</td> |
| <td class="tbltd1">35.3/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">100</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">7</td> |
| <td class="tbltd1">44.1/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">120</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">7</td> |
| <td class="tbltd1">52.9/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">150</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">7</td> |
| <td class="tbltd1">66.0/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">200</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">11</td> |
| <td class="tbltd1">87.5/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">250</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">16</td> |
| <td class="tbltd1">109.5/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">300</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">35</td> |
| <td class="tbltd1">130.1/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">350</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">54</td> |
| <td class="tbltd1">150.4/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">400</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">120</td> |
| <td class="tbltd1">164.3/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">450</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">394</td> |
| <td class="tbltd1">158.4/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">500</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">355</td> |
| <td class="tbltd1">182.9/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">550</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">369</td> |
| <td class="tbltd1">198.4/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">600</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">446</td> |
| <td class="tbltd1">206.4/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">650</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">492</td> |
| <td class="tbltd1">219.9/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">700</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">599</td> |
| <td class="tbltd1">225.9/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">750</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">668</td> |
| <td class="tbltd1">231.9/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">800</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">875</td> |
| <td class="tbltd1">225.6/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">850</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">976</td> |
| <td class="tbltd1">230.5/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">900</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">1258</td> |
| <td class="tbltd1">220.9/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">950</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">1474</td> |
| <td class="tbltd1">215.8/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| <tr> |
| <td class="tbltd1">1000</td> |
| <td class="tbltd1">25</td> |
| <td class="tbltd1">1966</td> |
| <td class="tbltd1">190.8/sec</td> |
| <td class="tbltd1">0.00%</td> |
| </tr> |
| </tbody> |
| </table> |
| </td> |
| |
| <td class="valign-top"> |
| |
| <p style="margin: 20px 0 0 5px"><strong>Notes and observations:</strong></p> |
| |
| <ul style="margin: 5px 0 0 -.7em"> |
| <li>Maximum throughput was recorded at 231.9/sec for 750 users. Throughput |
| is generally much quicker for requests in the first part of the test |
| plan, and then decreases as <code>/checkout</code> and <code>/purchase</code> |
| requests are served. Because the elapsed time for these requests begins |
| to dramatically increase beyond 750 users, the overall throughput begins |
| to decrease beyond this number.</li> |
| |
| <li>When testing for 500 users, JMeter became unresponsive and it was necessary |
| to shut it down from the task manager. It is likely that JMeter was running |
| out of memory to record and display results for the |
| <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#Graph_Results" |
| target="_blank">Graph Results</a> and |
| <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#View_Results_Tree" |
| target="_blank">View Results Tree</a> listeners. These two listeners were |
| removed from the test plan, and results for 500 - 1000 users were then recorded |
| using the <a href="http://jakarta.apache.org/jmeter/usermanual/component_reference.html#Summary_Report" |
| target="_blank">Summary Report</a> listener only.</li> |
| |
| <li>In all tests, the <code>Error</code> <code>%</code> column remained at |
| <code>0.00%</code>. The server was able to successfully respond to all |
| requests, even when the computer's CPU levels were at a maximum, and JMeter |
| was lagging in its ability to display results. This would indicate that the |
| bottleneck in these tests was the computer's processing resources. (The |
| computer had available memory for all tests.)</li> |
| |
| <li>The Average represents the average elapsed time (in milliseconds) |
| for all requests serviced in the test plan. While the average values |
| for the most demanding tests were still under 2 seconds, the Summary |
| Report's Maximum values recorded for elapsed time were much higher, |
| reaching nearly 70 seconds for the <code>/purchase</code> request. |
| When determining what resources are required for a normal load, consider |
| that these results do not include network time, and that most users |
| are willing to wait at most 4 - 8 seconds for a |
| response.<sup><a href="#footnote2TestProfile" id="2TestProfile" |
| style="text-decoration:none">[2]</a></sup> |
| </li> |
| </ul> |
| </td> |
| </tr> |
| </table> |
| |
| <p style="margin-top: 0">If the production server is on a machine that has resources similar |
| to those of your development environment, and assuming your computer is not running other |
| CPU-intensive processes while tests are conducted, you can get a rough idea of how many |
| users can be served by examining your computer's CPU usage during tests. For example, if |
| it has been decided that CPU levels for normal and peak loads will be approximately 30% |
| and 70%, respectively, you can watch the CPU monitor as you increase the number of users |
| with each run of the test plan. The following images suggest 150 users could be served |
| during a normal load, and 400 during a peak load.</p> |
| |
| <table> |
| <tr> |
| <td><strong>CPU levels for 150 users</strong></td> |
| <td><strong>CPU levels for 400 users</strong></td> |
| </tr> |
| <tr> |
| <td> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/150-users.png" |
| alt="CPU graph for 150 users" class="margin-around b-all" |
| title="CPU levels when running the test with 150 users"></td> |
| <td> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/400-users.png" |
| alt="CPU graph for 400 users" class="margin-around b-all" |
| title="CPU levels when running the test with 400 users"></td> |
| </tr> |
| </table> |
| |
| <p>Keep in mind that when running tests in this manner, your local server is |
| competing with JMeter for the computer's resources. Eventually, you'll want |
| to test your production server remotely to get more accurate results. See the |
| following resources for more information:</p> |
| |
| <ul style="margin: 0 0 0 -1.7em"> |
| <li><a href="http://jakarta.apache.org/jmeter/usermanual/remote-test.html" |
| target="_blank">JMeter User's Manual: 15. Remote Testing</a></li> |
| <li><a href="http://jakarta.apache.org/jmeter/usermanual/jmeter_distributed_testing_step_by_step.pdf" |
| target="_blank">JMeter Distributed Testing Step-by-Step</a> [pdf]</li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2 id="profile">Using the NetBeans Profiler</h2> |
| |
| <p>The NetBeans Profiler is an |
| <a href="http://www.developer.com/java/other/article.php/3795991/Winners-of-the-Developercom-Product-of-the-Year-2009-Are-Announced.htm" |
| target="_blank">award winning</a> development utility that enables you to profile |
| and monitor your application's CPU and memory usage, and thread status. The Profiler |
| is an integral component of the IDE, and offers a click-of-the-button profiling environment |
| that aids you when handling memory and performance-related issues. For an overview of |
| the Profiler's features, see |
| <a href="../../../../features/java/profiler.html" target="_blank">NetBeans IDE 6.9 |
| Features: Profiler</a>.</p> |
| |
| <p>When profiling web applications, you can use the Profiler to work in tandem with a load |
| script, such as a test plan created in JMeter. Often, problems start to arise only after |
| your application has been running in a host environment for a certain period of time, and |
| has begun serving multiple concurrent requests. In order to get an idea of how the application |
| will perform before it is migrated to a production environment, you can launch the Profiler, |
| run a test script on the application, and examine the results in the Profiler's interface.</p> |
| |
| <ul> |
| <li><a href="#memoryLeaks">About Memory Leaks</a></li> |
| <li><a href="#monitoring">Monitoring your Application</a></li> |
| <li><a href="#heapWalker">Evaluating Heap Contents with the HeapWalker</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="memoryLeaks">About Memory Leaks</h3> |
| |
| <p>In Java, memory leaks occur when objects continue to be referenced even after they are no |
| longer needed. This prevents Java's built-in garbage collection mechanism from destroying |
| these objects, and consequently they remain in existence throughout the life of your |
| application. When these objects are regularly created, the Java Virtual Machine (JVM) <em>heap</em> |
| will continue to grow over time, ultimately resulting in an <code>OutOfMemoryError</code> |
| when the heap is eventually exhausted.</p> |
| |
| <p>The JVM heap represents memory that is dynamically allocated by the Virtual Machine during |
| runtime. Because the GlassFish server runs on Java, it relies on the JVM heap for memory |
| resources during execution. All applications that are deployed to the server can be perceived |
| as extensions to this rule; in other words when your web application runs, it consumes |
| resources from the JVM heap.</p> |
| |
| <p>When building web applications, you need to be mindful of memory allocation. Aside from |
| avoiding memory leaks in your code, you must ensure that the JVM heap is large enough to |
| accommodate all user sessions at a given time, and that your system is able to support the |
| maximum heap size set by your server.</p> |
| |
| |
| <h3 id="monitoring">Monitoring your Application</h3> |
| |
| <p>The following example aims to familiarize you with the Profiler's interface, and demonstrates |
| how you can utilize its functionality to ensure that the <code>AffableBean</code> application |
| will continue to perform efficiently after it has been serving client requests for some time. |
| In this example, you download and add a new JMeter test plan, |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FuseCaseTestRandom.jmx"><code>useCaseTestRandom.jmx</code></a>, |
| to the project. The new test plan is an advanced version of the one you created earlier |
| in this unit. It makes use of JMeter's conditional and random controllers to adapt a slightly |
| more realistic simulation of the tutorial's use-case.</p> |
| |
| <p>Consider that only a small fraction of visits to an e-commerce site will result in a completed |
| order. If you recall from units 8 and 9, <a href="#manage-sessions">Managing Sessions</a> |
| and <a href="#transaction">Integrating Transactional Business Logic</a>, the application |
| terminates the user session upon a successfully completed order. In other words, with each |
| completed order, the server is able to free up any resources that were previously tied to the |
| session. Now, consider the far more common scenario of a user not completing an order, but |
| simply navigating away from the site. Based on the session time-out which you specified in the |
| application's web deployment descriptor, the server will need to wait a period of time before |
| it can free any resources tied to the session. The new load script, <code>useCaseTestRandom.jmx</code>, |
| is configured so that on average one in ten user threads completes an order. Our goal by running |
| this load script is to determine whether the application's host environment (i.e., the GlassFish |
| server running locally on your computer) has enough memory capacity to provide continuous, fast |
| service for an extended period of time.</p> |
| |
| <p class="notes"><strong>Note:</strong> Recall that in |
| <a href="manage-sessions.html#time-out">Managing Sessions: Handling Session Time-Outs</a>, |
| you set the <code>AffableBean</code> session time-out to 10 minutes.</p> |
| |
| <ol> |
| <li>Download |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FuseCaseTestRandom.jmx"><code>useCaseTestRandom.jmx</code></a> |
| and add it to the <code>AffableBean</code> project. To add it to the project, copy it from |
| your computer's file system (Ctrl-C; ⌘-C on Mac), then in the IDE, open the Files |
| window (Ctrl-2; ⌘-2 on Mac), right-click the <code>jmeter</code> folder and choose |
| Paste. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/files-window.png" |
| alt="JMeter test plans displayed in Files window" class="margin-around b-all" |
| title="JMeter test plans contained in 'jmeter' folder within project"> |
| |
| <br> |
| <p class="notes"><strong>NetBeans 6.8 note:</strong> The <code>useCaseTestRandom.jmx</code> |
| script is not compatible with the JMeter Kit plugin for NetBeans 6.8. Because the script |
| utilizes various logic controllers which unfortunately are not available in JMeter |
| version 2.2, it will not run on the JMeter implementation in NetBeans 6.8. In order to |
| become familiar with the Profiler, use <code>useCaseTest.jmx</code> in this exercise |
| instead. If you use <code>useCaseTest.jmx</code>, you need to set the load script to |
| run continuously. To do so, open the script in JMeter, select the <code>AffableBeanUsers</code> |
| thread group, then in the main panel, select the 'Forever' checkbox for the Loop Count |
| field.</p></li> |
| |
| <li>If you are running the Profiler for the first time, you need to perform a calibration step |
| on the JDK. To do so, choose Profile > Advanced Commands > Run Profiler Calibration. |
| For more information, refer to the NetBeans User FAQ wiki: |
| <a href="http://wiki.netbeans.org/FaqProfilerCalibration" target="_blank">What exactly does |
| the Profiler Calibration mean?</a>.</li> |
| |
| <li>Click the Profile Project ( <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/profile-btn.png" |
| alt="Profile Project button"> ) button. When a project is profiled for the first time, its |
| build script must be modified to enable profiling. The IDE warns you that it will modify the |
| project's build script. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/enable-profiling.png" |
| alt="Profiler dialog box warning that build script will be modified" class="margin-around b-all" |
| title="The project build script must be modified to enable profiling"> |
| |
| <p class="notes"><strong>Note:</strong> You can undo this action at a later point by choosing |
| Profile > Advanced Commands > Unintegrate Profiler from the main menu. Alternatively, |
| you can switch to the Files window, delete your project's <code>build.xml</code> file, then |
| rename the <code>build-before-profiler.xml</code> file to <code>build.xml</code>.</p></li> |
| |
| <li>Click OK. The project's build file is modified, and the Profiler window opens for the project. |
| The window enables you to select from one of three profiling tasks: |
| |
| <ul style="margin: 7px 0 0 -1.7em"> |
| <li><strong>Monitor Application:</strong> Provides obtain high-level information about |
| properties of the target JVM, including thread activity and memory allocations.</li> |
| <li><strong>Analyze Performance:</strong> Provides detailed data on application performance, including |
| the time to execute methods and the number of times the method is invoked.</li> |
| <li><strong>Analyze Memory:</strong> Provides detailed data on object allocation and garbage |
| collection.</li> |
| </ul> |
| |
| <li>Click the Monitor button in the left column. Select the 'LoadGenerator Script' option, then choose |
| <code>useTestCaseRandom.jmx</code> from the drop-down list. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/monitor-application.png" |
| alt="Profiler window - Monitor Application" class="margin-around b-all" id="profilerWindow" |
| title="Profiler window opens, enabling task selection and configuration"></li> |
| |
| <li>Click Run. The IDE takes the following actions: |
| |
| <ul style="margin: 7px 0 0 -1.7em"> |
| <li>Starts the GlassFish server in profile mode. (If the server is already running, it is first stopped.)</li> |
| <li>Deploys the web application to GlassFish.</li> |
| <li>Starts a profiling session, attaches the profiler to the server, and opens the Profiler Control Panel in the IDE.</li> |
| <li>Runs the associated load script (<code>useTestCaseRandom.jmx</code>).</li> |
| </ul> |
| |
| <p class="notes"><strong>Note:</strong> If the profiler does not run the load script after starting |
| the application in profile mode, you can invoke it yourself. From the Projects window, right-click |
| the script and choose External Edit. Then, in JMeter, press Ctrl-R (⌘-R on Mac) to run the |
| script. If the left-hand graph displayed by the VM Telemetry Overview depicts the purple area as |
| remaining horizontal (shown below), you can be fairly certain that the load script is not running.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/vm-telemetry-overview-heap.png" |
| alt="VM Telemetry Overview - JVM Heap" class="margin-around b-all" style="margin:0 0 0 35px" |
| title="The server is loaded, but the load script is not running"></li> |
| |
| <li>In the Profiler Control Panel, click the Threads ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/threads-btn.png" |
| alt="VM Telemetry button"> ) button. The Threads window opens to display all threads |
| maintained by the server while the application is running. You can select Live Threads Only, |
| or Finished Threads Only in drop-down at the top of the window in order to filter the display |
| according to live or finished threads. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/live-threads.png" |
| alt="Threads window" class="margin-around b-all" style="width:688px" |
| title="View live threads maintained by the server at runtime"> |
| |
| <p class="tips">You can select the Enable Threads Monitoring option in the Profiler window |
| (displayed <a href="#profilerWindow">above</a>). This will trigger the Threads window to |
| open by default when running the Profiler.</p></li> |
| |
| <li>In the Profiler Control Panel, click the VM Telemetry ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/vm-telemetry-btn.png" |
| alt="VM Telemetry button"> ) button. |
| |
| <br><br> |
| Similar to the VM Telemetry Overview, the VM Telemetry window provides views on the |
| JVM heap, garbage collection (GC), as well as threads and loaded classes.</li> |
| |
| <li>Ensure that the Memory (Heap) tab is selected at the bottom of the window, then allow the |
| Profiler to monitor the heap while the load script runs against the application. |
| |
| <br><br> |
| You can hover your cursor over the graph to view real-time measurements of the heap size versus the used heap. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/heap-popup.png" |
| alt="Popup displaying heap measurements in the Memory (Heap) tab of the VM Telemetry window" |
| class="margin-around b-all" |
| title="Hover your cursor over the graph for a real-time display of heap measurements"> |
| |
| <p class="tips">Click the Scale to Fit ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/scale-to-fit-btn.png" |
| alt="Scale to Fit button"> ) button above the graph to maintain a continuous view of the entire |
| monitoring session.</p> |
| |
| <br> |
| The image below shows the state of the heap after monitoring the server for approximately |
| three hours while running the <code>useTestCaseRandom.jmx</code> script continuously with |
| 150 simultaneous users. The <code>AffableBean</code> application running on the GlassFish |
| server uses under 175 MB of the JVM heap. |
| |
| <a href="../../../../images_www/articles/73/javaee/ecommerce/test-profile/heap-monitor.png" rel="lytebox" |
| title="The profiler monitors the JVM heap while the JMeter load script runs continuously against the application" |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/heap-monitor.png" |
| alt="VM Telemetry - Memory (Heap)" class="margin-around b-all" style="width: 688px" |
| title="Click to enlarge" id="vmTelemetryMonitor"></a> |
| </li> |
| </ol> |
| |
| <h3 id="heapWalker">Evaluating Heap Contents with the HeapWalker</h3> |
| |
| <p>The HeapWalker is a tool that is built into the NetBeans Profiler, which allows you to examine |
| JVM heap contents. You can use it to browse classes and instances of classes on the heap, fields |
| of each instance or class, and references to each instance.</p> |
| |
| <p>The HeapWalker is particularly useful when locating the cause of memory leaks in your code. You can |
| set the Profiler to automatically take a heap dump if an <code>OutOfMemoryError</code> occurs |
| when you are profiling an application. You can then use the HeapWalker to inspect the heap dump |
| and determine which objects were consuming the most memory.</p> |
| |
| <p>This functionality is enabled by default, but you can view and modify Profiler settings from |
| the IDE's Options window (Tools > Options; NetBeans > Preferences on Mac). From the Options |
| window, select Miscellaneous, then select the Profiler tab. In the On OutOfMemoryError field, |
| note that 'Save heap dump to profiled project' option is selected.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/profiler-options.png" |
| alt="Options window - Profiler options" class="margin-around b-all" style="margin-top:0" |
| title="A heap dump is taken by default if the JVM runs out of memory for the profiled application"> |
| |
| <p>For example, if the GlassFish server utilizes 512 MB of memory, and the JVM attempts to allocate |
| more than 512 MB of memory to the JVM heap (represented by the pink area in the heap size graph |
| of the VM Telemetry monitor, <a href="#vmTelemetryMonitor">shown above</a>), an <code>OutOfMemoryError</code> |
| will occur, and the IDE will ask you if you would like to view the heap in the HeapWalker.</p> |
| |
| <p>To take a heap dump while your application is being profiled, choose Profile > Take Heap Dump |
| from the main menu.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/take-heap-dump.png" |
| alt="Profiler menu" class="margin-around b-all" style="margin-top:0" |
| title="To take a heap dump, choose Profile > Take Heap Dump from the main menu"> |
| |
| <p>The following example depicts a heap dump from running the <code>useCaseTestRandom.jmx</code> |
| script at 500 users, ramp-up period at 100 seconds, and with a loop count of 5. The HeapWalker's |
| Summary provides an Inspect panel which enables you to locate the largest objects in the heap. |
| Specify the number of objects you want to search for, then click Find.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/inspect-heap.png" |
| alt="HeapWalker - Summary - Inspect panel" class="margin-around b-all" style="margin-top:0" |
| title="Use the Inspect panel to determine the largest objects in the heap"> |
| |
| <p>In the above image, you can see that for the <code>AffableBean</code> application, the largest |
| object in the heap dump is an instance of the <code>org.apache.catalina.session.StandardManager</code> |
| class, with a retained size of nearly 79 MB.</p> |
| |
| <p>Clicking the object name enables you to open the Instances view on the object. When you do so, |
| you can see the instances of the class that exist on the heap (left column), the fields contained |
| in the class, and their values (right column, top), and other objects on the heap referring |
| to the instance (right column, bottom).</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/instances-view.png" |
| alt="HeapWalker - Instances view" class="margin-around b-all" style="width:728px; margin-top:0" |
| title="Use the Instances view to examine class instances, their fields and references"> |
| |
| <p>In the above image, it appears that 706 <code>StandardSession</code> objects were active on |
| the heap, a result of the load script simulating multiple user sessions. The server must have |
| sufficient memory resources to maintain session objects during periods of high traffic.</p> |
| |
| <p>You can save (Ctrl-S; ⌘-S on Mac) heap dumps. When you do so, they become listed in the |
| Profiler Control Panel under Saved Snapshots.</p> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/test-profile/saved-snapshots.png" |
| alt="Profiler Control Panel - Saved Snapshots" class="margin-around b-all" style="margin-top:0" |
| title="Saved heap dumps can be loaded from the Profiler Control Panel"> |
| </div> |
| |
| |
| <br> |
| <h2 id="glassFishTune">Tuning the GlassFish Server</h2> |
| |
| <p>In order to gain optimum performance for your application when it is deployed to GlassFish, |
| you should become acquainted with various tuning parameters which can be adjusted from the |
| Administration Console. The following tips are taken directly from the white paper, |
| <a href="https://www.sun.com/offers/details/OptimizeGlassFishPerformance.xml" target="_blank">Optimize |
| GlassFish Performance in a Production Environment</a>. Although the paper focuses on GlassFish |
| v2, the tuning tips can be directly applied to GlassFish v3 or Open Source Edition 3.0.1.</p> |
| |
| <p class="tips">There are various mapping changes that occurred between GlassFish v2 and v3. Tables |
| listing changes are provided on the GlassFish wiki: <a href="http://wikis.sun.com/display/GlassFish/GrizzlyConfigOnePager" |
| target="_blank">GrizzlyConfig One Pager</a>.</p> |
| |
| <p>The GlassFish Administration Console can be accessed from the IDE's Services window:</p> |
| |
| <ol style="margin-top:0"> |
| <li>Open the Services window (Ctrl-5; ⌘-5 on Mac) and expand the Servers node |
| so that the GlassFish server node is visible.</li> |
| |
| <li>Ensure that the GlassFish server is running. If the server is running, a small green |
| arrow is displayed next to the GlassFish icon ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/gf-server-running-node.png" |
| alt="GlassFish server node in Services window"> ). If you need to start it, right-click |
| the server node and choose Start.</li> |
| |
| <li>Right-click the GlassFish server node and choose View Admin Console. The login form |
| for the GlassFish Administration Console opens in a browser.</li> |
| |
| <li>Log into the Administration Console by typing <code>admin</code> / <code>adminadmin</code> |
| for the username / password.</li> |
| </ol> |
| |
| <p>From the GlassFish Administration Console, you can view and make adjustments to the following |
| parameters.</p> |
| |
| <ul> |
| <li><a href="#tip3">Tip 3: Java Heap Size</a></li> |
| <li><a href="#tip6">Tip 6: HTTP Request Processing Threads</a></li> |
| <li><a href="#tip10">Tip 10: JDBC Tuning</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="tip3">Tip 3: Java Heap Size</h3> |
| |
| <p>From <a href="https://www.sun.com/offers/details/OptimizeGlassFishPerformance.xml" target="_blank">Optimize |
| GlassFish Performance in a Production Environment</a>:</p> |
| |
| <blockquote style="margin-top: 0"> |
| <em>The size of the heap is determined by the Java options -Xmx (maximum) and -Xms |
| (minimum). While a larger heap can contain more objects and reduce the frequency |
| of garbage collection, it may result in longer garbage collection times especially |
| for a full GC cycle. The recommendation is to tune the heap based on the size of |
| total available memory in your system, process data model (32-bit or 64-bit) and |
| operating system.</em> |
| </blockquote> |
| |
| <ol> |
| <li>In the Tree which displays in the left column of the Administration Console, |
| expand the Configuration node, then click JVM Settings.</li> |
| |
| <li>In the main panel, select the JVM Options tab.</li> |
| |
| <li>Scroll the list of options and note the <code>-Xmx</code> option: |
| |
| <pre class="examplecode">-Xmx512m</pre> |
| |
| The GlassFish server (v3 and Open Source Edition 3.0.1) sets the heap to 512 MB |
| by default. If you wanted to increase the heap size to 1 GB, you would enter |
| '<code>-Xmx1024m</code>', click the Save button in the upper right corner, and |
| then restart the server.</li> |
| </ol> |
| |
| |
| <h3 id="tip6">Tip 6: HTTP Request Processing Threads</h3> |
| |
| <p>From the <a href="http://docs.sun.com/app/docs/doc/819-3681/abefm" target="_blank">Sun Java |
| System Application Server 9.1 Performance Tuning Guide</a>:</p> |
| |
| <blockquote style="margin-top: 0"> |
| <em>The</em> [Max Thread Pool Size] <em>parameter specifies the maximum number of |
| simultaneous requests the server can handle. The default value is 5. When the server |
| has reached the limit or request threads, it defers processing new requests until the |
| number of active requests drops below the maximum amount. Increasing this value will |
| reduce HTTP response latency times. |
| |
| <br><br> |
| In practice, clients frequently connect to the server and then do not complete their |
| requests. In these cases, the server waits a length of time specified by the Idle Thread |
| Timeout parameter.</em> [900 seconds, i.e., 15 minutes, is the default entry for GlassFish |
| v3 and Open Source Edition 3.0.1.] |
| |
| <br><br> |
| <em>Also, some sites do heavyweight transactions that take minutes to complete. Both of |
| these factors add to the maximum simultaneous requests that are required. If your site |
| is processing many requests that take many seconds, you might need to increase the number |
| of maximum simultaneous requests. |
| |
| <br><br> |
| Adjust the thread count value based on your load and the length of time for an average |
| request. In general, increase this number if you have idle CPU time and requests that are |
| pending; decrease it if the CPU becomes overloaded. If you have many HTTP 1.0 clients |
| (or HTTP 1.1 clients that disconnect frequently), adjust the timeout value to reduce the |
| time a connection is kept open. |
| |
| <br><br> |
| Suitable Request Thread Count values range from 100 to 500, depending on the load. If your |
| system has extra CPU cycles, keep incrementally increasing thread count and monitor performance |
| after each incremental increase. When performance saturates (stops improving), then stop |
| increasing thread count.</em> |
| </blockquote> |
| |
| <ol> |
| <li>In the Administration Console Tree, expand the Configuration node, then click |
| Thread Pools. |
| |
| <br><br> |
| The GlassFish server provides two thread pools by default. The <code>http-thread-pool</code> |
| thread pool is configured for use by network listeners, while <code>thread-pool-1</code> is |
| configured for use by the ORB (object request broker) for RMI/IIOP requests. |
| (A stand-alone web application deployed over a non-distributed environment, such |
| as the <code>AffableBean</code> application, relies on the <code>http-thread-pool</code> |
| by default.)</li> |
| |
| <li>Under the Thread Pool ID column, click <code>http-thread-pool</code>.</li> |
| |
| <li>In the <strong>Max Thread Pool Size</strong> field, adjust the maximum number of threads |
| available to the thread pool.</li> |
| |
| <li>Click the Save button in the upper right corner, and then restart the server.</li> |
| </ol> |
| |
| |
| <h3 id="tip10">Tip 10: JDBC Tuning</h3> |
| |
| <p>From <a href="https://www.sun.com/offers/details/OptimizeGlassFishPerformance.xml" target="_blank">Optimize |
| GlassFish Performance in a Production Environment</a>:</p> |
| |
| <blockquote style="margin-top: 0"> |
| <em>If your application uses Java DataBase Connectivity (JDBC) software for database access, |
| it may be beneficial to tune your database connection pool. A general rule of thumb is to |
| tune the value for <code>max-pool-size</code> and <code>steady-pool-size</code> to the |
| same number of HTTP request processing threads. If your JDBC driver supports this |
| feature, it is advisable to use JDBC drivers that use statement caching to re-use |
| prepared statements.</em> |
| </blockquote> |
| |
| <ol> |
| <li>In the Administration Console Tree, expand the Resources > JDBC > Connection Pools node, |
| then click the <code>AffableBeanPool</code> node.</li> |
| |
| <li>In the General tab under Pool Settings, specify values for the following fields: |
| |
| <ul style="margin: 7px 0 0 -1.7em"> |
| <li><strong>Initial and Minimum Pool Size:</strong> (<code>steady-pool-size</code>) |
| Minimum and initial number of connections maintained in the pool.</li> |
| |
| <li><strong>Maximum Pool Size:</strong> (<code>max-pool-size</code>) |
| Maximum number of connections that can be created to satisfy client requests.</li> |
| |
| <li><strong>Pool Resize Quantity:</strong> (<code>pool-resize-quantity</code>) |
| Number of connections to be removed when pool idle timeout expires.</li> |
| |
| <li><strong>Idle Timeout:</strong> (<code>idle-timeout-in-seconds</code>) |
| Maximum time that connection can remain idle in the pool.</li> |
| |
| <li><strong>Max Wait Time:</strong> (<code>max-wait-time-in-millis</code>) |
| Amount of time caller waits before connection timeout is sent.</li> |
| </ul></li> |
| |
| <li>Click the Save button in the upper right corner, and then restart the server.</li> |
| </ol> |
| |
| <p class="tips">Connection pool settings can also be specified in the <code>sun-resources.xml</code> descriptor:</p> |
| |
| <pre class="examplecode" style="margin-top:0; margin-left:35px; width:685px"> |
| <jdbc-connection-pool <strong>max-pool-size</strong>="32" |
| <strong>steady-pool-size</strong>="8" |
| <strong>pool-resize-quantity</strong>="2" |
| <strong>idle-timeout-in-seconds</strong>="300" |
| <strong>max-wait-time-in-millis</strong>="60000"> |
| ... |
| </jdbc-connection-pool></pre></div> |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Testing and Profiling">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <br> |
| <h2 id="seeAlsoTestProfile">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Resources</h3> |
| |
| <ul> |
| <li><a href="http://profiler.netbeans.org/" target="_blank">NetBeans Profiler</a> [product page]</li> |
| <li><a href="../../../../features/java/profiler.html" target="_blank">NetBeans Profiler Features</a></li> |
| <li><a href="../../java/profiler-profilingpoints.html" target="_blank">Using Profiling Points</a></li> |
| <li><a href="http://profiler.netbeans.org/docs/help/6.0/heapwalker.html" target="_blank">Using HeapWalker</a></li> |
| <li><a href="http://wiki.netbeans.org/HeapWalkerDemo" target="_blank">HeapWalker Demo</a></li> |
| <li><a href="../../java/profile-loadgenerator.html" target="_blank">Using a Load Generator</a></li> |
| <li><a href="../profiler-javaee.html" target="_blank">Profiling an Enterprise Application</a></li> |
| <li><a href="../../java/profiler-intro.html" target="_blank">Introduction to Profiling Java Applications</a></li> |
| <li><a href="../../../articles/nb-profiler-uncoveringleaks_pt1.html" target="_blank">Uncovering Memory Leaks Using NetBeans Profiler</a></li> |
| <li><a href="../../../../community/magazine/html/04/profiler.html" target="_blank">Advanced Profiling: Theory in Practice with NetBeans</a></li> |
| <li><a href="https://netbeans.org/download/magazine/01/nb01_profiler.pdf" target="_blank">Exploring the NetBeans Profiler</a> [pdf]</li> |
| <li><a href="https://channelsun.sun.com/media/show/14757?n=playlist&nid=81" target="_blank">The New NetBeans IDE 6 Profiler</a> [screencast]</li> |
| <li><a href="https://netbeans.org/project_downloads/www/flashdemo/profiler-demo1.swf" target="_blank">Getting Started with NetBeans Profiler 5.0</a> [screencast]</li> |
| <li><a href="https://netbeans.org/project_downloads/www/flashdemo/profiler-demo2.swf" target="_blank">Performance Profiling with NetBeans Profiler 5.0</a> [screencast]</li> |
| <li><a href="http://www.javapassion.com/handsonlabs/javatestjmeter/index.html" target="_blank">JavaPassion LAB 5116: Finding Memory Leaks Using the NetBeans Profiler</a></li> |
| </ul> |
| |
| <h3>JMeter</h3> |
| |
| <ul> |
| <li><a href="http://jakarta.apache.org/jmeter/" target="_blank">Apache JMeter</a> [product homepage]</li> |
| <li><a href="http://jakarta.apache.org/jmeter/usermanual/index.html" target="_blank">Apache JMeter: User's Manual</a></li> |
| <li><a href="http://jakarta.apache.org/jmeter/usermanual/jmeter_distributed_testing_step_by_step.pdf" target="_blank">jMeter Distributed Testing</a> [pdf]</li> |
| <li><a href="http://www.javapassion.com/handsonlabs/javatestjmeter/index.html" target="_blank">JavaPassion LAB 1077: JMeter Load Testing</a></li> |
| <li><a href="http://vimeo.com/3453772" target="_blank">Apache JMeter Getting Started Tutorial</a> [screencast]</li> |
| <li><a href="https://www.packtpub.com/beginning-apache-jmeter/book" target="_blank">Apache JMeter</a> [book]</li> |
| </ul> |
| |
| <h3>GlassFish Performance</h3> |
| |
| <ul> |
| <li><a href="http://java.sun.com/performance/reference/whitepapers/tuning.html" target="_blank">Java Tuning White Paper</a></li> |
| <li><a href="http://www.google.co.uk/url?sa=t&source=web&cd=3&ved=0CCMQFjAC&url=http%3A%2F%2Fdeveloper.connectopensource.org%2Fdownload%2Fattachments%2F29851654%2FGlassFishDay2008PerfPreso.pdf&rct=j&q=Tuning%20GlassFish%20Performance%20Tips%20Deep%20Singh&ei=ru7WTNjUPIWUjAenyZTHCQ&usg=AFQjCNHLz1wnaG7h-ey6wsPOOIxV-xoDzA&sig2=aNoCg9O132PgIQ0eWmHx6g&cad=rja">Tuning Your GlassFish - Performance Tips</a> [pdf]</li> |
| <li><a href="https://www.sun.com/offers/details/OptimizeGlassFishPerformance.xml" target="_blank">Optimize GlassFish Performance in a Production Environment</a> [pdf]</li> |
| <li><a href="http://dlc.sun.com/pdf/819-3681/819-3681.pdf" target="_blank">Sun Java System Application Server 9.1 Performance Tuning Guide</a> [pdf]</li> |
| </ul> |
| |
| </div> |
| |
| |
| <br> |
| <h2>References</h2> |
| |
| <ol> |
| <li id="footnote1TestProfile"><a href="#1TestProfile" style="text-decoration:none">^</a> Actually, in JMeter |
| version 2.4, using the HTTP Proxy Server to record HTTPS requests should be possible. See the JMeter User's |
| Manual, <a href="http://jakarta.apache.org/jmeter/usermanual/get-started.html#opt_ssl" |
| target="_blank">2.2.4 SSL Encryption</a> for more details.</li> |
| |
| <li id="footnote2TestProfile"><a href="#2TestProfile" style="text-decoration:none">^</a> The acceptable response |
| time for retail web page response times is debatable, but general concensus seems to waver between 4 and 8 |
| seconds. For example, see: |
| |
| <ul style="margin: 7px 0 0 -0.7em"> |
| <li><a href="http://answers.google.com/answers/threadview/id/716510.html" target="_blank">Google Answers: E-Commerce Site Speed Industry Standards</a></li> |
| <li><a href="http://www.conversionchronicles.com/The_Billion-Dollar_Question_-_What_is_the_Impact_of_Web_Site_Performance_on_E-commerce.html" target="_blank">Conversion Chronicles: What is the Impact of Web Site Performance on E-commerce?</a></li> |
| <li><a href="http://www.akamai.com/html/about/press/releases/2006/press_110606.html" target="_blank">Akamai and JupiterResearch Identify '4 Seconds' as the New Threshold of Acceptability for Retail Web Page Response Times</a></li> |
| <li><a href="http://www.websiteoptimization.com/speed/1/" target="_blank">Response Time: Eight Seconds, Plus or Minus Two</a></li> |
| </ul> |
| </li> |
| </ol> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="conclusion">The NetBeans E-commerce Tutorial - Conclusion</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><strong>Conclusion</strong> |
| |
| <ul style="margin: 5px 0 0 -2em"> |
| <li><a href="#deliver">Delivering your Work</a></li> |
| <li><a href="#framework">Using the JavaServer Faces Framework</a></li> |
| <li><a href="#seeAlsoConclusion">See Also</a></li> |
| <li><a href="#about">About the NetBeans E-commerce Tutorial</a></li> |
| <li><a href="#acknowledge">Acknowledgments</a></li> |
| <li><a href="#disclaimer">Disclaimer</a></li> |
| </ul></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>Congratulations! You have now finished developing the <code>AffableBean</code> application. |
| By following this tutorial, you incrementally built a simple e-commerce application using |
| Java-based technologies. In the process, you became familiar with the NetBeans IDE, and |
| have learned how to use it for the development of Java EE and web projects. Referring |
| back to the <a href="design.html#requirements">customer requirements</a>, you can |
| confirm that each requirement has been fully implemented, and through continuous feedback |
| from the Affable Bean staff, you are confident that they'll be satisfied with the |
| final product. At this stage however, you may ask, "What specifically needs to |
| be delivered to the customer?" and "How can the application become deployed |
| to the customer's production server so that it functions online?" This tutorial |
| unit briefly discusses next steps in terms of handing off deliverables, and concludes |
| with a discussion on how using a framework such as JavaServer Faces could improve the |
| application and benefit your experience when developing future projects.</p> |
| |
| <p>You can view a live demo of the <code>AffableBean</code> application: |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">NetBeans E-commerce |
| Tutorial Demo Application</a>.</p> |
| |
| <p>The completed <code>AffableBean</code> project is also |
| <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252FAffableBean_complete.zip">available |
| for download</a>.</p> |
| |
| <br style="clear:left;"> |
| |
| |
| <br> |
| <h2 id="deliver">Delivering your Work</h2> |
| |
| <p>When delivering your work, you should prepare both a WAR (web archive) file, which is |
| a compiled, ready-to-deploy version of your project, and a source distribution, which |
| contains all the source files you created during the development phase.</p> |
| |
| <ol style="margin-top:0"> |
| <li><strong>WAR File Distribution:</strong> A WAR file is basically a compressed |
| collection of classes, files and other artifacts that constitute the web application. |
| You can create a WAR file for your project using the IDE. In the Projects window, |
| right-click your project node and choose Clean and Build. When your project is |
| built, a WAR file is generated and placed in a <code>dist</code> folder in your |
| project. You can verify this by examining your project in the Files window (Ctrl-2; |
| ⌘-2 on Mac). (Refer back to <a href="setup-dev-environ.html#run">Setting up |
| the Development Environment</a>).</li> |
| |
| <li><strong>Source Distribution:</strong> A package containing all source and configuration |
| files, typically in an archive file format (e.g., ZIP, TAR). You can use your NetBeans |
| project as part of your source distribution. Before compressing your project, make sure |
| to clean it (In the Projects window, right-click the project node and choose Clean) in |
| order to delete <code>build</code> and <code>dist</code> folders, if they exist. You |
| should also remove any of your environment-specific details included in the project. |
| To do so, navigate to the project on your computer's file system, then expand the |
| project's <code>nbproject</code> folder and delete the <code>private</code> folder |
| contained therein. (When the project is opened again in the IDE, the <code>private</code> |
| folder and its files are regenerated according to the current environment.) |
| |
| <br><br> |
| As part of your source distribution, you would need to also provide any scripts or |
| artifacts that are necessary for setup, configuration, and population of the database. |
| In this scenario, that would include the MySQL Workbench project from Unit 4, |
| <a href="#data-model">Designing the Data Model</a>, the DDL script that creates |
| the <code>affablebean</code> database schema, and possibly a separate script that |
| populates the <code>category</code> and <code>product</code> tables with business |
| data.</li> |
| </ol> |
| |
| <p>As was indicated in the tutorial <a href="design.html#scenario">Scenario</a>, a |
| "technically-oriented staff member is able to deploy the application to the |
| production server once it is ready." Aside from necessary performance tuning |
| (GlassFish tuning is discussed in Unit 12 <a href="test-profile.html#glassFishTune">Testing |
| and Profiling</a>) the person responsible for this would need to ensure that the database |
| driver is accessible to the server (i.e., place the driver JAR file in the server's |
| library folder). He or she would also need to know the JNDI name of the data source used |
| by the application to interact with the database. This is found in the persistence unit |
| (<code>persistence.xml</code> file) and, as you may recall, is: <code>jdbc/affablebean</code>. |
| This is the only "link" between the application itself and the back-end database |
| server.</p> |
| |
| <p class="notes"><strong>Note:</strong> Recall that the <code>sun-resources.xml</code> file, |
| which you created in Unit 6, <a href="connect-db.html#createConnPoolDataSource">Connecting |
| the Application to the Database</a> contains entries that instruct the GlassFish server |
| to create the JDBC resource and connection pool when the application is deployed. The |
| <code>sun-resources.xml</code> file is a deployment descriptor specific to the GlassFish |
| server only. Therefore, if the customer isn't using GlassFish as the production server, |
| the file should be deleted before the application is deployed. If the <code>sun-resources.xml</code> |
| file isn't removed from the WAR distribution however, it would simply be ignored by the |
| server it is deployed to.</p> |
| |
| <p>In terms of security, it would be necessary to set up a <em>user</em> and <em>group</em> |
| on the production server, so that the server can authenticate persons wanting to log into |
| the administration console. Also, SSL support for the production server would need to be |
| enabled, and you would need to acquire a certificate signed by a trusted third-party Certificate |
| Authority (CA), such as <a href="http://www.verisign.com" target="_blank">VeriSign</a> or |
| <a href="http://www.thawte.com/" target="_blank">Thawte</a>.</p> |
| |
| <p>Once the database is created and tables are populated with necessary data, the connection |
| pool and JDBC resource are set up on the production server, and security measures have |
| been taken, the application WAR file can be deployed to and launched on the production |
| server. Using GlassFish, it is possible to deploy your applications via the Administration |
| Console. (Select Applications in the left-hand Tree, then click the Deploy button to deploy |
| a new application.)</p> |
| |
| <p class="tips">The GlassFish plugin support in NetBeans also enables you to connect to a |
| remote instance of GlassFish. You can therefore work with a GlassFish production server |
| from the IDE for monitoring, profiling, and debugging tasks. If you are interested in |
| using GlassFish as a production server, refer to the <a href="#seeAlso">See Also</a> |
| section below for a list of web hosting solutions.</p> |
| |
| <p><em>Portability</em> is among the key benefits of Java EE. As your application adheres to |
| the technology specifications, it can theoretically be deployed to any server that supports |
| the same specifications. Recall that the <a href="intro.html#jcp">Introduction</a> lists |
| the specifications that you have used in this tutorial. All of these specifications are |
| part of the Java EE 6 platform specification (<a href="http://jcp.org/en/jsr/summary?id=316" |
| target="_blank">JSR 316</a>). Therefore, any server that is Java EE 6-compliant would be |
| a candidate for running the <code>AffableBean</code> application.</p> |
| |
| |
| <br> |
| <div class="feedback-box float-left" style="width: 683px;"> |
| |
| <h3>Did you know?</h3> |
| |
| <p>The NetBeans IDE began as a student project (originally called Xelfi) at |
| Charles University in Prague, Czech Republic in 1996. The goal was to write |
| a Delphi-like Java IDE. Xelfi was the first Java IDE written in Java, with |
| its first pre-releases in 1997.</p> |
| |
| <p>NetBeans was later purchased by Sun Microsystems in 1999, and shortly |
| thereafter became Sun's first sponsored open source project.</p> |
| |
| <p>In June 2000, the initial netbeans.org website was launched. You can view |
| an archived version of the site at: |
| <a href="http://web.archive.org/web/20000815061212/https://netbeans.org/index.html" |
| target="_blank">http://web.archive.org/web/20000815061212/https://netbeans.org/index.html</a></p> |
| |
| <p>For more information, see <a href="https://netbeans.org/about/history.html" target="_blank">A |
| Brief History of NetBeans</a>.</p> |
| </div> |
| <br style="clear:left"/> |
| |
| |
| <br> |
| <h2 id="framework">Using the JavaServer Faces Framework</h2> |
| |
| <p>Having developed a Java web application from scratch puts you in a great position to |
| begin appreciating how a framework can benefit your work. This section briefly introduces |
| the JavaServer Faces (JSF) framework, then examines the advantages of applying the |
| framework to the <code>AffableBean</code> application.</p> |
| |
| <ul> |
| <li><a href="#whatJSF">What is the JavaServer Faces Framework?</a></li> |
| <li><a href="#benefitJSF">How Can JSF Benefit Your Project?</a></li> |
| </ul> |
| |
| <div class="indent"> |
| <h3 id="whatJSF">What is the JavaServer Faces Framework?</h3> |
| |
| <p>The JavaServer Faces framework (<a href="http://jcp.org/en/jsr/detail?id=314" target="_blank">JSR 314</a>) |
| is an integral part of the Java EE platform and aims to facilitate web development by |
| providing the following:</p> |
| |
| <ul> |
| <li><strong>a user interface component model:</strong> JSF includes a standard component |
| API, which enables you to use and create custom UI components for your applications. |
| A <em>UI component</em> is a widget that has a specific appearance and guarantees |
| certain behavior. For example, this can be a simple text field that includes built-in |
| data validation and conversion with accompanying error messages, or it can be a complex |
| data table that interacts with a back-end data store and offers scrolling and column |
| sorting for users. Being able to reuse UI components for your application's interface |
| (or acquire custom components from third-party vendors) becomes increasingly important |
| as your application grows in size and complexity.</li> |
| |
| <li><strong>an MVC development infrastructure:</strong> The framework provides a |
| <code>FacesServlet</code> which works behind the scenes to dispatch requests to their |
| appropriate handlers (usually <em>backing beans</em> that you create). You author page |
| views using Facelets, the default view handler technology for JSF 2.0. These features, |
| when operating in tandem with JSF's <em>request processing lifecycle</em> (described |
| below), encourage your work to adhere to the MVC paradigm.</li> |
| </ul> |
| |
| <p>The JSF framework manages the request-response cycle by automating events that typically |
| need to occur for each client request. These events are qualified into six distinct |
| phases that are together known as the <em>JSF request processing lifecycle</em>. The book, |
| <a href="http://www.amazon.com/JavaServer-Faces-2-0-Complete-Reference/dp/0071625097/ref=pd_bxgy_b_img_a" |
| target="_blank">JavaServer Faces 2.0: The Complete Reference</a> by Ed Burns and Chris |
| Schalk, describes the lifecycle phases as follows:</p> |
| |
| <blockquote style="margin-top: 0"> |
| <em>[T]he request processing lifecycle performs all of the necessary back-end processing |
| for which one would otherwise have to write his or her own code. The lifecycle directs |
| the processing of incoming request parameters, and it manages a server-side set of UI |
| components and synchronizes them to what the user sees in a client browser. It also |
| satisfies follow-up requests for images, style sheets, scripts, and other kinds of |
| resources required to complete the rendering of the UI.</em><sup><a href="#footnote1Conclusion" |
| id="1Conclusion" style="text-decoration:none">[1]</a></sup> |
| </blockquote> |
| |
| <p id="lifecyclePhases">The six lifecycle phases, according to |
| <a href="http://www.amazon.com/JavaServer-Faces-2-0-Complete-Reference/dp/0071625097/ref=pd_bxgy_b_img_a" |
| target="_blank">JavaServer Faces 2.0</a>, are defined as follows:</p> |
| |
| <ol style="margin-top:0"> |
| <li><strong>Create or Restore View:</strong> Restores or creates a server-side component |
| tree (View) in memory to represent the UI information from a client.</li> |
| |
| <li><strong>Apply Request Values:</strong> Updates the server-side components with fresh |
| data from the client.</li> |
| |
| <li><strong>Process Validations:</strong> Performs validation and data type conversion on |
| the new data.</li> |
| |
| <li><strong>Update Model Values:</strong> Updates any server-side Model objects with new |
| data.</li> |
| |
| <li><strong>Invoke Application:</strong> Invokes any application logic needed to fulfill |
| the request and navigate to a new page if needed.</li> |
| |
| <li><strong>Render Response:</strong> Saves state and renders a response to the requesting |
| client.<sup><a href="#footnote2Conclusion" id="2Conclusion" style="text-decoration:none">[2]</a></sup></li> |
| </ol> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/conclusion/jsf-request-processing-lifecycle.png" |
| class="margin-around" alt="JSF request processing lifecycle" title="The JSF request processing lifecycle"> |
| |
| <p>One important concept of the JSF framework is the server-side UI component tree, or Faces |
| <em>View</em>. This component tree is built and maintained in server memory for each client |
| request, and is primarily associated with the first and last phases of the request processing |
| lifecycle depicted above. Consequently, the application is able to maintain state between |
| requests in a way that doesn't involve any manual coding on the part of the developer. In |
| other words, the request processing lifecycle handles synchronization between the server-side |
| View and that which is presented to the client. This enables you, the Java web developer, |
| to focus on code that is specific to your business problem.</p> |
| |
| |
| <h3 id="benefitJSF">How Can JSF Benefit Your Project?</h3> |
| |
| <p>To understand JSF's benefits, let's take a second look at the <code>AffableBean</code> |
| project and consider how the framework could be applied.</p> |
| |
| <h4>Strong Templating Support</h4> |
| |
| <p>Rather than creating your application page views in JSP pages, you'd be using Facelets |
| technology instead.<sup><a href="#footnote3Conclusion" id="3Conclusion" style="text-decoration:none">[3]</a></sup> |
| Facelets is a first-rate templating technology that enables you to maximize markup reuse |
| and reduce redundancy in your page views. Also, because Facelets pages use the <code>.xhtml</code> |
| file extension, you are able prepare views using standard XHTML syntax.</p> |
| |
| <p>In the <code>AffableBean</code> project, we took measures to reduce redundancy by factoring |
| out the header and footer markup for all page views into separate JSP fragment files, |
| and then included them in views by using the <code><include-prelude></code> and |
| <code><include-coda></code> elements in the deployment descriptor. Aside from the |
| header, the layouts for each of the application's five page views were unique. However, |
| many websites maintain the same layout across multiple pages. This is where templating |
| comes in especially handy.</p> |
| |
| <p>With Facelets templating, you have more control over which portions of markup get displayed |
| for individual page views. For example, you could create a template layout that is common |
| to all page views, and insert view-specific content into the template to render your views. |
| In this manner, you could specify a title for each page view. (Notice that in the |
| <code>AffableBean</code> application, the title remains the same for all page views.)</p> |
| |
| <h4>No Need to Handle Incoming Request Parameters</h4> |
| |
| <p>Upon reexamining the <code>AffableBean</code>'s <code>ControllerServlet</code>, you can see |
| that each time we implemented code for the supported URL patterns, it was necessary to manually |
| extract user parameters using the <code>request</code>'s <code>getParameter</code> method. |
| When working in JSF, you often create <em>backing beans</em>, which are Java classes that |
| are conceptually bound to a specific page view. Parameters are automatically extracted from |
| a request (during phase 2 of the <a href="#lifecyclePhases">request processing lifecycle</a>), |
| and set as properties for the backing bean. JSF also takes care of casting the <code>String</code> |
| values of your request parameters into the types that you have defined for your backing bean |
| properties. For example, if you have a property defined as an <code>int</code>, and your |
| incoming request parameter is a <code>String</code> whose value is "<code>33</code>", |
| JSF automatically converts the value to an <code>int</code> before storing it in the backing |
| bean.</p> |
| |
| <h4>No Need to Programmatically Configure Navigation</h4> |
| |
| <p>In order to set up navigation, we followed a certain pattern when implementing the |
| <code>ControllerServlet</code>: For each incoming request, the <code>getServletPath</code> |
| method is called to determine the requested URL pattern. After logic related to the URL pattern |
| is performed, a <code>RequestDispatcher</code> is attained, and the request is forwarded |
| to the appropriate page view. In numerous cases, the appropriate page view is specified by |
| hard-coding the path using the <code>userPath</code> variable.</p> |
| |
| <p>None of this is necessary when using JSF - navigation is handled by the framework. Your job |
| would be to either associate page views with URL patterns and any logical outcomes using a |
| Faces configuration file, or take advantage of JSF 2.0's <em>implicit navigation</em> feature, |
| which automatically forwards a request to a view that has the same name as the requested |
| URL pattern.</p> |
| |
| <h4>Built-in Validation Support</h4> |
| |
| <p>JavaServer Faces provides built-in server-side validation support. In the <code>AffableBean</code> |
| project, we created a <code>Validator</code> class and manually coded logic to perform all |
| validation. Using JSF, server-side validation would automatically occur at phase 3 of the |
| <a href="#lifecyclePhases">request processing lifecycle</a>.</p> |
| |
| <p>It would be worthwhile to take advantage of this validation for the <code>AffableBean</code> |
| checkout form, however some preliminary steps would be in order. Specifically, the HTML |
| markup for form elements would need to be replaced with comparable tags from JSF's |
| <a href="http://javaserverfaces.dev.java.net/nonav/docs/2.0/vdldocs/facelets/h/tld-summary.html" |
| target="_blank">Standard HTML Library</a>. This step converts the form elements into |
| JSF UI components, which we can then specify validation actions on using JSF's |
| <a href="http://javaserverfaces.dev.java.net/nonav/docs/2.0/vdldocs/facelets/f/tld-summary.html" |
| target="_blank">Core Library</a>. To give an idea, the side-by-side comparison |
| below demonstrates an adaptation of the checkout form's "name" field.</p> |
| |
| <table> |
| <tr> |
| <td> |
| <strong>HTML Markup</strong> |
| |
| <pre class="examplecode" style="width:252px"> |
| <label for="name">name:</label> |
| <input type="text" |
| id="name" |
| size="30" |
| maxlength="45" |
| value="${param.name}" /> |
| |
| <c:if test="${!empty nameError}"> |
| Value is required. |
| </c:if></pre> |
| </td> |
| |
| <td class="indent"> |
| <strong>JSF HTML Tag Library</strong> |
| |
| <pre class="examplecode" style="width:362px"> |
| <h:outputLabel value="name: " for="name"> |
| <h:inputText id="name" |
| size="30" |
| maxlength="45" |
| <strong>required="true"</strong> |
| value="#{checkoutBean.name}" /> |
| </h:outputLabel> |
| |
| <h:message for="name" /> |
| </pre> |
| </td> |
| </tr> |
| </table> |
| |
| <p>The <code><h:outputLabel></code> tag renders as an HTML <code><label></code> |
| tag, whereas <code><h:inputText></code> renders as an <code><input></code> |
| tag whose <code>type</code> is set to "<code>text</code>". Note the <code>required</code> |
| attribute, which is set to <code>true</code> (shown in <strong>bold</strong>). This is |
| all that's needed to ensure that the field is not left blank by the user. The |
| <code><h:message></code> tag identifies the location where any validation error |
| messages for the field should display. JSF's default error message for a field that |
| requires user input is, "Value is required."</p> |
| |
| <p>Continuing with the example, if we wanted to check whether input for the field hasn't |
| exceeded 45 characters, we could apply the <code><f:validateLength></code> tag.</p> |
| |
| <pre class="examplecode" style="margin-top:0; width:660px"> |
| <h:outputLabel value="name: " for="name"> |
| <h:inputText id="name" |
| size="30" |
| maxlength="45" |
| required="true" |
| value="#{checkoutBean.name}"> |
| |
| <strong><f:validateLength maximum="45" /></strong> |
| </h:inputText> |
| </h:outputLabel> |
| |
| <h:message for="name" /></pre> |
| |
| <h4>Well-Defined Division of Labor</h4> |
| |
| <p>As stated in the <a href="http://download.oracle.com/javaee/6/tutorial/doc/bnapj.html" target="_blank">Java |
| EE 6 Tutorial</a>, "One of the greatest advantages of JavaServer Faces technology is that it |
| offers a clean separation between behavior and presentation for web applications." If you |
| are working on a large project that involves a team of developers, the framework functions as a |
| blueprint which allows team members to focus on different areas of development simultaneously. For |
| example, front-end developers can implement page views using tags from JSF's HTML Library, while |
| programmers responsible for implementing component logic and behavior can "plug their work |
| into" existing HTML library tags.</p> |
| |
| <h4>Ability to Render the View with Other Markup Languages</h4> |
| |
| <p>Suppose that the Affable Bean staff commission you at a later point to prepare a |
| mobile version of their site, so users can access it using a hand-held device. |
| JSF APIs are a flexible rendering technology that enable you to attach multiple |
| renderers to the component tree (i.e., View) of a JSF-enabled application. In |
| other words, it is possible to create custom components that, for example, render |
| HTML when requested by a browser, or WML when requested by a PDA.</p> |
| </div> |
| |
| |
| <div class="feedback-box"> |
| <a href="/about/contact_form.html?to=3&subject=Feedback: NetBeans E-commerce Tutorial - Conclusion">Send |
| Us Your Feedback</a></div> |
| |
| <br style="clear:both;"> |
| |
| |
| <h2 id="seeAlsoConclusion">See Also</h2> |
| |
| <div class="indent"> |
| <h3>NetBeans Tutorials</h3> |
| |
| <div class="indent"> |
| <p><strong>JavaServer Faces</strong></p> |
| |
| <ul style="margin: -.5em 0 1em -1.8em"> |
| <li><a href="../../web/jsf20-support.html" target="_blank">JSF 2.0 Support in NetBeans IDE</a></li> |
| <li><a href="../../web/jsf20-intro.html" target="_blank">Introduction to JavaServer Faces 2.0</a></li> |
| <li><a href="../../web/jsf20-crud.html" target="_blank">Generating a JavaServer Faces 2.0 CRUD Application from a Database</a></li> |
| <li><a href="../../../samples/scrum-toys.html" target="_blank">Scrum Toys - The JSF 2.0 Complete Sample Application</a></li> |
| </ul> |
| |
| <p><strong>Contexts and Dependency Injection</strong></p> |
| |
| <ul style="margin: -.5em 0 1em -1.8em"> |
| <li><a href="../cdi-intro.html" target="_blank">Getting Started with Contexts and Dependency Injection and JSF 2.0</a></li> |
| <li><a href="../cdi-inject.html" target="_blank">Working with Injection and Qualifiers in CDI</a></li> |
| <li><a href="../cdi-validate.html" target="_blank">Applying @Alternative Beans and Lifecycle Annotations</a></li> |
| <li><a href="../cdi-events.html" target="_blank">Working with Events in CDI</a></li> |
| </ul> |
| </div> |
| |
| |
| <h3>JavaServer Faces</h3> |
| |
| <ul> |
| <li><strong>Product Page:</strong> <a href="http://www.oracle.com/technetwork/java/javaee/javaserverfaces-139869.html" target="_blank">JavaServer Faces Technology</a></li> |
| <li><strong>Specification Download:</strong> <a href="http://jcp.org/aboutJava/communityprocess/final/jsr314/index.html" target="_blank">JSR 314: JavaServer Faces 2.0</a></li> |
| <li><strong>Reference Implementation:</strong> <a href="http://javaserverfaces.dev.java.net/" target="_blank">GlassFish: Project Mojarra</a></li> |
| <li><strong>Official Forum:</strong> <a href="http://forums.sun.com/forum.jspa?forumID=427" target="_blank">Web Tier APIs - JavaServer Faces</a></li> |
| <li><a href="http://download.oracle.com/javaee/6/tutorial/doc/bnaph.html" target="_blank">The Java EE 6 Tutorial - Chapter 4: JavaServer Faces Technology</a></li> |
| <li><a href="http://download.oracle.com/javaee/6/tutorial/doc/giepx.html" target="_blank">The Java EE 6 Tutorial - Chapter 5: Introduction to Facelets</a></li> |
| <li><a href="http://www.amazon.com/JavaServer-Faces-2-0-Complete-Reference/dp/0071625097/ref=pd_bxgy_b_img_a" target="_blank">JavaServer Faces 2.0: The Complete Reference</a> [Book]</li> |
| <li><a href="http://www.amazon.com/Core-JavaServer-Faces-David-Geary/dp/0137012896/ref=pd_bxgy_b_img_b" target="_blank">Core JavaServer Faces</a> [Book]</li> |
| <li><a href="http://www.amazon.com/JSF-2-0-Cookbook-Anghel-Leonard/dp/1847199526/ref=pd_sim_b_2" target="_blank">JSF 2.0 Cookbook</a> [Book]</li> |
| <li><a href="http://refcardz.dzone.com/refcardz/javaserver-faces-20" target="_blank">JSF 2.0 Refcard</a></li> |
| </ul> |
| |
| |
| <h3>GlassFish Web Hosting</h3> |
| |
| <ul> |
| <li><a href="http://www.joyent.com/" target="_blank">Joyent Cloud Hosting</a></li> |
| <li><a href="http://www.eapps.com/applications/glassfish-hosting.php" target="_blank">eApps Hosting</a></li> |
| <li><a href="http://www.visionwebhosting.net/glassfish-hosting.html" target="_blank">Vision Web Hosting</a></li> |
| <li><a href="http://www.jspzone.net/glassfish_hosting.htm" target="_blank">[DE]SYSTEMS</a></li> |
| <li><a href="http://www.jspzone.net/glassfish_hosting.htm" target="_blank">JSPZone</a></li> |
| </ul> |
| </div> |
| |
| |
| <br> |
| <h2 id="about">About the NetBeans E-commerce Tutorial</h2> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/conclusion/logo.png" |
| class="margin-around float-left" alt="AffableBean logo"> |
| |
| <br> |
| <p>The NetBeans E-commerce Tutorial and sample application were conceived of and |
| written by Troy Giunipero. The application began as a project arising out of |
| Sun's <a href="http://research.sun.com/SEED/" target="_blank">SEED program</a>, |
| and was developed from January 2009 to November 2010. The tutorial was prepared |
| as part of ongoing efforts to provide documentation for the IDE's |
| <a href="../../../trails/java-ee.html" target="_blank">Java EE & Java Web Learning |
| Trail</a>.</p> |
| |
| <br style="clear:left"> |
| |
| |
| <br> |
| <h2 id="acknowledge">Acknowledgments</h2> |
| |
| <p>Many people have helped with this project. I am especially grateful to following individuals |
| for their help, support and contributions:</p> |
| |
| <ul> |
| <li>Ed Burns, who was my SEED mentor, for his patience and guidance, and his willingness to |
| share his technical expertise in our numerous discussions concerning Java web technologies.</li> |
| |
| <li>My managers, Patrick Keegan, for originally approving this project, and David Lindt, who |
| showed continuous support.</li> |
| |
| <li>David Konecny and Andrei Badea for their invaluable help and advice, especially in regard |
| Java Persistence, working with EclipseLink, and integrating EE 6 technologies.</li> |
| |
| <li>Don McKinney for providing the three beautiful diagrams used in <a href="#design">Designing |
| the Application</a>.</li> |
| |
| <li>Eric Jendrock and the Java EE Tutorial team, for granting permission to adapt and reproduce |
| diagrams from the Java EE 5 Tutorial. Diagrams were used in <a href="#security">Securing |
| the Application</a>, and are based on <a href="http://download.oracle.com/javaee/5/tutorial/doc/bnbxj.html#bnbxl" |
| target="_blank">Figure 28-6: Mapping Roles to Users and Groups</a> and |
| <a href="http://download.oracle.com/javaee/5/tutorial/doc/bncbe.html#gexfa" |
| target="_blank">Figure 30-3: Form-Based Authentication</a>.</li> |
| |
| <li>Jan Pirek, for coordinating and setting up necessary resources to make the |
| <a href="http://services.netbeans.org/AffableBean/" target="_blank">live demo</a> a reality.</li> |
| |
| <li>Ondrej Panek for providing a Czech translation of text used in the sample application.</li> |
| |
| <li>Also, special thanks to <a href="http://www.flickr.com/photos/cobalt/" target="_blank">cobalt123</a> |
| for graciously permitting usage of several photos, including |
| <a href="http://www.flickr.com/photos/cobalt/46523149/" target="_blank">Fresh Picks</a> and |
| <a href="http://www.flickr.com/photos/cobalt/1441879742/" target="_blank">Give Us Our Daily |
| Bread #1</a>.</li> |
| </ul> |
| |
| |
| <br> |
| <h2 id="disclaimer">Disclaimer</h2> |
| |
| <p>This tutorial and sample application are solely available for educative purposes. Although |
| the sample application demonstrates a real-world scenario, there are several aspects that |
| are decidedly not "real-world". For example, e-commerce sites do not typically |
| store customer credit card details, but allow payment to be managed by a reputable third-party |
| service, such as <a href="https://www.paypal.com" target="_blank">PayPal</a> or |
| <a href="http://www.rbsworldpay.com/" target="_blank">WorldPay</a>. Furthermore, although |
| not discussed in the tutorial, customer trust is a hard-earned commodity. An e-commerce |
| site's privacy policy, as well as the terms and conditions surrounding placed orders should |
| be made easily available to customers and site visitors.</p> |
| |
| <p>The sample application and project snapshots are provided "AS IS," without a warranty |
| of any kind. If you aim to use or modify this software for your own purposes, please comply |
| with the license presented at |
| <a href="http://developers.sun.com/berkeley_license.html" target="_blank">http://developers.sun.com/berkeley_license.html</a>.</p> |
| |
| |
| <br> |
| <h2>References</h2> |
| |
| <ol> |
| <li id="footnote1Conclusion"><a href="#1Conclusion" style="text-decoration:none">^</a> Adapted from <a href="http://www.amazon.com/JavaServer-Faces-2-0-Complete-Reference/dp/0071625097/ref=pd_bxgy_b_img_a" |
| target="_blank">JavaServer Faces 2.0: The Complete Reference</a>, Chapter 3: The JavaServer |
| Faces Request Processing Lifecycle.</li> |
| |
| <li id="footnote2Conclusion"><a href="#2Conclusion" style="text-decoration:none">^</a> Ibid.</li> |
| |
| <li id="footnote3Conclusion"><a href="#3Conclusion" style="text-decoration:none">^</a> You can |
| certainly use JavaServer Pages in a JSF application. Facelets is the default view handler |
| technology for JSF version 2.0. For previous JSF versions, the default is JSP. In fact, when |
| creating a new JSF 2.0 project in the IDE, you are able to specify the view technology you |
| want to use (Facelets or JSP).</li> |
| </ol> |
| |
| |
| |
| <br><br><br><br> |
| <h1 id="setup">The NetBeans E-commerce Tutorial - Setup Instructions</h1> |
| |
| <div style="margin-left:-3px"> |
| <div class="feedback-box margin-around float-left" style="margin-right:15px"> |
| |
| <h4>Tutorial Contents</h4> |
| |
| <ol> |
| <li><a href="#intro">Introduction</a></li> |
| <li><a href="#design">Designing the Application</a></li> |
| <li><a href="#setup-dev-environ">Setting up the Development Environment</a></li> |
| <li><a href="#data-model">Designing the Data Model</a></li> |
| <li><a href="#page-views-controller">Preparing the Page Views and Controller Servlet</a></li> |
| <li><a href="#connect-db">Connecting the Application to the Database</a></li> |
| <li><a href="#entity-session">Adding Entity Classes and Session Beans</a></li> |
| <li><a href="#manage-sessions">Managing Sessions</a></li> |
| <li><a href="#transaction">Integrating Transactional Business Logic</a></li> |
| <li><a href="#language">Adding Language Support</a></li> |
| <li><a href="#security">Securing the Application</a></li> |
| <li><a href="#test-profile">Testing and Profiling</a></li> |
| <li><a href="#conclusion">Conclusion</a></li> |
| </ol> |
| </div> |
| </div> |
| |
| <p><img src="../../../../images_www/articles/68/netbeans-stamp-68-69.png" class="stamp" |
| alt="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9" |
| title="Content on this page applies to NetBeans IDE, versions 6.8 and 6.9"></p> |
| |
| <p>If you want to follow a tutorial unit without having completed previous units, |
| you need to perform some preliminary steps in order to set up your development |
| environment.</p> |
| |
| <ol style="margin:5px 0 0 320px"> |
| <li><strong>Set up your MySQL database server.</strong> Follow the steps outlined in: |
| <a href="setup-dev-environ.html#communicate">Communicating with the Database Server</a>.</li> |
| |
| <li><strong>Create the <code>affablebean</code> schema on the database server, |
| and populate the database with sample data:</strong> |
| |
| <ol style="margin: 5px 0 0 -1.5em"> |
| <li>Click on <a href="https://netbeans.org/projects/samples/downloads/download/Samples%252FJavaEE%252Fecommerce%252Faffablebean.sql">affablebean.sql</a> |
| and copy (Ctrl-C; ⌘-C on Mac) the entire contents of the file.</li> |
| |
| <li>Open the IDE's SQL editor. In the Services window (Ctrl-5; ⌘-5 on Mac), |
| right-click the <code>affablebean</code> database connection ( |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/common/db-connection-node.png" |
| alt="Database connection node"> ) node and choose Execute Command. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup/execute-command.png" |
| class="margin-around b-all" alt="Services window - Execute command menu option" |
| title="Choose Execute Command from a connection node to open the IDE's SQL editor"> |
| |
| <br> |
| The IDE's SQL editor opens.</li> |
| |
| <li>Paste (Ctrl-V; ⌘-V on Mac) the entire contents of the <code>affablebean.sql</code> |
| file into the editor.</li> |
| |
| <li>Click the Run SQL ( <img src="../../../../images_www/articles/73/javaee/ecommerce/common/run-sql-btn.png" |
| alt="Run SQL button"> ) button in the editor's toolbar. The script runs on your |
| MySQL server. Tables are generated for the database, and sample data is added to |
| the <code>product</code> and <code>category</code> tables.</li> |
| </ol></li> |
| |
| <li><strong>Create a connection pool and JDBC resource on GlassFish.</strong> |
| |
| <ol style="margin: 5px 0 0 -1.5em"> |
| <li>In the Services window (Ctrl-5; ⌘-5 on Mac), expand the Servers > GlassFish |
| Server 3 node and choose Properties. In the Servers window that displays, make sure the |
| 'Enable JDBC Driver Deployment' option is selected. If your project requires the MySQL |
| <a href="http://www.mysql.com/downloads/connector/j/" target="_blank">Connector/J</a> |
| driver, this option will ensure that the driver is deployed to GlassFish when your |
| project is deployed. (If the server is already running, you'll need to restart the |
| server.)</li> |
| |
| <li>In the Services window, right-click the GlassFish Server 3 node and choose Start.</li> |
| |
| <li>Once the server is running, right-click the GlassFish Server 3 node and choose View Admin |
| Console.</li> |
| |
| <li>Log into the console (default username/password is: <code>admin/adminadmin</code>).</li> |
| |
| <li>In the Admin Console, in the Tree on the left, expand the Resources > JDBC node, |
| then click the Connection Pools node.</li> |
| |
| <li>In the Connection Pools interface, click the New button, and enter the following details: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>Name:</strong> <code>AffableBeanPool</code></li> |
| <li><strong>Resource Type:</strong> <code>javax.sql.ConnectionPoolDataSource</code></li> |
| <li><strong>Database Vendor:</strong> <code>MySql</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup/connection-pool.png" |
| class="margin-around b-all" alt="GlassFish Admin Console - Connection Pools interface" |
| title="Specify settings to create a connection pool that connects with a MySQL database"></li> |
| |
| <li>Click Next. Accept all defaults and click Finish.</li> |
| |
| <li>In the Connection Pools interface, click on your newly created <code>AffableBeanConnectionPool</code> |
| to make the following change under the General tab: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>Datasource Classname:</strong> <code>com.mysql.jdbc.jdbc2.optional.MysqlDataSource</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup/datasource-classname.png" |
| class="margin-around b-all" style="width:638px" |
| alt="GlassFish Admin Console - Connection Pools interface" |
| title="Set the datasource classname for the connection pool"></li> |
| |
| <li>Click Save.</li> |
| |
| <li>Click the Additional Properties tab and ensure that the following three properties |
| have been set. (There may be other properties listed - these are default settings, |
| however the following three must be set manually.) |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>User:</strong> <code>root</code></li> |
| <li><strong>Password:</strong> <code>nbuser</code></li> |
| <li><strong>URL:</strong> <code>jdbc:mysql://localhost:3306/affablebean</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup/additional-properties.png" |
| class="margin-around b-all" style="width:638px" |
| alt="GlassFish Admin Console - Connection Pools interface" |
| title="Set username, password and url to the database"></li> |
| |
| <li>Click Save.</li> |
| |
| <li>Click the General tab, then click Ping. You should see a message indicating that |
| the ping succeeded. The <code>AffableBeanPool</code> connection pool can now |
| connect to your MySQL database server. |
| |
| <br> |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup/ping-succeeded.png" |
| class="margin-around b-all" style="width:638px" |
| alt="GlassFish Admin Console - Connection Pools interface" |
| title="Ping the MySQL server to determine whether the connection pool can connect"></li> |
| |
| <li>In the Admin Console's Tree in the left column, click the Resources > |
| JDBC > JDBC Resources node. The JDBC Resources interface opens in |
| the main window.</li> |
| |
| <li>Click the New button to create a new JDBC resource, then enter the following |
| details: |
| |
| <ul style="margin: 5px 0 0 -1em"> |
| <li><strong>JNDI Name:</strong> <code>jdbc/affablebean</code></li> |
| <li><strong>Connection Pool:</strong> <code>AffableBeanPool</code></li> |
| </ul> |
| |
| <img src="../../../../images_www/articles/73/javaee/ecommerce/setup/jdbc-resource.png" |
| class="margin-around b-all" alt="GlassFish Admin Console - JDBC Resource interface" |
| title="Specify JNDI name and connection pool to create the JDBC resource"></li> |
| |
| <li>Click OK.</li> |
| </ol> |
| </li> |
| </ol> |
| |
| <p style="margin-left:27em">You have set up the MySQL server and can connect to it from the |
| IDE's Services window. You created a database named <code>affablebean</code>, and populated |
| the database's <code>product</code> and <code>category</code> tables with sample data. You |
| then started the GlassFish server, and created a connection pool that enables the server to |
| connect to the <code>affablebean</code> database. Finally, you created a JDBC resource which |
| your application can use to reference the server's connection pool.</p> |
| |
| <p style="margin-left:27em">You can now open and run any of the project snapshots provided for |
| you in the tutorial units.</p> |
| |
| </body> |
| </html> |