Seam-Seamless integration of JSF, part 3rd: Ajax for JSF Seamless fusion with Seam Remoting and AJAX4JSF User and server |
|
Level: Intermediate
Dan Allen (dan.allen@mojavelinux.com), Senior Java engineer, Coderyte, Inc.
June 25, 2007 JSF's component-based methodology facilitates abstraction, but most Ajax implementations are greatly disrupted by exposing the underlying HTTP exchange. In the final article of the seamless integration of the JSF series, Dan Allen showed how to communicate with the managed beans on the server using the Seam Remoting API and the AJAX4JSF component as if the beans were local to the browser. You will learn how easy it is to take advantage of Ajax as a natural improvement on the JSF event-driven architecture, and how to do this without impacting the JSF component model.
Today, most Java™ developers are bullish on mashups, so you might be confused about how Seam and the so-called WEB 2.0 technology, especially Ajax, can be integrated. It would be cool to use Seam to start some of the page updates in JSF or to help JSF application mashups with Google maps, wouldn't it? Not only can you do this, but it's also very easy.
|
more Ajax technical resources.
Visit the Ajax Technology Resource Center, a one-stop center for information about AJAX programming models, including many documents, tutorials, forums, blogs, wikis, and news. Any new information about Ajax can be found here. |
|
In the last article in the seamless integration of the JSF series, I'll show you how to use the Seam Remoting API and the AJAX4JSF component to assist in Ajax-style interactions based on JSF applications. As you'll see, the great benefit of combining Seam and Ajax is that it allows you to enjoy all the WEB 2.0 luxuries without the pain of using JavaScript XMLHttpRequest objects. With Seam Remoting and AJAX4JSF, you can communicate with managed beans on the server as if the beans were local to the browser. Browsers and server states are synchronized, and there is no need to deal with low-level APIs that facilitate communication between them.
I'll start by showing you how Seam is a new component-based way to drive Ajax programming. You will learn how to use the Seam Remoting API to communicate between JavaScript and server-side objects through Ajax. Once you understand this new (and simple) approach to Ajax, you can use it to enhance Open 18 applications by creating a mashup between the Open 18 Stadium directory and Google Maps. Use AJAX4JSF to merge the course directory pages and the course Details page of the application. Re-access the application's spring integration and make the spring bean available in Seam Remoting lifecycle.
|
upgrade to Seam 1.2.1.GA Seam World is developing rapidly and a new version of the framework has been published since the previous article in this series. The sample in this article refers to Seam 1.2.1 or later. In earlier versions of Seam, the server-side remoting functionality was fully implemented by Seamremotingservlet. In the most recent release, the functionality has been refactored into Seam Remoting packages, and a generic resourceservlet is used to assign processing of non-JSF requests, such as Remoting calls. In addition, the remoting library is now packaged as a separate JAR, the Jboss-seam-remoting.jar. In addition to the jars needed to run the example in this series, "seam-Seamless integration JSF, part 1th: Application framework tailored for JSF," you also need to include the jar in your application classpath. |
|
The mashup between Open 18 and Google Maps allows users to locate locations in the golf course directory in the map. Combining this field directory with the Pitch Detail page (and Ajax for low-level code) allows you to display the details of the course without loading a new page. Integrating the Spring bean and Seam Remoting allows you to capture the repositioning of Google Maps location tags and store the latitude and longitude of the relevant pitches in the database. As you can see, the result is a WEB 2.0-style application that all golfers like to use, which is impressive.
If you've ever suffered from overly complex AJAX programming involving a lot of JavaScript, and if you've so far avoided using AJAX because you don't want to face complexity, what this article is going to teach will help you avoid that worry. When refactoring an application, you need to do some JavaScript coding, but unlike most Ajax implementations, JavaScript does not occupy much of your code; instead, it extends only server-side Java objects.
Different paths to Ajax
Just as you want to avoid explicit memory management in your application, you don't want to have to deal with low-level Ajax request protocols. Doing so will only cause more trouble (or, more specifically, more trouble), such as multiple browser support, data marshaling, concurrency conflicts, server load, and custom servlet and servlet filters. One of the biggest problems you want to avoid is an inadvertent, stateless request-response paradigm, but the example is a component-based framework, such as JSF, that you want to hide.
The JSF lifecycle facilitates component-oriented design by shielding application code from the underlying servlet model. To keep this abstraction in the process of Ajax, you can leave these trivial tasks at the lower levels to Seam Remoting or AJAX4JSF processing. Both libraries are responsible for the pipeline processing required to fuse the JSF components into the browser through Ajax interaction. Figure 1 shows the Seam Remoting in the actual application. When an event is triggered, such as when a user clicks a button, the message is sent asynchronously to the component on the server. Once a response is received, it is used to incrementally update the page. Low-level communication protocols used to process interactions between browsers and server-side components are hidden behind APIs.
|
about this series Seam-Seamless integration JSF tells me that seam is the first application framework that really fits into JSF, and can fix the main vulnerabilities that other extension frameworks can't fix. By reading the series, you can decide for yourself whether Seam is a proper complement to JSF. |
|
In the use case shown in Figure 1, the user can see the result of the method call that occurred after the button was clicked. When studying this use case, there are two important points to note: (1) the page will never be refreshed, (2) The client code communicates transparently with the method on the component, rather than explicitly building and then requesting the URL. Standard HTTP requests are used in the background, but client code never needs to interact directly with the HTTP protocol.
Figure 1. Seam Remoting Fusion JSF components and browsers
Seam Remoting and AJAX4JSF
Seam Remoting and AJAX4JSF are two unique libraries that serve the "Ajax" purpose of JSF respectively. All two libraries use Ajax to introduce an interactive model in which communication between browsers and servers can occur asynchronously in the background and is not visible to users. There is no need to waste time on user page overloading in order to execute methods on the server. The information retrieved by the server in the Ajax requests issued by these libraries can be used to incrementally update the status of the page in real time. Two libraries can be equipped with a lifecycle that restores the status of the (restore) component when the browser needs it. This Ajax interaction is not a real request but rather a "recovery and execution". The browser looks like the "knock" on the server's shoulder, and it executes a method on a managed bean on the server side and returns the result.
Although the two libraries work differently, they are not mutually exclusive. Since they all use the JSF component model, they can be easily combined, which is described in detail later in this article. For now, we just need to consider separately how Ajax-style interactions are introduced into JSF applications: Seam Remoting provides JavaScript APIs that can be used to access JavaScript in the same way as local objects Server-side components in order to send and retrieve data through method calls. Seam Remoting uses a custom, non-JSF lifecycle to enable the browser to communicate with the server-side components. Only the Seam container and its components can be recovered during these requests. The transparency protocol is Ajax, but you don't have to bother with the details of how the packet is transmitted.
AJAX4JSF is a step closer to abstraction by completely hiding the use of JavaScript. It wraps all the logic within the base UI component. AJAX4JSF accepts Ajax requests through a complete JSF lifecycle. Thus, Ajax-enabled components can execute action handlers without triggering browser navigation events, upgrade the JSF component tree, and render portions of the page again. Similarly, communications are implemented through AJAX, but all of these occur in the background and are not visible to page developers. AJAX4JSF's component-oriented approach makes AJAX functionality a natural part of JSF, not an outsider.
I'll delve into these ways, but let's take a look at the basics of Ajax.
|
Back to the top of the page |
|
Narrowing differences
To make your application a "rich" application in the sense of Ajax/web 2.0, a Web browser (or client) must have direct access to the components on the server. Because of the huge differences between client and server, it is challenging to make this goal a reality. One aspect of the difference (that is, the network) exists in the client browser, on the other hand, on the server and its components. One of the goals of Ajax applications is to make them "talk" to each other.
In fact, in most traditional WEB applications, the client and the server can communicate normally, but interactivity is completely different. The server initiates a conversation and the browser listens to the conversation. It is not surprising that you have been caught up in such dialogues before. In a world without Ajax communications, a browser can send a sync request to any URL, but it must render the HTML that the server sends back. Another disadvantage of this type of interactivity is that there is a lot of waiting time.
In the case of HTTP, which has no development language, the browser client will have absolutely nothing to do with how the server generates HTML, and thus the content of its components is unknown. From a browser standpoint, the page generation process is a completely black box. The browser can ask the server a different question in the form of a URL and pass the prompts packaged as request parameters and POST data, but it does not actually speak the language of the server. If you want to provide a browser with a view of the action to the application server side, you need to build more sophisticated means of communication. This page-oriented deterministic approach can do nothing about it.
Web Browser as an Ajax client
Seam Remoting and AJAX4JSF are different ways to break the gap between customers and browser components, so it's important to know how to take advantage of both. Seam Remoting provides a browser-local language JavaScript-form API that can be accessed through methods on the server-side components of these APIs. To assign access to these methods, they must be explicitly marked as "Remote" by @Remote annotations.
The invocation mechanism in Seam Remoting is similar to Java RMI, both of which use a local proxy object or a "stub" to allow JavaScript to invoke components that reside on a remote server. In the case of a customer, the stub object is a remote object. The stub is responsible for implementing method execution on the actual remote object. When the remote method is invoked, the response encapsulates the return value of this method invocation. The return value is prepared to be processed into a JavaScript object. Therefore, Seam Remoting allows the browser to "speak" the local language of the server. The combination of Java code and JavaScript is a bit of a surprise to those who think the two are originally a language.
|
a conversation with Ajax Seam leads to Ajax in a way that allows the browser to have complex details about the state of the server, such as which conversations are currently active dialogues, stakes related. The ability to use Seam Remoting to control the content of a conversation can be important for remote invocation of objects that need to be in the conversation scope in the future. |
|
On the other hand, AJAX4JSF provides JSF component tags to declaratively correlate the action handlers on UI events and server-side managed beans. These action handler methods do not need to be marked as "remote." Instead, they are traditional JSF action handlers, or public methods on managed beans, either without arguments or accepting actionevent.
Unlike Seam Remoting, AJAX4JSF can return changes in the JSF component tree to the browser. These changes are returned in the form of XHTML fragments. These segments are associated with a single JSF component on this page and prove themselves to be partial-page updates. Therefore, the isolation area of this page can be rendered anew by the browser with the new markup. These segments are special requests, either by using the Rerender attribute marked by the AJAX4JSF component, or by encapsulating multiple regions of the template into an output panel labeled "True" with the attribute ajaxrendered=. The Rerender property represents a specific set of components that should be reproduced, referenced by their component IDs. By contrast, the use of ajaxrendered= "true" is a bit too comprehensive, requiring that all "Ajax-rendered" areas be updated as long as the AJAX request for AJAX4JSF management is complete.
AJAX4JSF and Seam Remoting enable browsers to grow from basic HTML renderer to a mature Ajax client. When integrating these two frameworks, the application is really exciting. In fact (the news is a little surprising, so you'd better sit down and listen), combining Seam Remoting and AJAX4JSF features allows you to free yourself from developing your own custom Ajax JSF components. You can use any existing, non-Ajax-enabled JSF component in Ajax communications by nesting a4j:support tags in its declarations. You can manage this interaction with Seam Remoting if you work outside the UI component (as you did in the later Google Maps mashup) and you need to query server-side components for information, update the component, or instruct it to perform operations.
While Seam Remoting and AJAX4JSF are functionally overlapping, both can be beneficial in adding Ajax-style interactions to the application. In addition, you will soon see that two libraries provide a seamless Ajax solution for JSF applications.
|
Back to the top of the page |
|
Seam Remoting Quick Start
If Seam Remoting is not so complex to implement, then it is an ideal solution. Don't worry. Seam Remoting is not as scary as the remote EJB objects you've been exposed to. Using the Seam Remoting API to enable JavaScript code to interact with server-side components The best side is that the process is unusually simple. Seam can really do all the hard work for you-you don't even have to edit a row of XML to start using it. (If you're doing more XML programming than Java programming at the moment, this is really exciting news.) )
Let's take a quick look at the steps required to "Ajax" a JSF application using Seam Remoting.
Exposing beans
There are two requirements for exposing server-side object methods to remote Ajax: This method must be a public member of the Seam component and must be equipped with @WebRemote annotations. That's two points.
The actual simplicity is illustrated in Listing 1, where Seam component Reasonpotaction exposes a single method to Ajax customers for remote execution, that is, Drawreason (). Each time this method is invoked on this stub, the call is passed across the Internet to the server and one of the top ten reasons for using Seam in the project is randomly selected by using the corresponding method on the server side. The server then returns this value to the customer (for more information on these 10 reasons, see Resources).
Listing 1. Exposing remote method calls
@Name ("Reasonpot") @Scope (scopetype.session) public class Reasonpotaction { Private static string[] reasons = new string[] { "It's the quickest way to get/" rich/"." "It's the easiest way to get started with EJB 3.0.", "It ' s best way to leverage JSF." "It ' s the easiest way to do BPM.", "But CRUD are easy too!", "It makes persistence a breeze.", "Use annotations (instead of XML).", "Get hip to automated integration testing." "Marry open source with open standards." "It Just works!" };
Private Random Randomindexselector = new Random ();
@WebRemote Public String Drawreason () { Return Reasons[randomindexselector.nextint (reasons.length)]; } }
|
Services to resources
Once the server-side component is set up, you need to have the browser ready to invoke the @WebRemote method. Seam uses a custom servlet to process HTTP requests to execute a remote method and return its results. Don't worry: You won't have to interact directly with that servlet. Seam Remoting The JavaScript library handles all the interactions with the seam servlet, and is handled in the same way that it manages all aspects of the XMLHttpRequest object.
The only thing you need to consider when using this servlet is to set Seam Remoting in your application. Better yet, you only need to configure seam's custom servlet once, regardless of the number of seam features that require custom servlet services. Contrary to the use of a specific servlet for each attribute-the attribute may be to provide a resource (such as a JavaScript file) to the browser or to handle a non-JSF request (like an AJAX remoting call), Seam binds all of these tasks to a single controller Reso Under the Urce Servlet. This servlet uses a delegation chain model to pass these tasks to the registered handler. For example, the Remoting object (which I'll introduce later) registers itself to receive all Ajax requests from Seam Remoting JavaScript libraries.
The XML definition of the Resource servlet is shown in Listing 2 and must be installed in the application's Web.xml file under Faces Servlet:
Listing 2. Seam Resource The XML definition of the Servlet
<servlet> <servlet-name>seam Resource servlet</servlet-name> <servlet-class>org.jboss.seam.servlet.ResourceServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>seam Resource servlet</servlet-name> <url-pattern>/seam/resource/*</url-pattern> </servlet-mapping>
|
Self-booting API
The real behind-the-scenes reason for Seam Remoting mechanism is the JavaScript library. The Resource Servlet assigns jobs to Remoting objects to service these libraries. The two JavaScript libraries emitted create a browser-appropriate hook to invoke the remote method using JavaScript.
You must import all two JavaScript libraries into the page, as shown in Listing 3. The first library remote.js is static, passing Seam's client remoting framework to the browser. The second library Interface.js is created dynamically on each request. It contains the remote stub and the complex types required to interact with the server-side components. Note that Seam does not generate stubs and complex types for all components that specify a method for the remote. Instead, it resolves the interface.js URL? The query string after the character to collect the name of the component to expose. Each component name is made up of & Symbol separation. This stack-style method allows the browser to make a minimum number of requests for external JavaScript files. Seam will then generate only these stubs and complex types for these components. As an example, the two JavaScript imports in Listing 3 will load the seam Remoting library and instruct seam to prepare the Reasonpot and Anothername components:
Listing 3. Importing client frameworks and APIs
<script type= "Text/javascript" Src= "Seam/resource/remoting/resource/remote.js" ></script> <script type= "Text/javascript" Src= "Seam/resource/remoting/interface.js?reasonpot&anothername" ></script>
|
With this, you are ready to proceed. You have finished Seam Remoting settings, and you can now start making some remote calls.
|
Back to the top of the page |
|
Make a remote call
All client framework code for seam Remoting libraries is encapsulated in seam JavaScript objects. In fact, this high-level object is just a namespace-a container that can bundle a set of functions under only one by one names. In JavaScript, namespaces are simply objects that can load static properties, static methods, and other nested namespace objects. The important thing to note is that the JavaScript in Seam Remoting can work well with other JavaScript. This means that you can take advantage of libraries such as Prototype or Dojo to allow the JSF UI to interact with server-side components. Using a third-party JavaScript library in the JSF UI used to be a huge challenge for JSF developers, so Seam JavaScript objects are popular:
The capabilities of Seam Remoting libraries are allocated between Seam.component and Seam.remoting namespace objects. The Seam.component static method provides access to the remote Seam component, while the static Seam.remoting method controls Remoting settings and creates custom data types. As you can see from this example, the custom data type is any non-primitive object that needs to be created locally to invoke the remote method.
Execution details
To execute a remote method, first obtain an instance of the component that holds the method. If you want to use an existing Seam component instance (meaning that it already exists on the server), you can use Seam.Component.getInstance (), and if you want to instantiate a new instance before making the call, you can use the Seam.Component.newInstance (). These instances are remote stubs that are dynamically built by Seam. The stub proxy all method calls, processes the component names, methods, and parameters into XML, and passes the XML payload to the server-side component through an AJAX request. The remoting framework code on the server gets the request, unlocks the XML, extracts the component name, methods, and arguments, and then increases the method on the server-side component instance. Finally, the server sends back the return value to the client in response to an Ajax call. Again, all of this work is hidden behind the stub, greatly simplifying the JavaScript code.
So far, the background of the introduction is enough. Listing 4 shows how to perform the Drawreason () method on the Reasonpot component in the conversation scope, which is marked as a remote service in Listing 1. Once you have the component stub, execute this method just as any other JavaScript method call does.
Listing 4. Calling the remote method
<script type= "Text/javascript" > Seam.Component.getInstance ("Reasonpot"). Drawreason (Displayreason);
function Displayreason (reason) { alert (reason); } </script>
|
In Listing 4, it should be noted that there is an important difference between the method on the stub and the "actual" method on the server-side component. Are you aware of that? Each call on the component stub is completed asynchronously. This means that the result of a remote method call is not immediately available to the executing thread. Because of this, the method on the stub does not have the value to return, regardless of whether the matching server-side method has the value to return. When the method on the remote stub executes, it actually seems to say, "OK, I'll reply you later, please leave your contact number." "The code you provide is actually the callback JavaScript function." The task is to capture the actual return value.
The callback function is the standard structure of the asynchronous API. When the response from an AJAX request returns to the browser, it is executed by Seam Remoting JavaScript framework. If a method on a server-side component has a non-null return value, the value is passed into this callback function as its unique argument. On the other hand, if the method on the server-side component has an empty return type, this optional argument can be ignored.
Conversation within the scope of the bean
For most remoting requirements, you can use the APIs described so far to address them. If the request is given in order to retrieve a server-side component or to execute one of its exposed methods, the component must be visible during the remoting lifecycle. References to beans within the conversation scope do not require any extra work because these beans are always available for HTTP requests made in the same browser dialog.
Beans in the conversation scope require more skill because they are associated with HTTP requests based on the presence of a dialog token. When working with beans within the conversation scope, you must be able to establish the correct dialog context during a remote invocation. This dialog is reactivated by sending a dialog token with a remote request. The details of this interaction are handled by the Seam Remoting framework as long as you provide a dialog token.
Keep in mind that Ajax requests can be sent from the same window to communicate with two or more conversations on this server. If you specify a dialog ID before retrieving the component instance stub, Seam can differentiate between them. This can be accomplished using Seam.Remoting.getContext (). Setconversationid ("#{conversation.id}").
Seam always exposes the current conversation under #{conversation.id} value-binding expressions. JavaScript can actually see the parsed values, usually a numeric value, not an expression placeholder. You can register the value with the remoting content, and it will then be delivered by subsequent requests. Instead, you can read the dialog ID that was allocated in the previous request by calling Seam.Remoting.getContext () after the remote call was initiated. Getconversationid (). In this way, remoting calls can take full advantage of the benefits of the conversation scope and participate in state behavior.
|
Back to the top of the page |
|
Google maps and Open 18 applications