Configuring Seam applications for Seam Remoting

From ThemesWiki

Jump to: navigation, search
Configuring Seam applications for Seam Remoting
Official Page
Project Documentation
Download
Source Book
200px-184719592X.jpg
ISBN 978-1-847195-92-0
Publisher Packt Publishing
Author(s) David Salter

To configure a web application to use Seam Remoting, declare the Seam Resource servlet within our application's WEB-INF/web.xml file as follows.

 <servlet>
  <servlet-name>Seam Resource Servlet</servlet-name>
  <servlet-class>
  org.jboss.seam.servlet.SeamResourceServlet
  </servlet-class>
 </servlet>
  <servlet-mapping>
  <servlet-name>Seam Resource Servlet</servlet-name>
  <url-pattern>/seam/resource/*</url-pattern>
 </servlet-mapping>

That's all a Seam web application will work with Seam Remoting. To make things even easier, this configuration is automatically done when applications are created with SeamGen, so you would have to worry about this configuration only if you are using non-SeamGen created projects.criminal justice degree


Contents

[edit] Configuring Seam Remoting server side

To declare that a Seam component can be used via Seam Remoting, the methods that are to be exposed need to be annotated with the @WebRemote annotation. For simple POJO components, this annotation is applied directly on the POJO itself, as shown in the following code snippet.

 
 @Name("helloWorld")
 public class HelloWorld implements HelloWorldAction {
 @WebRemote
 public String sayHello() {
 return "Hello world !!";
 }

For Session Beans, the annotation must be applied on the Session Beans business interface rather than on the implementation class itself. A Session Bean interface would be declared as follows.

 import javax.ejb.Local;
 import org.jboss.seam.annotations.remoting.WebRemote;
  @Local
  public interface HelloWorldAction {
  @WebRemote
  public String sayHello();
  @WebRemote
  public String sayHelloWithArgs(String name);
 }

The implementation class is defined as follows:

 import javax.ejb.Stateless;
 import org.jboss.seam.annotations.Name;
 @Stateless
 @Name("helloWorld")
 public class HelloWorld implements HelloWorldAction {
  public String sayHello() {
  return "Hello world !!";
  }
  public String sayHelloWithArgs(String name) {
  return "Hello "+name;
  }
  }

Note that, to make a method available to Seam Remoting, all we need to do is to annotate the method with @WebRemote and then import the relevant class. As we can see in the preceding code, it doesn't matter how many parameters our methods take.

[edit] Configuring Seam Remoting client side

In the previous sections, we've seen that minimal configuration is required to enable Seam Remoting and to declare Seam components as Remoting-aware. Similarly in this section, we'll see that minimal work is required within a Facelets file to enable Remoting.graduate degree


The Seam Framework provides built-in JavaScript to enable Seam Remoting. To use this JavaScript, we first need to define it within a Facelets file in the following way:

 <script type="text/javascript" 
 src="/HelloWorld/seam/resource/ remoting/resource/remote.js">
 </script>
 <script type="text/javascript" 
 src="/HelloWorld/seam/resource/ remoting/interface.js?helloWorld">

To include the relevant JavaScript into a Facelets page, we need to import the /seam/resource/remoting/resource/remote.js and /seam/resource/remoting/interface.js JavaScript files.

You can see that the interface.js file takes an argument defining the name of the Seam component that we will be accessing (this is the name of the component for which we have defined methods with the @WebRemote annotation).

If we wish to use two or more different Seam components from a Remoting interface, we would specify their names as parameters to the interface.js file separated by using an "&", for example:

<script type="text/javascript" src="/HelloWorld/seam/resource/ remoting/interface.js?helloWorld&mySecondComponent& myThirdComponent">

To specify that we will use Seam components from the web tier is straight-forward, however, the Seam tag library makes this even easier.

Instead of specifying the JavaScript shown in the preceding examples, we can simply insert the <s:remote /> tag into Facelets, passing the name of the Seam component to use within the include parameter.

 <ui:composition
 xmlns="http://www.w3.org/1999/xhtml"
 xmlns:s="http://jboss.com/products/seam/taglib"
 xmlns:ui="http://java.sun.com/jsf/facelets"
 xmlns:f="http://java.sun.com/jsf/core"
 xmlns:h="http://java.sun.com/jsf/html"
 xmlns:rich="http://richfaces.org/rich"
 template="layout/template.xhtml">
   <ui:define name="body">
   <h1>Hello World</h1>
<s:remote include="helloWorld"/>

To use the <s:remote /> tag, we need to import the Seam tag library, as shown in this example. When the web page is rendered, Seam will automatically generate the relevant JavaScript.


If we are using the <s:remote /> tag and we want to invoke methods on multiple Seam components, we need to place the component names as comma-separated values within the include parameter of the tag instead, for example:</blockquote>
<s:remote include="helloWorld, mySecondComponent, myThirdComponent" />

[edit] Invoking Seam components via Remoting

Now that we have configured our web application, defined the services to be exposed from the server, and imported the JavaScript to perform the AJAX calls, we can execute our remote methods.undergraduate degree


To get an instance of a Seam component within JavaScript, we use the Seam.Component.getInstance() method. This method takes one parameter, which specifies the name of the Seam component that we wish to interact with.

Seam.Component.getInstance("helloWorld")

This method returns a reference to Seam Remoting JavaScript to allow our exposed @WebReference methods to be invoked. When invoking a method via JavaScript, we must specify any arguments to the method (possibly there will be none) and a callback function. The callback function will be invoked asynchronously when the server component's method has finished executing. Within the callback function we can perform any JavaScript processing (such as DOM processing) to give our required AJAX-style functionality.

For example, to execute a simple Hello World client, passing no parameters to the server, we could define the following code within a Facelets file.

  <ui:define name="body">
  <h1>Hello World</h1>
  <s:remote include="helloWorld"/>
   <p>
  <button onclick="javascript:sayHello()">Say Hello</button>
  </p>
  <p>
  <div id="helloResult"></div>
  </p>
  <script type="text/javascript">
  function sayHello() {
  var callback = function(result) {
  document.getElementById("helloResult").innerHTML=result;
  };
  Seam.Component.getInstance("helloWorld").
  sayHello(callback);
  }
  </script>
 </ui:define>

Let's take a look at this code, one piece at a time, to see exactly what is happening.

 <s:remote include="helloWorld"/>
 <p>
 <button onclick="javascript:sayHello()">Say Hello</button>
 </p>

In this part of the code, we have specified that we want to invoke methods on the helloWorld Seam component by using the <s:remote /> tag. We've then declared a button and specified that the sayHello() JavaScript method will be invoked when the button is clicked.

Next we've defined an empty <div /> called helloResult. This <div /> will be populated via the JavaScript DOM API with the results from out server side method invocation.

  <script type="text/javascript">
  function sayHello() {
  var callback = function(result) {
  document.getElementById("helloResult").innerHTML=result;
  };
  Seam.Component.getInstance("helloWorld").
  sayHello(callback);
  }
 </script>

Next, we've defined our JavaScript function sayHello(), which is invoked when the button is clicked. This method declares a callback function that takes one parameter. The JavaScript DOM API uses this parameter to set the contents of the helloResult <div /> that we have defined earlier.

So far, everything that we've done here has been simple JavaScript and hasn't used any Seam APIs. Finally, we invoke the Seam component using the Seam.Component.getInstance().sayHello() method, passing the callback function as the final parameter.

When we open the page, the following flow of events occurs:

1. The page is displayed with appropriate JavaScript created via the <s:remote /> tag.

2. The user clicks on the button.

3. The Seam JavaScript is invoked, which causes the sayHello() method on the helloWorld component to be invoked.

4. The server side component completes execution, causing the JavaScript callback function to be invoked.

5. The JavaScript DOM API uses the results from the server method to change the contents of the <div /> in the browser, without causing the entire page to be refreshed.

This process shows how we've developed some AJAX functionality by writing a minimal amount of JavaScript, but more importantly, by not dealing with XML or the JavaScript XMLHttp class.

The preceding code shows how we can easily invoke server side methods without passing any parameters. This code can easily be expanded to pass parameters, as shown in the following code snippet:

 <s:remote include="helloWorld"/>
 <p>
  <button onclick="javascript:sayHelloWithArgs()">
  Say Hello with Args
  </button>
 </p>
 <p>
  <div id="helloResult"></div>
 </p>
  <script type="text/javascript">
  function sayHelloWithArgs() {
  var name = "David";
  var callback = function(result) {
  document.getElementById("helloResult").innerHTML=result;
  };
  Seam.Component.getInstance("helloWorld").
  sayHelloWithArgs(name, callback);
 }
 </script>

The preceding code shows that the process for invoking remote methods with parameters is similar to the process for invoking remote methods with no parameters. The important point to note is that the callback function is specified as the last parameter.

When our simple application is run, we get the following screenshot.

Clicking on either of the buttons on the page causes our AJAX code to be executed, and the text of the <div /> component to be changed.

If we want to invoke a server side method via Seam Remoting and we want the method to be invoked as a part of a Seam conversation, as described in the previous tutorial, we can use the Seam.Remoting.getcontext.setConversationId() method to set the conversation ID. This ID will then by used by the Seam Framework to ensure that the AJAX request is a part of the appropriate conversation.</blockquote>
Seam.Remoting.getContext().setConversationId(# {conversation.id});


[edit] Debugging Seam Remoting

When writing Seam Remoting applications, it can be useful to see the AJAX conversations that are being carried out between the browser and the server.

Seam enables a debug window that shows all of the Remoting communications to be turned on. Debugging is turned off by default, but can be enabled by editing the WEB-INF/components.xml file.

Debugging can be enabled within this file in two ways:

  • Setting the debug property of the org.jboss.seam.remoting.remoting component to true.
  • Setting the debug property of the remoting:remoting component to true.

[edit] The org.jboss.seam.remoting.remoting component

The simplest way to enable Seam Remoting debugging is to set the debug property to true on the org.jboss.seam.remoting.remoting component. This is achieved by specifying the following code within the WEB-INF/components.xml file.

 <component name="org.jboss.seam.remoting.remoting">
 <property name="debug">true</property>
 </component>
 

However, if this mechanism is used for enabling debugging, the XML within the components.xml cannot be validated fully against the XML schema, because the component name cannot be validated. The following technique allows better control, and helps to ensure that the components.xml file can be validated against its schema.

[edit] The <remoting:remoting> component

Seam Remoting debugging can also be enabled by using the <remoting:remoting> component. To enable debugging, insert the following code into the WEB-INF/components.xml file.

<remoting:remoting debug="true" />

It's evident from this code that the component name can be fully validated against the XML schema, which will help to reduce errors within the configuration.

To use this type of configuration, we must first specify the namespace and schema location for the Seam Remoting component. This is achieved within the <components /> element of the WEB-INF/components.xml file, as shown in the following code snippet.

  <components xmlns="http://jboss.com/products/seam/components"
  xmlns:core="http://jboss.com/products/seam/core"
  xmlns:persistence="http://jboss.com/products/seam/persistence"
  xmlns:drools="http://jboss.com/products/seam/drools"
  xmlns:bpm="http://jboss.com/products/seam/bpm"
  xmlns:security="http://jboss.com/products/seam/security"
  xmlns:mail="http://jboss.com/products/seam/mail"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:remoting="http://jboss.com/products/seam/remoting"
  xsi:schemaLocation=
  "http://jboss.com/products/seam/core
  http://jboss.com/products/seam/core-2.1.xsd
  http://jboss.com/products/seam/persistence
  http://jboss.com/products/seam/persistence-2.1.xsd
  http://jboss.com/products/seam/drools
  http://jboss.com/products/seam/drools-2.1.xsd
  http://jboss.com/products/seam/bpm
  http://jboss.com/products/seam/bpm-2.1.xsd
  http://jboss.com/products/seam/security
  http://jboss.com/products/seam/security-2.1.xsd
  http://jboss.com/products/seam/mail
  http://jboss.com/products/seam/mail-2.1.xsd
  http://jboss.com/products/seam/remoting
  http://jboss.com/products/seam/remoting-2.1.xsd
  http://jboss.com/products/seam/components
  http://jboss.com/products/seam/components-2.1.xsd">

From this XML fragment, we can see that we define the XML namespace remoting as http://jboss.com/products/seam/remoting. We then define the schema location as http://jboss.com/products/seam/remoting-2.1.xsd.

Once debugging is enabled via either of the two methods described earlier, whenever a Remoting method is executed, all of the data that is passed between the server and the web browser is displayed within a popup browser window, as shown in the following screenshot.

For our simple HelloWorld method, let's see what the HTML exchanges between client and server are.

In the request packet, we can see that the sayHelloWithArgs method on the helloWorld component is being invoked, passing the parameter value "David". This is being invoked with a conversation handle of "5".

In the response packet, we can see that the value "Hello David" is returned as the response.

[edit] Source

The source of this content is Chapter 9: Configuring Seam applications for Seam Remoting of Seam 2.x Web Development by David Salter (Packt Publishing, 2009). Affordable web design

[edit] Changing the Please wait message

When Seam Remoting is being performed and the JavaScript in the browser is invoking a server side method, a message is displayed on the upper-right of the browser window, stating Please wait . This text is displayed until the AJAX call is complete, and is intended to show the user that communication is being performed between the browser and the server.online major| accounting degree


The Please wait text can be customized to display any value (message) that is required by setting the Seam.Remoting.loadingMessage property from within client side JavaScript, as shown in the following code sample.

  function sayHello() {
  Seam.Remoting.log("setting the loading message");
  Seam.Remoting.loadingMessage = "Hold on a moment...";
  // .. rest of code removed for brevity.
 }

[edit] Source

The source of this content is Chapter 9: Configuring Seam applications for Seam Remoting of Seam 2.x Web Development by David Salter (Packt Publishing, 2009).

Personal tools