Part 1 | Part 2 | Part 3
For example, here's how you can plug in a framework named A:
The page renders the UI shown in Figure 1. The UI prompts a user to guess a number that the system — in the person of Duke, the Java technology mascot — has selected. The UI displays the text Hi my name is Duke. I am thinking of a number from min to max. , where min and max represent the minimum and maximum values allowable as a guess, respectively. The UI also displays the Duke image, a text field for the user to enter a number, and a button to submit the form.
Enhanced Web Tier Capabilities
Some of the most significant enhancements made in Java EE 6 appear in the web tier. As mentioned earlier, one of the goals of Java EE 6 is to make the platform more extensible, and two key improvements in the area of extensibility are web fragments and shared framework pluggability. These two new features are provided in Java EE 6 by Servlet 3.0 technology. Servlet 3.0, JSR 315, the latest version of Servlet technology, offers some other valuable enhancements such as support for asynchronous processing and support for annotations.
Another important Java EE 6 web tier technology is JSF 2.0, the latest version of JSF technology. Among its benefits, JSF 2.0 simplifies page and component authoring through Facelets, and adds support for asynchronous JavaScript and XML (commonly referred to as Ajax), and annotations.
Support for Web Fragments in Servlet 3.0
Web application developers often use third-party frameworks such as Apache Wicket or Spring MVC in their applications. To use these frameworks, developers need to register the frameworks in the web application, a task that involves configuring framework-specific artifacts such as servlets and listener classes. It's typical for developers to register these frameworks by specifying deployment descriptors for the frameworks in the application's web.xml file — the same file that contains deployment descriptors for the web components that constitute the web application. Not only does this make for some very large web.xml, files but it also makes it difficult to isolate and maintain the descriptors for the frameworks.
Web fragments enable web frameworks to self-register, eliminating the need for you to register them through deployment descriptors.
|
Web fragments, a new feature of Servlet 3.0 technology, solve this problem by modularizing deployment descriptors. A web fragment can be considered a logical segment of a web.xml file. There can be multiple web fragments, each representing a logical segment, and the set of web fragments can be viewed as constituting an entire web.xml file. This logical partitioning of the web.xml file enables web frameworks to self-register to the web container. Each web framework that you use in a web application can define in a web fragment all the artifacts that it needs, such as servlets and listeners, without requiring you to edit or add information in the web.xml file.
Here is an example of a web fragment that registers a servlet and a listener:
<web-fragment>
<servlet>
<servlet-name>myFrameworkServlet</servlet-name>
<servlet-class>myFramework.myFrameworkServlet</servlet-class>
</servlet>
<listener>
<listener-class>myFramework.myFrameworkListener</listener-class>
</listener>
</web-fragment>
|
The <web-fragment> element identifies a web fragment. A web fragment must be in a file named web-fragment.xml and can be placed in any location in a web application's classpath. However, it's expected that a web framework will typically place its web fragments in the META-INF directory of the framework's JAR file, which will typically reside in the WEB-INF/lib directory of the web application.
You use the element <metadata-complete> in the web.xml file to instruct the web container whether to look for web fragments as well as annotations.
see Annotations in More Types of Java EE Components in Part 3 for information about annotations provided by Servlet 3.0 technology.
see Annotations in More Types of Java EE Components in Part 3 for information about annotations provided by Servlet 3.0 technology.
If you set <metadata-complete> to false, or do not specify the <metadata-complete> element in your web.xml file, then during deployment, the container must scan web fragments and annotations to build the effective metadata for the web application. In response, the web container searches for web fragments and annotations in framework JAR files. The web container then uses the configuration information in each web fragment to register the framework for use with the web application.
With its support for web fragments, Servlet 3.0 technology lets you modularize your web.xml file.
|
However, setting <metadata-complete> to true, causes the deployment descriptors to provide all the configuration information for the web application. In this case, the web container does not search for web fragments and annotations.
Because Servlet 3.0 technology supports web fragments, you can modularize your web.xml file. Your web application can still have the traditional, monolithic web.xml file, or it can have a logically partitioned web.xml file that includes one or more web fragments.
However, because Servlet 3.0 enables you to modularize your deployment descriptors, the order in which these descriptors are processed can be important. For example, the order in which the descriptors for an application are processed affects the order in which servlets, listeners, and filters are invoked. With Servlet 3.0, you can specify the order in which deployment descriptors are processed.
Servlet 3.0 supports absolute ordering and relative ordering of deployment descriptors. Your specify absolute ordering using the <absolute-ordering> element in the web.xml file. You specify relative ordering with an <ordering> element in the web-fragment.xml file.
For example, suppose your application includes two web fragments — MyFragment2 and MyFragment3, and also includes a web.xml file. You can declare absolute ordering of the descriptors by specifying the following in the web.xml file for the application:
<web-app>
<name>MyApp</name>
<absolute-ordering>
<name>MyFragment3</name>
<name>MyFragment2</name>
</absolute-ordering>
...
</web-app>
|
Here, the processing order would be as follows:
web.xml. The web.xml descriptor is always processed first
MyFragment3.
MyFragment2.
Web fragments and annotations are not the only way that Servlet 3.0 allows you to extend a web application. You can also plug in shared copies of frameworks, such as Java API for XML-Based Web Services (JAX-WS), JAX-RS and JSF that are built on top of the web container. Servlet 3.0 introduces a new interface called ServletContainerInitializer that can be used to plug in a framework.
For example, here's how you can plug in a framework named A:
@HandlesTypes(AnnotationA.class)
AServletContainerInitializer implements ServletContainerInitializer
{
public void onStartup(Set<Class<A>>c, ServletContext ctx) throws ServletException {
// Framework-specific code here to initialize the runtime
// and setup the mapping etc.
ServletRegistration reg = ctx.addServlet("AServlet", "com.foo.AServlet");
reg.addServletMapping("/foo");
|
The container discovers the ServletContainerInitializer using the JAR services API. It does this when the container or application is started. The framework implementing the ServletContainerInitializer must bundle in the META-INF/services directory of its JAR file a file called javax.servlet.ServletContainerInitializer that points to the implementation class of the ServletContainerInitializer.
The @HandlesTypes annotation specifies the types that the ServletContainerInitializer can handle. Any classes of those types discovered in any JAR contained in the WEB-INF/lib directory are passed to the ServletContainerInitializer. The ServletContainerInitializer is then able to use the same programmatic configuration APIs as ServletContextListeners.
The @HandlesTypes annotation specifies the types that the ServletContainerInitializer can handle. Any classes of those types discovered in any JAR contained in the WEB-INF/lib directory are passed to the ServletContainerInitializer. The ServletContainerInitializer is then able to use the same programmatic configuration APIs as ServletContextListeners.
Servlet 3.0 introduces support for asynchronous processing. With this support, a servlet no longer has to wait for a response from a resource such as a database before its thread can continue processing, that is, the thread is not blocked. This support enables long-lived client connections such as those in chat room applications. In these types of applications you don't want a server thread to be blocked for a long period of time serving a request from a single client. You want the servlet to process a request from the client and then free up the server thread as quickly as possible for other work. Among its benefits, support for asynchronous processing makes the use of servlets with Ajax more efficient.
A servlet no longer has to wait for a response from a resource such as a database before its thread can continue processing.
|
Servlets and servlet filters that support asynchronous processing must be written with the goal of asynchrony in mind. In particular, several long-standing assumptions about the order in which some methods will be called do not apply for asynchronous processing.
To ensure that code written for synchronous processing won't be used in an asynchronous context, Servlet 3.0 requires you to use the asyncSupported=true attribute. To make a servlet asynchronous, you specify asyncSupported=true in a @WebServlet annotation and make asynchronous requests in the servlet.
To ensure that code written for synchronous processing won't be used in an asynchronous context, Servlet 3.0 requires you to use the asyncSupported=true attribute. To make a servlet asynchronous, you specify asyncSupported=true in a @WebServlet annotation and make asynchronous requests in the servlet.
You can also mark a servlet filter as asynchronous by specifying asynchSupported=true in a @WebFilter annotation. Only after taking these steps are taken the corresponding classes available for asynchronous invocations.
The support for asynchronous processing also includes new ServletRequest methods, such as startAsync(), to make an asynchronous request, and new classes, such as AsyncContext, which provides the execution context for an asynchronous operation.
Here, for example, is a servlet that makes an asynchronous request.
@WebServlet(name="CalculatorServlet", asyncSupported=true, urlPatterns={"/calc", "/getVal"})
public class CalculatorServlet extends HttpServlet{
public void doGet(HttpServletRequest req, HttpServletResponse res) {
...
AsyncContext aCtx = req.startAsync(req, res);
}
...
}
|
Notice that the startAsync() method returns an AsyncContext object. This object holds the request and response objects that were passed in the call to the method. At this point, the thread that served the original request is available for other operations.
Servlet 3.0 also introduces a new listener class, AsyncListener that notifies you when an asynchronous operation is complete or if a timeout occurs. The AsyncContext class includes a complete() method, with which you can commit the response after an asynchronous operation is complete. The AsyncListener class also has a dispatch() method that forwards the asynchronous request to the container so that other frameworks such as JSP can generate the response.
JavaServer Faces technology provides a server-side component framework that simplifies the development of user interfaces (UIs) for Java EE applications. The latest release of the technology, JSF 2.0, JSR 314, makes UI development for Java EE applications even easier. One area of particular improvement is page authoring. Authoring a JSF page is much easier in JSF 2.0 through the use of the standard JavaServer Faces View Declaration Language, commonly called Facelets.
Facelets
Facelets is a powerful but lightweight declaration language that you can use to present JSF pages.
|
Facelets is a powerful but lightweight declaration language that you can use to present JSF pages. In the Facelets approach, you use HTML-style templates to present a JSF page and to build component trees. Although JSF can be used with different display technologies, most JSF applications use JSP as the display technology. In other words, the UI in a JSF application is typically a JSP page that contains JSF components. However, Facelets offers several advantages over JSP.
Facelets is now the preferred presentation technology for building JSF-based applications.
|
In JSP, elements in a web page are processed and rendered in a progressive order. However, JSF provides its own processing and rendering order. This can cause unpredictable behavior when web applications are executed. Facelets resolves this mismatch. Facelets also enables code reuse through templating and can significantly reduce the time to develop and deploy UIs. For these reasons, Facelets is now the preferred presentation technology for building JSF-based applications.
Facelets are usually written with XHTML markup language. This allows Facelets pages to be portable across diverse development platforms. Here, for example, is a Facelets XHTML page that is part of a sample JSF application provided with the Java EE 6 Tutorial.
<xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<head>
<title>Guess Number JSF Application</title>
</head>
<body>
<h:form>
<h2>
Hi. My name is Duke. I am thinking of a number from <b>
<h:outputText value="#{UserNumberBean.minimum}"/> to
<b>
<h:outputText value="#{UserNumberBean.maximum}"/>.
<p>
Can you guess it ?
</p>
<h:graphicImage id="waveImg" url="/wave.med.gif" />
<h:inputText id="userNo"
value="#{UserNumberBean.userNumber}">
converterMessage="#{ErrMsg.userNoConvert}">
<f:validateLongRange
minimum="#{UserNumberBean.minimum}"
maximum="#{UserNumberBean.maximum}"/>
</h:inputText>
<h:commandButton id="submit"
action="success" value="submit" />
<h:message showSummary="true" showDetail="false"
style="color: red;
font-family: 'New Century Schoolbook', serif;
font-style: oblique;
text-decoration: overline"
id="errors1"
for="userNo"/>
</h2>
</h:form>
</body>
</html>
|
The page renders the UI shown in Figure 1. The UI prompts a user to guess a number that the system — in the person of Duke, the Java technology mascot — has selected. The UI displays the text Hi my name is Duke. I am thinking of a number from min to max. , where min and max represent the minimum and maximum values allowable as a guess, respectively. The UI also displays the Duke image, a text field for the user to enter a number, and a button to submit the form.
|
This Facelets XHTML page is not very different from an equivalent JSP page. In particular, Facelets supports JSF and JSTL tag libraries. Facelets also includes a Facelets tag library that enables feature-rich page templating. The namespace declaration xmlns:ui="http://java.sun.com/jsf/facelets" is for the Facelets tag library — although no tags in that library are used in this example. Facelets also supports the unified expression language.
It might not be evident here what additional value Facelets provides over JSP. To better understand the value of Facelets, let's examine two of its most powerful features: templating and composite components.
Templating
Templating allows you to create a page that acts as a template for other pages in an application.
|
With templating, you can create a page that acts as a template for other pages in an application. This helps you avoid creating similarly constructed pages multiple times. Templating also helps maintain a standard look and feel in an application with a large number of pages.
The Facelets tag library contains a templating tag, <ui:insert>. To implement templating, you create a template page that includes the <ui:insert> tag. You then create a client page that uses the template. In the client page, you use a <ui:composition> tag to point to the template and <ui:define> tags to specify content to insert into the template.
Here is an example of a template page.
<xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
<head>
<title><ui:insert name="title">Page Title</ui:insert</title><body>
</head>
<body>
<div>
<ui:insert name="Links"/>
</div>
<div>
<ui:insert name="Data"/>
</div>
</body>
</html>
|
Here is an example of a client page that uses the template.
<xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
<body>
<ui:composition template="/template.xhtml">
This text will not be displayed.
<ui:define name="title">
Welcome page
</ui:define>
<ui:define name="Links">
... [Links should be here]
</ui:define>
<ui:define name="Data">
... [Data should be here]
</ui:define>
</ui:composition>
This text also will not be displayed.
</body>
</html>
|
When the template is invoked by the client, it renders a page with the title Welcome Page. The page also displays two sections: one that lists the links specified in the client, and one that shows the data specified in the client.
Composite Components
A composite component makes it easy to create customized JSF components.
|
Composite components is a new feature in JSF that makes it easy to create customized JSF components. You can create composite components by using JSF page markup, other JSF UI components, or both. And with the help of Facelets, any XHTML page can become a composite component. In addition, composite components can have validators, converters, and listeners attached to them just like the set of UI components provided by JSF.
After you create a composite component, you can store it in a library and use it as needed.
Let's create a composite component that is rendered as a login panel. When a user logs in, the component reports a login event as shown in Figure 2.
|
Here is the source code for the composite component.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
xmlns:f="http://java.sun.com/jsf/facelets">
xmlns:composite="http://java.sun.com/jsf/composite">
<h:head>
<title>This content will not be displayed in the rendered output</title>
</h:head>
<h:body>
<composite:interface>
<composite:actionSource name="loginEvent"/>
</composite:interface>
<composite:implementation>
<table>
<tr>
<td>Username: <h:inputText id="username" /> </td>
</tr>
<tr>
<td>Password: <h:inputSecret id="password" /></td>
</tr>
<tr>
<td><h:commandButton value="Login" id="loginEvent" /></td>
</tr>
</table>
</composite:implementation>
</h:body>
</html>
|
The declaration xmlns:composite="http://java.sun.com/jsf/composite" declares the namespace for composite UI components. The <composite:interface> tag declares the usage contract for the composite component, in other words, what a page author needs to know to use the composite component. The <composite:attribute> tag in the usage contract specifies a <composite:actionSource> tag.
This tag indicates that the component can expose an event, making it accessible by any page that uses the composite component.
The <composite:implementation> tag defines the implementation for the composite component. Here the implementation is a simple table that contains JSF components for the username and password fields and a login button.
To make the composite component available for use, you save the code in an XHTML file and then store the file in a subdirectory of the resources directory under the application root directory. The name of the subdirectory is taken to be the name of the resource library that contains the composite component. The JSF runtime finds the composite component by appending .xhtml to the name of the composite component's tag. For example, if you name the tag loginPanel, store the code for the composite component in a file named loginPanel.xhtml.
You can then use the composite component in a web page. Here, for example, is the code for the web page shown in Figure 2 that uses the composite component.
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:ez="http://java.sun.com/jsf/composite/ezcomp">
<head>
<title>Example 01>/title>
<style type="text/css">
.grayBox { padding: 8px; margin: 10px 0; border: 1px solid #CCC; background-color: #f9f9f9; }
</style>
</h:head>
<h:body>
<p>Usage of Login Panel Component</p>
<ui:debug hotkey="p" rendered="true"/>
<h:form>
<div id="compositeComponent" class="grayBox" style="border: 1px solid #090;">
<ez:loginPanel>
<f:actionListener for="loginEvent" type="example01.LoginActionListener" />
</ez:loginPanel>
</div>
<p><h:commandButton value="reload" /></p>
<p><h:outputText value="#{loginActionMessage}" /></p>
</h:form>
</h:body>
</html>
|
Notice the declaration xmlns:ez="http://java.sun.com/jsf/composite/ezcomp". This specifies the namespace and prefix for the composite component. In this case, ezcomp is the name of the subdirectory in the resources directory. JSF uses the following convention: for any namespace URI starting with http://java.sun.com/jsf/composite/, the one and only path segment that ends the namespace URI is taken to be the name of the resource library in which the Facelets XHTML files for the composite components are found.
The <f:actionListener> tag associates an action listener with the composite component. The for attribute in the tag indicates that this listener is for the action event named loginEvent on the composite component. You would also need to provide code to process the event. For example, you might provide code that looks something like the following:
import javax.faces.component.UIComponent;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
public class LoginActionListener implements ActionListener {
public void processAction(ActionEvent event) throws AbortProcessingException {
FacesContext context = FacesContext.getCurrentInstance();
context.getExternalContext().getRequestMap().put("loginActionMessage",
"Login event happened");
}
}
|
Support for Ajax in JSF 2.0
JSF 2.0 has built-in support for Ajax, making it easier to develop dynamic web applications that take advantage of both JSF technology and Ajax.
|
JSF 2.0 has built-in support for Ajax. With Ajax, web applications can retrieve data from the server asynchronously in the background without interfering with the display and behavior of the existing page.
In support of Ajax, JSF's request processing cycle has been expanded to allow partial page updates and partial view traversal. Partial view traversal allows one or more components in a view to be visited, potentially to have them pass through either or both the execute phase or render phase of the request processing lifecycle. This is a key feature in JSF and Ajax frameworks and it allows selected components in the view to be processed, rendered, or both.
To use Ajax with JSF you need to access a JavaScript resource that has the resource identifier jsf.js. The resource, which exists under the javax.faces resource library, contains the JavaScript API that enables JSF to interact with Ajax. The JavaScript API comprises a standard set of JavaScript functions that facilitate Ajax operations in a JavaServer Faces framework. You rarely need to include this file directly. JSF automatically includes it whenever you use any Ajax-enabled tags or components in your view.
You can then make an Ajax request in either of two ways. You can use the <f:ajax> tag or you can invoke functions in the JavaScript API.
Here is an example that uses the <f:ajax> tag:
<h:commandButton id="button1">
<f:ajax execute="..." render="..."/>
</h:commandButton>
|
Here, the <f:ajax> tag is nested inside an <h:commandButton> tag. This associates the Ajax action specified in the execute attribute with the command button rendered by the <h:commandButton> tag. You can also specify an event attribute to identify the JavaScript DOM event to which the Ajax action applies. If you do not specify an event attribute, JSF uses the default action for the component. In this case, the default action is onclick, so JSF associates the Ajax request specified in the execute attribute with the onclick event of the rendered button. When a user clicks the button, JSF submits the Ajax request to the server.
One benefit of using the <f:ajax> tag is that you don't have to specifically load the jsf.js resource in your page — it is done automatically for you. By comparison, if you invoke the JavaScript API, you first have to make the jsf.js resource available to the current view, using an<h:outputScript> tag. For example:
<f:view contentType="text/html"/>
<h:head>
<meta...
<title...
</h:head>
<h:body>
...
<h:outputScript name="jsf.js" library="javax.faces" target="body"/>
...
</h:body>
...
|
You then use functions in the JavaScript API to make Ajax requests. For example, you use the JavaScript function jsf.ajax.request to send an Ajax request to the server, as shown in the following code example. The code includes a <h:commandButton> tag that renders a button. When a user clicks the button, an Ajax request is submitted to the server.
<h:commandButton id="button1" value="submit" onclick="jsf.ajax.request(this,event);" />
|
JSF 2.0's built-in support for Ajax makes it a lot easier to develop dynamic web applications that take advantage of both JSF technology and Ajax.
This section covered only some of the many new features and enhancements in Servlet 3.0 and JSF 2.0. Another new feature of note in Servlet 3.0 enables you to use methods in the ServletContext class to programmatically add servlets and servlet filters to a web application during startup. You use the addServlet() method to add a servlet to the web application, and the addFilter() method to add a servlet filter. The ability to programmatically add servlets and servlet filters at startup is particularly useful to framework writers. In conjunction with the shared framework pluggability feature by which extension libraries can discover classes listed in the @HandlesTypes annotation, with this facility web frameworks can configure themselves with no developer intervention.
In addition, Servlet 3.0 works with a number of enhanced security features. For example, in addition to declarative security, Servlet 3.0 offers programmatic security through the HttpServletRequest interface. You can, for example, use the authenticate() method of HttpServletRequest in an application to perform username and password collection, or you can use the login() method to direct the container to authenticate the request caller from within an unconstrained request context. For more information about these and other features in Servlet 3.0, see Servlet 3.0, JSR 315.
Some additional enhancements in JSF 2.0 relate to how resources are packaged and handled. JSF 2.0 standardizes where resources are packaged. All resources now go in a resources directory or a subdirectory. Resources are any artifacts that a component may need in order to be rendered properly, such as CSS files or JavaScript files. Figure 3 shows part of a NetBeans IDE project for a JSF application. Notice the resources directory in the project and the CSS and image resources it contains.
Figure 3. Resources in the resources Directory of a JSF Application |
JSF 2.0 also includes new APIs for representing and handling resources. You use the javax.faces.application.Resource class to represent a resource. You use the javax.faces.application.ResourceHandler class to create instances of resources as well as to serve resources to the requesting user agent. For more information about these and other features in JSF 2.0, see the JSR 314: JavaServer Faces 2.0 specification.
No comments :
Post a Comment