- create a web project on netbeans IDE with name AffableBean using GlassFish serverv3 or Open Source Edition 3.0.1 + Java EE 6 Web.
- change the password for root user:
shell> mysql -u root
mysql> UPDATE mysql.user SET Password = PASSWORD('nbuser') WHERE User = 'root';
mysql> FLUSH PRIVILEGES;
- register the Mysql Server on netbeans.
- create a database instance name affablebean, grant full access to root@localhost using services tab.
4. Designing the Data Model
- Creating the affablebean Schema.
- create an EER Diagram and the following tables on it: category,customer_order,customer, product.
- create the Relationships between tables.
- Forward-Engineering to the Database to generate database tables.
5. Preparing the Page Views and
Controller Servlet
index.jsp,
category.jsp,
cart.jsp,
checkout.jsp,
confirmation.jsp
affablebean.css
- Creating a Header and Footer and jsp-property-group in web.xml
- Creating the Controller Servlet using the @WebServlet annotation.category.jsp,
cart.jsp,
checkout.jsp,
confirmation.jsp
affablebean.css
- Creating a Header and Footer and jsp-property-group in web.xml
6. Connecting the Application to the Database
- Adding Sample Data to the Database
- Creating a Connection Pool and Data Source
- Testing the Connection Pool and Data Source
- Setting Context Parameters: Setting up context parameters can be accomplished in two steps:
- Listing parameter names and values in the web deployment descriptor
- Calling the parameters in JSP pages using the
initParam
object
Insert JSTL code by pressing Ctrl-Space
- Using Implicit Objects > pageContext > request > queryString
7. Adding Entity Classes and
Session Beans
- What are EJB and JPA Technologies?EnterPrise JavaBeans technology as a "server-side component architecture" that "enables rapid and simplified development of distributed, transactional, secure and portable applications.Some of the services that we take advantage of in this tutorial are described in EJB 3 In Action as follows:
- Pooling: 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.
- Thread Safety: 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.
- Transactions: 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, Integrating Transactional Business Logic.
- Security: 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.[2] In Unit 11, Securing the Application, a demonstration of EJB's
@RolesAllowed
annotation is provided.
- 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.
- You can avoid the task of writing low-level, verbose and error-prone JDBC/SQL code.
- JPA transparently provides services for data caching and performance optimization.
Enterprise session beans are invoked by a client in order to perform a specific business operation. The name session implies that a bean instance is available for the duration of a "unit of work". The EJB 3.1 specification describes a typical session object as having the following characteristics:
- Executes on behalf of a single client
- Can be transaction-aware
- Updates shared data in an underlying database
- Does not represent directly shared data in the database, although it may access and update such data
- Is relatively short-lived
- Is removed when the EJB container crashes. The client has to re-establish a new session object to continue computation.
EJB provides three types of session beans: stateful, stateless, and singleton. The following descriptions are adapted from the Java EE 6 Tutorial.
- Stateful: 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 conversational state.
- Stateless: 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.
- Singleton: 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.
For purposes of developing the e-commerce application in this tutorial, we will only be working with stateless session beans.
- Adding Entity Classes from Database
- Adding Session Beans
A session facade is a design pattern advertised in the Enterprise BluePrints program. As stated in the Core J2EE Pattern Catalog, it attempts to resolve common problems that arise in a multi-tiered application environment, such as:
- Tight coupling, which leads to direct dependence between clients and business objects
- Too many method invocations between client and server, leading to network performance problems
- Lack of a uniform client access strategy, exposing business objects to misuse
Using the session and entity beans in the
AffableBean
project (remove the JSTL data access logic that you previously set up for the index and category pages).8. Managing Sessions
- Working with an HttpSession Object
ShoppingCart cart = new ShoppingCart(); session.setAttribute("cart", cart);
In order to retrieve the cart from the session, the
getAttribute
method is applied:cart = (ShoppingCart) session.getAttribute("cart");
In JSP pages, you can access objects bound to the session using EL expressions. Continuing with the above example, if a
ShoppingCart
object named 'cart
' is bound to the session, you can access the object using the following EL expression:${cart}
- Working with Scoped Variables in Web Applications
When working with JSP/Servlet technology, there are four scope objects available to you within the realm of the application. JSP technology implements implicit objects that allows you to access classes defined by the Servlet API.
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
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
category.jsp
for example, the expression:${categoryProducts}
is shorthand for:
${sessionScope.categoryProducts}
- Examining Session Data with the Java Debugger
- Set a breakpoint in the
doPost
method on the line that creates anHttpSession
object (line 150). To set a breakpoint, click in the left margin of the editor. - Run the debugger. Click the Debug Project
- ( Ctrl+F7 ) Step Out: Steps you out of the current method call. Executes and removes the topmost method call in your call stack.
- (F4 ) Run to Cursor: Executes up to the line on which your cursor is placed.
- Apply Code Changes: 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.
- (Shift+F8 ) Step Over Expression: 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 ( ) command
- Examining Session Tracking Options
The AffableBean
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 cart.jsp
page in the editor, you'll see that the <form>
tags contain a hidden field.<form action="updateCart" method="post">
<input type="hidden"
name="productId"
value="${product.id}">
...
</form>
- Examining Client-Server Communication with the HTTP Monitor
- Maintaining Sessions with URL Rewriting
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.
You need to ensure that the application is capable of rewriting URLs whenever cookies are disabled. You do this by calling the response’s encodeURL
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.
For example, the browser sends a request for AffableBean
's third category (bakery): category?3
. The server responds with session ID included in the URL:
/AffableBean/category;jsessionid=364b636d75d90a6e4d0085119990?3
As stated above, all URLs returned by your application's servlets must be encoded. Keep in mind that JSP pages are compiled into servlets. How can you encode URLs in JSP pages? JSTL's <c:url>
tag serves this purpose.
Modify the request so that it is passed through the <c:url>
tag.
<form action="<c:url value='addToCart'/>" method="post">
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.
<form action="addToCart;jsessionid=4188657e21d72f364e0782136dde" method="post">
- Handling Session Time-Outs
Setting Session Time Intervals
<session-config>
<session-timeout>
15
</session-timeout>
</session-config>
Programmatically Handling Session Time-Outs
=> implement the Filter
interface
@WebFilter(servletNames = {"Controller"})
public class SessionTimeoutFilter implements Filter {
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() {
}
}
encodeURL
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.AffableBean
's third category (bakery): category?3
. The server responds with session ID included in the URL:<c:url>
tag serves this purpose.<c:url>
tag.<form action="<c:url value='addToCart'/>" method="post">
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.
<form action="addToCart;jsessionid=4188657e21d72f364e0782136dde" method="post">
- Handling Session Time-Outs
Setting Session Time Intervals
<session-config>
<session-timeout>
15
</session-timeout>
</session-config>
Programmatically Handling Session Time-Outs
=> implement the
@WebFilter(servletNames = {"Controller"})
public class SessionTimeoutFilter implements Filter {
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() {
}
}
Filter
interface@WebFilter(servletNames = {"Controller"})
public class SessionTimeoutFilter implements Filter {
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() {
}
}
9. Integrating Transactional Business Logic
Overview of the Transaction
9. Integrating Transactional Business Logic
Overview of the Transaction
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
OrderManager
EJB. TheOrderManager
uses the provided data and performs the following write actions to the database:- A new
Customer
record is added. - A new
CustomerOrder
record is added. - New
OrderedProduct
records are added, according to the items contained in theShoppingCart
.
We'll implement this by creating a
placeOrder
method which performs the three write actions by sequentially calling private helper methods, addCustomer
,addOrder
, and addOrderedItems
. 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:@TransactionManagement
(
TransactionManagementType
.CONTAINER)
: Used to specify that any transactions occurring in the class are container-managed.@TransactionAttribute
(
TransactionAttributeType
.REQUIRED)
: Used on the method that invokes the transaction to specify that a new transaction should be created (if one does not already exist).
- Click the New File ( ) 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.
- Click Next. Name the EJB '
OrderManager
', place the EJB in thesession
package, and accept other default settings. (Create a stateless session bean, and do not have the wizard generate an interface for the bean.)
At this stage you might assume that, transaction or no transaction, the
OrderManager
is now able to successfully write entity objects to the database. Run the project and see how customer orders are currently being processed.- Press F6 (fn-F6 on Mac) to run the project.
- Step through the business process flow. 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:
- name:
Hugo Reyes
- email:
hurley@mrcluck.com
- phone:
606252924
- address:
Karlova 33
- prague:
1
- credit card number:
1111222233334444
- name:
- Click the 'submit purchase' button. The server responds with an HTTP status 500 message.
One way to overcome this is to manually synchronize the persistence context with the database. This can be accomplished using the
EntityManager
's flush
method.In the
addOrderedItems
method, add a call to flush the persistence context to the database.private void addOrderedItems(CustomerOrder order, ShoppingCart cart) {
em.flush();
List 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);
}
}
Setting up the Transaction Programmatically
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.[1] The following steps demonstrate how to ensure that the write operations performed in the
placeOrder
method are treated as a single transaction.- Refer to the transaction diagram above. Add the two transaction-related annotations to the
OrderManager
EJB.@Stateless @TransactionManagement(TransactionManagementType.CONTAINER) public class OrderManager { @PersistenceContext(unitName = "AffableBeanPU") private EntityManager em; @TransactionAttribute(TransactionAttributeType.REQUIRED) public int placeOrder(String name, String email, String phone, String address, String cityRegion, String ccNumber, ShoppingCart cart) { try { ...
@TransactionManagement
annotation is used to specify that any transactions occurring in the OrderManager
EJB are container-managed. The@TransactionAttribute
annotation placed on the placeOrder
method specifies that any operations occurring in the method must be treated as part of a transaction.Add the following code. Explanation follows.
@PersistenceContext(unitName = "AffableBeanPU")
private EntityManager em;
@Resource
private SessionContext context;
@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) {
context.setRollbackOnly();
return 0;
}
}
Validating and Converting User Input
Also included in snapshot 8 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.
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.
10. Adding Language Support
"Language support" here refers to the ability to display page views according to the customer-specified languages. Within the context of the
AffableBean
application, we have agreed to provide support for both English and Czech, as per the previously outlined customer requirements.
In order to accomplish this, you rely on Java's support for internationalization. You create a resource bundle 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.
Understanding Resource Bundles
Understanding Resource Bundles
In Java, a resource bundle is a representation of the
java.util.ResourceBundle
class. As stated in the Javadoc,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.From the Javadoc, you can also note that the
This allows you to write programs that can:
- be easily localized, or translated, into different languages
- handle multiple locales at once
- be easily modified later to support even more locales
ResourceBundle
is parent to both ListResourceBundle
and PropertyResourceBundle
. In this tutorial we utilize thePropertyResourceBundle
, which manages resources as text files that use the .properties
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 ('_
'). For example, snippets from two of the resource bundles you create in this tutorial look as follows:
messages_en.properties
meats=meats
bakery=bakery
messages_cs.properties
meats=maso
bakery=pečivo
In the above example, '
messages
' represents the base name, and the locale identifier is the two-letter code which is appended using an underscore. (i.e., 'en
' for English, 'cs
' for Czech). The two-letter codes are derived from the international ISO 639 standard, which lists codes that represent the names of languages. The ISO 639 standard is adopted by the W3C Internationalization Activity and is used by all major browsers (these are the codes understood in the Accept-Language
HTTP header). It is also internalized in the java.util.Locale
class.Making Pages Multilingual
There are three basic steps that you need to follow to incorporate multilingual support into your web pages.
- Create a resource bundle for each language you plan to support.
- Register the resource bundle with the application by setting a context parameter in the
web.xml
deployment descriptor. - In page views, replace 'hard-coded' text with
<fmt:message>
tags that reference keys in the resource bundles
Setting up Form-Based Authentication
Declarative and Programmatic Security
With declarative security, 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.
With programmatic security, 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.
For the
Choosing an Authentication MechanismAffableBean
application, we'll use declarative security by declaring all security information in the web.xml
deployment descriptor.
An authentication mechanism is used to determine how a user gains access to restricted content. The Java EE platform supports various authentication mechanisms, such as HTTP basic authentication, form-based authentication, and client authentication. The authentication mechanism behind our login form will be form-based authentication. You'll learn what form-based authentication is when you begin setting up the login form for the
Setting up Users, Groups and RolesAffableBean
administration console below.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.
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.
A user 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 group, 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 roles.
realm: details of users and groups on the server in a security policy domain. 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.
The GlassFish server provides three preconfigured realms by default. These are the
file
, admin-realm
, and certificate
realms. Briefly, the file
realm stores user credentials in a local text file named keyfile
. The admin-realm
also stores credentials in a local text file, and is reserved for server administrator users. The certificate
realm, the server stores user credentials in a certificate database.
When defining users, groups and roles for the
AffableBean
administration console, we'll use the server's preconfigured file
realm.Configuring Secure Data Transport
There are two instances in the
AffableBean
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.
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.,
You can find the generated certificate in: https://
).<gf-install-dir>/glassfish/domains/domain1/config/keystore.jks
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 VeriSign or Thawte.
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.
12. Testing and Profiling
Testing with JMeter12. Testing and Profiling
Using the NetBeans Profile
13. Conclusion
Using the JavaServer Faces Framework
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
AffableBean
application.How Can JSF Benefit Your Project?
To understand JSF's benefits, let's take a second look at the
AffableBean
project and consider how the framework could be applied.Strong Templating Support
Rather than creating your application page views in JSP pages, you'd be using Facelets technology instead.[3] 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
.xhtml
file extension, you are able prepare views using standard XHTML syntax.
In the
AffableBean
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 <include-prelude>
and <include-coda>
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.
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
AffableBean
application, the title remains the same for all page views.)No Need to Handle Incoming Request Parameters
Upon reexamining the
AffableBean
's ControllerServlet
, you can see that each time we implemented code for the supported URL patterns, it was necessary to manually extract user parameters using the request
's getParameter
method. When working in JSF, you often create backing beans, 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 request processing lifecycle), and set as properties for the backing bean. JSF also takes care of casting the String
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 int
, and your incoming request parameter is a String
whose value is "33
", JSF automatically converts the value to an int
before storing it in the backing bean.No Need to Programmatically Configure Navigation
In order to set up navigation, we followed a certain pattern when implementing the
ControllerServlet
: For each incoming request, the getServletPath
method is called to determine the requested URL pattern. After logic related to the URL pattern is performed, a RequestDispatcher
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 userPath
variable.
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 implicit navigation feature, which automatically forwards a request to a view that has the same name as the requested URL pattern.
Built-in Validation Support
JavaServer Faces provides built-in server-side validation support. In the
AffableBean
project, we created a Validator
class and manually coded logic to perform all validation. Using JSF, server-side validation would automatically occur at phase 3 of the request processing lifecycle.
It would be worthwhile to take advantage of this validation for the
AffableBean
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 Standard HTML Library. This step converts the form elements into JSF UI components, which we can then specify validation actions on using JSF's Core Library. To give an idea, the side-by-side comparison below demonstrates an adaptation of the checkout form's "name" field.HTML Markup<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>
|
JSF HTML Tag Library
<h:outputLabel value="name: " for="name">
<h:inputText
id="name"
size="30"
maxlength="45"
required="true"
value="#{checkoutBean.name}" />
</h:outputLabel>
<h:message for="name" />
The
<h:outputLabel>
tag renders as an HTML <label>
tag, whereas <h:inputText>
renders as an <input>
tag whose type
is set to "text
". Note therequired
attribute, which is set to true
(shown in bold). This is all that's needed to ensure that the field is not left blank by the user. The <h:message>
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."
Continuing with the example, if we wanted to check whether input for the field hasn't exceeded 45 characters, we could apply the
<f:validateLength>
tag.<h:outputLabel value="name: " for="name">
<h:inputText id="name"
size="30"
maxlength="45"
required="true"
value="#{checkoutBean.name}">
<f:validateLength maximum="45" />
</h:inputText>
</h:outputLabel>
<h:message for="name" />
Well-Defined Division of Labor
As stated in the Java EE 6 Tutorial, "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.
Ability to Render the View with Other Markup Languages
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.
Nice
ReplyDeleteVery useful data.If you are looking for the best web development
ReplyDeletecompany, you have come to the right place.