Exadel Flamingo Developer Guide

Exadel Flamingo - Integration Library and Framework for RIA


+1. Introduction
1.1. What is Exadel Flamingo?
1.2. What is Seam?
1.3. What is Spring?
1.4. What is Flex?
1.5. What is JavaFX?
+2. Technical Requirements
2.1. Supported Java Versions
2.2. Supported JBoss Seam Versions
2.3. Supported Adobe Flex Versions
2.4. Supported Spring Framework Versions
2.5. Supported JavaFX Versions
+3. Getting Started with Flamingo
3.1. Downloading and Installing Flamingo 1.8.1
+3.2. Seam
+3.2.1. Server Configuration
3.2.1.1. Copying files
3.2.1.2. Using Seam Remoting
3.2.1.3. Using Servlets
3.2.2. Seam Component Creation
+3.2.3. Flex Client
3.2.3.1. AMF
3.2.3.2. Hessian
+3.2.4. JavaFX Client
3.2.4.1. Hessian
+3.3. Spring
+3.3.1. Server configuration
3.3.1.1. Using Servlets
3.3.2. Spring Service Bean Creation
+3.3.3. Flex Client
3.3.3.1. AMF
3.3.3.2. Hessian
3.3.4. JavaFX Client
+4. Create New Flamingo Project
+4.1. Create New Flamingo Project Using Flex Builder
4.1.1. AMF
4.1.2. Hessian
+4.2. Create New Flamingo Project Using Flamingo Generator Commands
4.2.1. Create a Project
4.2.2. Create Entity
+4.2.3. Create Screen
4.2.3.1. Flamingo Create Screen Example
4.2.4. Generate ActionScript Files from Java Files
+5. Flamingo Components
+5.1. Flex Components
+5.1.1. Validator
+5.1.1.1. EntityValidator
+5.1.1.2. HessianEntityValidator
+5.1.2. CallSet
+5.1.2.1. CallSet
+5.1.2.2. HessianCallSet
+5.1.3. Binding
+5.1.3.1. BindingService
+5.1.3.2. HessianBindingService
+5.1.4. SeamRemoteObject
5.1.4.1. Code Sample
5.1.4.2. Flex Client Components Reference
5.1.4.3. Events
5.1.4.4. Methods
+5.2. JavaFX Components
+5.2.1. Validator
+5.2.1.1. HessianEntityValidator
5.2.2. Binding
5.2.3. ServiceFactory
+5.2.4. SeamServiceFactory
5.2.4.1. Code Sample
5.3. "Hotel Booking" Demo
+6. Flamingo Dynamic Persistent Methods
+6.1. Dynamic Finders
6.1.1. Query by Relationship
6.1.2. Sorting
6.2. Dynamic Updaters
+7. Supported Communication Protocols
+7.1. Hessian 2
7.1.1. Known Issues
+7.2. AMF
7.2.1. AMF-Serializer
+8. Security
+8.1. Authentication
+8.1.1. Flamingo Authentication
+8.1.1.1. Basic Authentication
8.1.1.2. Custom Authentication
+8.2. Authorization
+8.2.1. Seam Authorization
8.2.1.1. Simplified
8.2.1.2. Advanced
8.2.2. Spring Authorization
9. Seam Internationalization
+10. Advanced Topics
10.1. "RemoteObject" Destinations
10.2. "RemoteObject" and "HessianService" Methods/Properties Limitations
10.3. "WebRemote" Configuration
10.4. Enumerated Types
+11. Legal Notes
11.1. License

Chapter 1. Introduction

This chapter contains a high-level introduction to Exadel Flamingo — what it is and what it does.

1.1. What is Exadel Flamingo?

This guide introduces the reader informally to the basic concepts and features of Exadel Flamingo – a powerful software development solution for integrating multiple Rich Internet Applications (RIAs) built on Adobe® Flex™ or JavaFX with JBoss Seam or Spring Framework as premier open source server side technology.

The guide does not attempt to be comprehensive and cover every single feature. Instead, it describes many of Flamingo's most noteworthy features, and gives you a good idea of its flavor and style.

Exadel Flamingo is an integration library and framework for Rich Internet Applications which effortlessly allows you to build Flex or JavaFX based user interfaces for your JBoss Seam/Spring Framework applications. You can think of Flamingo as the glue you need to get these different technologies working together.

In addition to this, Flamingo provides a common Seam/Spring integration layer to RIA technologies using which developers are able to work with Seam remote objects and Spring service beans as well as simple entities on the server side using native RIA approach on the client side. This communication between client and server sides is transparent.

Developers are also able to generate much of the mundane boring code automatically into sensible code patterns. This allows developers who deal with RIA projects to write mostly code related to the logic of the business application rather than struggle with setting up the project and locating all the right patterns.

1.2. What is Seam?

JBoss Seam is a powerful new application framework for building next generation Web 2.0 applications by unifying and integrating technologies such as Asynchronous JavaScript and XML (AJAX), Java Server Faces (JSF), Enterprise Java Beans (EJB3), Java Portlets and Business Process Management (BPM).

Learn more about Seam here.

1.3. What is Spring?

Spring is a lightweight Java/J2EE application framework. It includes powerful JavaBeans-based configuration management applying Inversion-of-Control principles, a generic abstraction layer for transaction management, a JDBC abstraction layer, integration with Hibernate, JDO, Apache OJB, and iBATIS SQL Maps, AOP functionality, and a flexible MVC Web application framework with multiple view technologies.

Learn more about Spring here.

1.4. What is Flex?

Adobe® Flex™ is a complete, powerful application development solution for creating and delivering rich Internet applications within the enterprise and across the web. It enables enterprises to create personalized, multimedia-rich applications that dramatically enhance user experience, revolutionizing the way people interact with the web.

Learn more about Flex here.

1.5. What is JavaFX?

JavaFX is a family of products and technologies from Sun Microsystems. The JavaFX products are intended to be used to create Rich Internet applications. Currently JavaFX consists of JavaFX Script and JavaFX Mobile (an OS for mobile devices), although further JavaFX products are planned.

Learn more about JavaFX here.

Chapter 2. Technical Requirements

Below is a list of the supported software versions necessary to start working with Flamingo.

2.1. Supported Java Versions

  • JDK 1.5 and higher

2.2. Supported JBoss Seam Versions

  • JBoss Seam 2.0.0.GA and higher

2.3. Supported Adobe Flex Versions

2.4. Supported Spring Framework Versions

  • Spring Framework version 2.5 and higher.

2.5. Supported JavaFX Versions

  • JavaFX SDK 1.2

Tip

To build projects by maven you should install JavaFX libraries to your local Maven repository. To do it run mvn-install-javafx.bat (Windows) or mvn-install-javafx (Linux).

  

We assume the list can be incomplete and absence of your environment in the list does not mean incompatibility. We appreciate your feedback on platforms that are not in the list but are compatible with Exadel Flamingo. It helps us to keep the list up-to-date.

Chapter 3. Getting Started with Flamingo

This chapter describes where you can get Exadel Flamingo, how to install it and work with a simple helloworld demo.

3.1. Downloading and Installing Flamingo 1.8.1

The latest release of Flamingo is available for download at:

http://flamingo.exadel.com

Please unzip "flamingo-1.8.1.zip" file to the chosen folder of your existing JBoss Seam application, e.g.: "flamingo-1.8.1". Optionally, you can add <flamingo-1.8.1/bin> directory to the path system variable. It will enable Flamingo commands to run from anywhere. Then run "flamingoinstall" shell script from the "bin" folder.

 

After that select which one of the following client-server techniques is preferable for you or just generate a ready project with the desired configuration using Flamingo Generator Commands as described in Chapter 4: Create New Flamingo Project.

3.2. Seam

Here a necessary sequence of operations to use Exadel Flamingo with JBoss Seam is described. This chapter also describes how to create a simple HelloWorld application using Adobe Flex and JavaFX technologies.

3.2.1. Server Configuration

This section of the guide will discuss necessary server configuration for JBoss Seam.

3.2.1.1. Copying files

Copy files"flamingo-service-1.8.1.jar", "amf-serializer-1.8.1.jar" (for AMF) and/or "hessian-3.1.3.jar"(for Hessian) into the "WEB-INF/lib" folder of your application. For EAR projects file "flamingo-service-1.8.1.jar" should be copied to the EAR root and specified in the "application.xml" file as a module.

Tip

File "hessian-3.1.3.jar" is available at

http://hessian.caucho.com/#Java

Choose one of the following steps, according to the fact you are using Seam Remoting or Servlets.

Seam Remoting is optional. Flamingo can use it if it is enabled, otherwise, Flamingo requires servlet configuration.

3.2.1.2. Using Seam Remoting

If Seam Remoting is used in your project, you don't need any additional configuration and now can call the Seam components directly from Flex 2 using AMF and/or Hessian protocols.

Note:

By default, Seam Remoting only allows calling methods marked with the @WebRemote annotation. Flamingo by default is not dependent on this annotation, and can call any method of any Seam component. If necessary, you can limit Flamingo to only use @WebRemote methods: add the following configuration into the "web.xml" file of your application:

<context-param>
    <param-name>flamingoConfig.webRemoteEnabled</param-name>
    <param-value>true</param-value>
</context-param>

3.2.1.3. Using Servlets

If Seam Remoting is not used in your project:

  • Add the following content into the "web.xml" file of your application if you use AMF:
    <servlet>
        <servlet-name>AMF Remote Servlet</servlet-name>
        <servlet-class>com.exadel.flamingo.service.seam.AMFToSeamServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>AMF Remote Servlet</servlet-name>
        <url-pattern>/flamingo/amf/*</url-pattern>
    </servlet-mapping>

This parameter shows that calls coming to URL "[server_name]/[context]/flamingo/amf/*" will be passed to the com.exadel.flamingo.service.seam.AMFToSeamServlet servlet.

Thus, using URL "/flamingo/amf/" you can call the servlet to access the Seam components via the AMF protocol.

  • OR this content if you use the Hessian protocol:
    <servlet>
        <servlet-name>Hessian Remote Servlet</servlet-name>
        <servlet-class>com.exadel.flamingo.service.seam.HessianToSeamServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Hessian Remote Servlet</servlet-name>
        <url-pattern>/flamingo/hessian/*</url-pattern>
    </servlet-mapping>

This parameter shows that calls coming to URL "[server_name]/[context]/flamingo/hessian/*" will be passed to the com.exadel.flamingo.service.seam.HessianToSeamServlet servlet.

Thus, using URL "/flamingo/hessian/ " you can call the servlet to access the Seam components via the Hessian protocol.

Tip

See also Chapter 6: Supported Communication Protocols to find more information about both Protocols and their configuration.

Note:

If you want to limit calling to the @WebRemote methods only (as designed in Seam Remoting), add the following configuration into the "web.xml" file of your application:

<context-param>
    <param-name>flamingoConfig.webRemoteEnabled</param-name>
    <param-value>true</param-value>
</context-param>

3.2.2. Seam Component Creation

Now we will create a Seam component to implement a simple HelloWorld demo:

  • Add a new file "HelloAction.java" with Seam component helloAction to the existing Seam application:

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
@Scope(ScopeType.STATELESS)
@Name("helloAction")
public class HelloAction {
    public String hello(String name) {
        return "Hello, " + name;
    }
}

The method of this class accepts a string sent from the client as an argument, and it is forwarded then back with string Hello, added at the beginning.

Note

Using Flamingo you can call not only stateless but stateful components as well, and the state will be saved from call to call.

3.2.3. Flex Client

Please add the client source code according to the protocol you use: AMF or Hessian. Fore more information about these protocols and their benefits please see Chapter 6: Supported Communication Protocols.

3.2.3.1. AMF

  • Create file "client.mxml" with the following content:

    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:word="*">
                    
    <mx:RemoteObject id="service" destination="helloAction"/>
                    
    <mx:Panel title="Flamingo AMF Hello World Sample"
    paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
                    
    <mx:HBox>
       <mx:Label text='Whom do you want to say "Hello" to?'/>
                    
        <mx:TextInput id="who"/>
                    
        <mx:Button label="Say Hello" click="service.hello(who.text)"/>
    </mx:HBox>
                    
    <mx:Label text='The server said: "{service.hello.lastResult}"'/>
                    
    </mx:Panel>
    </mx:Application>

    This sample shows how the hello method of server Seam component helloAction can be called using "RemoteObject" when clicking on the "Say Hello" button.

  • Create file "services-config.xml" with the following content:

    <?xml version="1.0" encoding="UTF-8"?>
    <services-config>
    <services>
    <service
       id="hello-service"
       class="flex.messaging.services.RemotingService"
       messageTypes="flex.messaging.messages.RemotingMessage">
        <destination id="helloAction">
          <channels>
            <channel ref="seam-amf"/>
          </channels>
        </destination>
    </service>
    </services>
    <channels>
      <channel-definition id="seam-amf" class="mx.messaging.channels.AMFChannel">
       <endpoint
       uri="http://{server.name}:{server.port}/helloworld/seam/resource/amf"
       class="flex.messaging.endpoints.AMFEndpoint"/>
      </channel-definition>
    </channels>
                    
    </services-config>

    This sample shows that channel seam-amf with a set url to access the server is applied in order to use destination helloAction;

where

"{server.name}:{server.port}" is server name:server port where your existing JBoss Seam application is running;

"helloworld" is the name of your existing application;

"helloAction" is the name of the component specified in the "HelloAction.java" file (see annotation @Name("helloAction") in 3.3.1);

"seam/resource/amf/" is the standard configuration while using Remoting. If you use another mapping for SeamResourceServlet or one of the Flamingo servlets, use the path specified in the "web.xml" file of your application for destination:

Example 3.1. 

uri="http://{server.name}:{server.port}/helloworld/flamingo/amf"


  • Compile an .swf file using parameter "mxmlc -output client.swf -compiler.services services-config.xml client.mxml" in the command line.

Note

Make sure, that the version of Flex2 compiler you use is not earlier than 2.0.1 Hotfix2: run "mxmlc -version" in the command line and verify that the build number is equal or higher than 166910.

  • Deploy your "client.swf" file into your server application.

  • Type in your browser the url to the .swf file: "http://localhost:8080/helloworld/client.swf"

  • Enjoy the results!

HelloWorld.swf

Figure 3.1. HelloWorld.swf


3.2.3.2. Hessian

  • Create file "client.mxml" with the following content:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:word="*">
            
<hessian:HessianService xmlns:hessian="hessian.mxml.*"
id="service" destination="seam/resource/hessian/helloAction"/>
            
<mx:Panel title="Flamingo Hessian Hello World Sample"
paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
            
<mx:HBox>
   <mx:Label text='Whom do you want to say "Hello" to?'/>
            
   <mx:TextInput id="who"/>
            
   <mx:Button label="Say Hello" click="service.hello.send(who.text)"/>
</mx:HBox>
            
<mx:Label text='The server said: "{service.hello.lastResult}"'/>
            
</mx:Panel>
</mx:Application>

This sample shows how the hello method of server Seam component helloAction can be called using HessianService when clicking on the "Say Hello" button,

where

"helloAction" is the name of the component specified in the "HelloAction.java" file (see annotation @Name("helloAction") in 3.3.1);

"seam/resource/hessian/" is the standard configuration while using Remoting. Please note that the URL is relative, so the application will contact http://[origin server]/[application context]/[path to Seam/Flamingo servlet]/helloAction as a service. If you use another mapping for SeamResourceServlet or one of the Flamingo servlets, use the path specified in the "web.xml" file of your application in the URL pattern:

Example 3.2. 

destination="flamingo/hessian/helloAction"


  • Compile an .swf file using parameter "mxmlc -output client.swf -library-path+=hessian-flash-3.1.2.swc client.mxml" in the command line.

Note

  • Make sure, that the version of Flex2 compiler you use is not earlier than 2.0.1 Hotfix2: run "mxmlc -version" in the command line and verify that the build number is equal or higher than 166910.

  • File "hessian-flash-3.1.2.swc" is available at

    http://hessian.caucho.com/#Flash/Flex.

  • Deploy your "client.swf" file into your server application.

  • Type in your browser the url to the .swf file: "http://localhost:8080/helloworld/client.swf".

  • Enjoy the results!
HelloWorld.swf

Figure 3.2. HelloWorld.swf


3.2.4. JavaFX Client

In this release only one method of communication between JavaFX client application and JBoss Seam is supported: via the Hessian protocol. Fore more information about this protocol and its benefits please see Chapter 6: Supported Communication Protocols

3.2.4.1. Hessian

  • Create the following structure of the working directory:

- classes

- lib

- src

  • Put libraries "hessian-3.1.3.jar", "jboss-seam.jar", "jboss-seam-remoting.jar", "javafxrt.jar", "javafxgui.jar" and "javafx-swing.jar" into the lib directory.

Note

"javafxrt.jar", "javafxgui.jar" and "javafx-swing.jar" can be copied from JavaFX SDK lib directory; "jboss-seam.jar" and "jboss-seam-remoting.jar" can be copied from Seam runtime lib directory.

File "hessian-3.1.3.jar" can be downloaded via this link: hessian.caucho.com/download/hessian-3.1.3.jar.

  • Create file "FXClient.fx" with the following content:

package com.exadel.flamingo.javafx;
          
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.TextOrigin;
import javafx.ext.swing.SwingButton;
import javafx.scene.layout.VBox;
import javafx.scene.control.TextBox;
          
import com.exadel.flamingo.javafx.samples.helloworld.javafx.HelloworldClient;
          
class Hello {
        public var name:String;
        public var str:String;
}
var helloModel = new Hello();
          
HelloworldClient.setServerUrl("http://localhost:8080/helloworld/seam/resource/hessian/helloAction");
          
          
var helloText: TextBox = TextBox {
       text: bind helloModel.name with inverse
       columns: 7
       selectOnFocus:true
}
          
var helloLabel = Text{
      y:8
      font: Font { name:"sansserif", size: 12 }
      fill: Color.BLACK
      content: bind "Server says: {helloModel.str}"
      textOrigin: TextOrigin.TOP
}
          
var helloButton = SwingButton  {
      text:"Say Hello!"
      action: function(){
             helloModel.str = HelloworldClient.CLIENT.hello(helloModel.name);
       }
}
          
Stage {
        title: "Helloworld Sample"
        width: 200
        height: 150
        scene: Scene {
                 content: VBox {
                         translateX: 5
                         translateY: 5
                         spacing: 10
                         content: [                
                                 HBox {
                                            content: helloText
                                            spacing: 10
                                 },
                                 HBox {
                                            content: helloButton
                                            spacing: 10
                             },
                                 HBox {
                                            content: helloLabel
                                            spacing: 10
                           }]
                 }
         }
}
        

This file creates a visual form to send data from the client side to the server,

where

"helloAction" is the name of the component specified in the "HelloAction.java" file created for the Seam application (see annotation @Name("helloAction") in 3.3.1);

"http://localhost:8080/helloworld/seam/resource/hessian/" is the standard configuration while using Remoting. Please note that the URL is relative, so the application will contact http://[origin server]/[application context]/[path to Seam/Flamingo servlet]/helloAction as a service. If you use another mapping for SeamResourceServlet or one of the Flamingo servlets, use the path specified in the "web.xml" file of your application in the URL pattern:

Example 3.3. 

destination="flamingo/hessian/helloAction"


  • Create interface “IHelloAction.java” for the helloAction Seam component:

package com.exadel.flamingo.javafx.samples;
public interface IHelloAction {
    public String hello(String name);
}

Note

The interface should contain all methods that can be called by the client on the server and their cignatures should be 100% identical.

  • Create file "HelloworldClient.java":

package com.exadel.flamingo.javafx.samples.javafx;
import com.caucho.hessian.client.HessianProxyFactory;
import com.exadel.flamingo.javafx.samples.IHelloAction;
import java.net.MalformedURLException;
public class HelloworldClient {
    public static HelloworldClient CLIENT;
    
    private String _url;
    private HelloworldClient(String string) {
        _url = string;
    }
    private IHelloAction _service;
    public static void setServerUrl(String url) {
        CLIENT = new HelloworldClient(url);
    }
    private IHelloAction getService() {
        if (_service == null) {
            try {
                HessianProxyFactory factory = new HessianProxyFactory();
                _service = (IHelloAction) factory.create(IHelloAction.class, _url);
            } catch (MalformedURLException ex) {
                System.out.println(ex);
            }
        }
        return _service;
    }
    public String hello(String s) {
        return getService().hello(s);
    }
}

This sample shows how the HelloworldClient class creates a connection with the server with the help of the HessianProxyFactory class and calls the corresponding methods of the component on the server.

 

Here is an example of usage of the JavaFX interpretator:

  • Compile java classes using the following parameter in the command line:

    javac -sourcepath src -classpath lib/hessian-3.1.3.jar;lib/jboss-seam.GA.jar;
    lib/jboss-seam.jar src/com/exadel/flamingo/javafx/samples/javafx/
    HelloworldClient.java -d classes
    
  • Compile javafx classes using the following parameter in the command line:

    javafxc -cp classes src/com/exadel/flamingo/javafx/MainFrame.fx -d classes
  • Create a jar file using the following parameter in the command line:

    jar cvf lib/HelloworldJFX.jar -C classes com
  • Run the application using the following parameter:

    javafx -cp lib/HelloworldJFX.jar:lib/hessian-3.1.3.jar:lib/javafx-swing.jar:
    lib/javafxgui.jar:lib/javafxrt.jar:lib/jboss-seam.jar:lib/jboss-seam-remoting.jar com.exadel.flamingo.javafx.MainFrame
    

Note

Change ":" to ";" if using Microsoft® Windows.

  • Enjoy the results!

HelloWorld

Figure 3.3. HelloWorld


3.3. Spring

Here a necessary sequence of operations to use Exadel Flamingo with Spring is described. This chapter also describes how to create a simple HelloWord application using Adobe Flex and JavaFX technologies.

3.3.1. Server configuration

This section of the guide will discuss necessary server configuration for Spring.

3.3.1.1. Using Servlets

  • Copy files "flamingo-service-spring-1.8.1.jar", "amf-serializer-1.8.1.jar" (for AMF) and/or "hessian-3.1.3.jar"(for Hessian) into the "WEB-INF/lib" folder of your application.

Tip

File "hessian-3.1.3.jar" is available at

http://hessian.caucho.com/#Java

  • Add the following content into the "web.xml" file of your application if you use AMF:
    <servlet>
        <servlet-name>AMF Remote Servlet</servlet-name>
        <servlet-class>com.exadel.flamingo.service.spring.AMFToSpringServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>AMF Remote Servlet</servlet-name>
        <url-pattern>/flamingo/amf/*</url-pattern>
    </servlet-mapping>

This parameter shows that calls coming to URL "[server_name]/[context]/flamingo/amf/*" will be passed to the com.exadel.flamingo.service.spring.AMFToSpringServlet servlet.

Thus, using URL "/flamingo/amf/" you can call the servlet to access the Spring beans via the AMF protocol.

  • OR this content if you use the Hessian protocol:
    <servlet>
        <servlet-name>Hessian Remote Servlet</servlet-name>
        <servlet-class>com.exadel.flamingo.service.spring.HessianToSpringServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Hessian Remote Servlet</servlet-name>
        <url-pattern>/flamingo/hessian/*</url-pattern>
    </servlet-mapping>

This parameter shows that calls coming to URL "[server_name]/[context]/flamingo/hessian/*" will be passed to the com.exadel.flamingo.service.spring.HessianToSpringServlet servlet.

Thus, using URL "/flamingo/hessian/ " you can call the servlet to access the Seam components via the Hessian protocol.

Tip

See also Chapter 6: Supported Communication Protocols to find more information about both Protocols and their configuration.

3.3.2. Spring Service Bean Creation

Now we will create a Spring bean to implement a simple HelloWorld demo:

Tip

If you want to create a new application from scratch see Chapter 4: Create New Flamingo Project for more details.

  • Add a new file "HelloService.java" to the existing Spring application:

package com.flamingo.sample;
public class HelloService {
    public String hello(String name) {
        return "Hello, " + name;
    }
}

The method of this class accepts a string sent from the client as an argument, and it is forwarded then back with string Hello, added at the beginning.

 

  • Add bean definition to application context file:

<beans>
<bean id="helloService" class="com.flamingo.sample.HelloService"/>
</beans>

Note

Using Flamingo you can call not only singleton beans but stateful beans as with the session scope.

3.3.3. Flex Client

Please add the client source code according to the protocol you use: AMF or Hessian. Fore more information about these protocols and their benefits please see Chapter 6: Supported Communication Protocols.

3.3.3.1. AMF

  • Create file "client.mxml" with the following content:

    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:word="*">
                  
    <mx:RemoteObject id="service" destination="helloService"/>
                  
    <mx:Panel title="Flamingo AMF Spring Hello World Sample"
    paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
                  
    <mx:HBox>
       <mx:Label text='Whom do you want to say "Hello" to?'/>
                  
       <mx:TextInput id="who"/>
                  
       <mx:Button label="Say Hello" click="service.hello(who.text)"/>
    </mx:HBox>
                  
    <mx:Label text='The server said: "{service.hello.lastResult}"'/>
                  
    </mx:Panel>
    </mx:Application>

    This sample shows how the hello method of server Spring bean helloService can be called using "RemoteObject" when clicking on the "Say Hello" button.

  • Create file "services-config.xml" with the following content:

    <?xml version="1.0" encoding="UTF-8"?>
    <services-config>
    <services>
    <service
       id="hello-service"
       class="flex.messaging.services.RemotingService"
       messageTypes="flex.messaging.messages.RemotingMessage">
       <destination id="helloService">
          <channels>
             <channel ref="spring-amf"/>
             </channels>
         </destination>
      </service>
    </services>
    <channels>
       <channel-definition id="spring-amf" class="mx.messaging.channels.AMFChannel">
       <endpoint
       uri="http://{server.name}:{server.port}/helloworld/flamingo/amf"
       class="flex.messaging.endpoints.AMFEndpoint"/>
       </channel-definition>
    </channels>
                  
    </services-config>

    This sample shows that channel spring-amf with a set url to access the server is applied in order to use destination helloService;

where

"{server.name}:{server.port}" is server name:server port where your existing JBoss Seam application is running;

"helloworld" is the name of your existing application;

"helloService" is the name of the bean specified in the application context file or via annotation like @Component(“helloService”) added to the HelloService class;

"flamingo/amf/" is the standard configuration while using servlets. If you use another mapping for HessianToSpringServlet, use the path specified in the "web.xml" file of your application for destination.

  • Compile an .swf file using parameter "mxmlc -output client.swf -compiler.services services-config.xml client.mxml" in the command line.

Note

Make sure, that the version of Flex2 compiler you use is not earlier than 2.0.1 Hotfix2: run "mxmlc -version" in the command line and verify that the build number is equal or higher than 166910.

  • Deploy your "client.swf" file into your server application.

  • Type in your browser the url to the .swf file: "http://localhost:8080/helloworld/client.swf"

  • Enjoy the results!

HelloWorld.swf

Figure 3.4. HelloWorld.swf


3.3.3.2. Hessian

  • Create file "client.mxml" with the following content:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:word="*">
          
<hessian:HessianService xmlns:hessian="hessian.mxml.*"
id="service" destination="flamingo/hessian/helloService"/>
          
<mx:Panel title="Flamingo Spring Hessian Hello World Sample"
paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10">
          
<mx:HBox>
   <mx:Label text='Whom do you want to say "Hello" to?'/>
          
   <mx:TextInput id="who"/>
          
   <mx:Button label="Say Hello" click="service.hello.send(who.text)"/>
</mx:HBox>
          
<mx:Label text='The server said: "{service.hello.lastResult}"'/>
          
</mx:Panel>
</mx:Application>

This sample shows how the hello method of server Spring service bean helloService can be called using "HessianService" when clicking on the "Say Hello" button,

where

"helloService" is the name of the component specified in the application context file;

"flamingo/hessian/" is the standard servlet configuration. Please note that the URL is relative, so the application will contact http://[origin server]/[application context]/[path to Spring/Flamingo servlet]/helloService as a service. If you use another mapping for HessianToSpringServlet use the path specified in the "web.xml" file of your application in the URL pattern.

  • Compile an .swf file using parameter "mxmlc -output client.swf -library-path+=hessian-flash-3.1.2.swc client.mxml" in the command line.

Note

  • Make sure, that the version of Flex2 compiler you use is not earlier than 2.0.1 Hotfix2: run "mxmlc -version" in the command line and verify that the build number is equal or higher than 166910.

  • File "hessian-flash-3.1.2.swc" is available at

    http://hessian.caucho.com/#Flash/Flex.

  • Deploy your "client.swf" file into your server application.

  • Type in your browser the url to the .swf file: "http://localhost:8080/helloworld/client.swf".

  • Enjoy the results!
HelloWorld.swf

Figure 3.5. HelloWorld.swf


3.3.4. JavaFX Client

In this release only one method of communication between JavaFX client application and Spring is supported: via the Hessian protocol. Fore more information about this protocol and its benefits please see Chapter 6: Supported Communication Protocols.

Example of creation of a simple HelloWorld demo on JavaFX on Spring is similar to the one described for JavaFX/Seam. Just use helloService Spring Service bean instead of helloAction Seam component on the client side and change the corresponding URL. A working example can be found in the Samples folder of the Exadel Flamingo bundle.

Chapter 4. Create New Flamingo Project

You can create a new Flamingo project in two ways: using Adobe Flex Builder or Maven FlamingoApp Generator Plugin.

4.1. Create New Flamingo Project Using Flex Builder

Flamingo supports the following versions of Adobe Flex Builder: Adobe® Flex™ Builder™ 2.0.1 HotFix 2 and higher.

Follow the instructions how to create a new sample project with the help of Adobe Flex Builder below. This sample application will use Flamingo EntityValidator component to validate text entered by user against Hibernate Validator annotations specified in the entity declaration (see more information and code samples in the Flamingo Components Chapter: EntityValidator):

  • Run Adobe Flex Builder. Create a new Project: File > New > Flex Project:

Create New Project

Figure 4.1. Create New Project


  • Select Project Type: select "Basic (e.g. XML or web service from PHP/JSP/ASP.NET )". Click Next.

Select Project Type

Figure 4.2. Select Project Type


  • Specify a name for your project: e.g. "validation". Browse a destination folder where your project will be located. Click Next.

Project Name and Location

Figure 4.3. Project Name and Location


  • Set the build paths for the new Flex project: Library path > Add SWC:

Add SWC

Figure 4.4. Add SWC


  • Browse the "flamingo-flex-1.8.1.swc" file and click OK:

Browse SWC

Figure 4.5. Browse SWC


  • The .swc file is now added. Fields "Main Application File" and "Output Folder" are predefined by the system. Click on Finish.

Finish Project Creation

Figure 4.6. Finish Project Creation


Your new Flex Project is now created!

  

To have this project working you need a running Seam or Spring web application with integrated Flamingo via URL "http://localhost:8080/validation/" with the entity named Person; see example in chapter 5.1.1.1.3 Code Sample. You can use the corresponding "validation" example in the Flamingo download bundle.

  

Please add implementation according to the protocol you use: AMF or Hessian.

4.1.1. AMF

  • Enter the following content into file "validation.mxml" that uses the EntityValidator component to validate the lastName property, entered in the first editbox, for the Person entity specified as destination property in EntityValidator:

    <?xml version="1.0" encoding="utf-8"?>
    <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
        xmlns:flamingo="com.exadel.flamingo.flex.components.flamingo.*">
        
        <flamingo:EntityValidator id="validator" 
            destination="Person" 
            validationTarget="{target.text}" 
            source="{test}" 
            property="text" 
            required="false"/>
            
        <mx:Form width="100%" >
            <mx:FormItem label="Validation target:" width="100%" >
                <mx:TextInput id="target" width="100%" text="lastName" />
            </mx:FormItem>
            <mx:FormItem label="Input value:" width="100%" >
                <mx:TextInput id="test" width="100%" />
            </mx:FormItem>
            <mx:FormItem>
                <mx:Button label="Validate" click="validator.validate()" />
            </mx:FormItem>
        </mx:Form>
        
    </mx:Application>
  • Create file "services-config.xml" with the following content to configure destination that EntityValidator component uses:

    <?xml version="1.0" encoding="UTF-8"?>
    <services-config>
        <services>
            <service
                id="validate-service"
                class="flex.messaging.services.RemotingService"
                messageTypes="flex.messaging.messages.RemotingMessage">
                <destination id="Person"/>
                <default-channels>
                    <channel ref="default-amf"/>
                </default-channels>
            </service>      
        </services>
        <channels>
            <channel-definition id="default-amf" class="mx.messaging.channels.AMFChannel">
                <endpoint
                    uri="http://localhost:8080/validation/seam/resource/amf"
                    class="flex.messaging.endpoints.AMFEndpoint"/>
            </channel-definition>  
        </channels>
    </services-config>

Note

For Spring change uri in the channel definition to http://localhost:8080/validation/flamingo/amf.

  • Configure the project: click on the "validation.mxml" file > Properties > Flex compiler.

Configuration

Figure 4.7. Configuration


  • Enter additional compiler arguments: "-services "services-config.xml"" to take into consideration the settings of destination set in the "services-config.xml" file:

Flex Compiler

Figure 4.8. Flex Compiler


  • Click on the Run button to run the project:

Run the Project

Figure 4.9. Run the Project


  • Type in your browser the url to the .swf file: "http://localhost:8080/validation/validation.swf"
  • Enjoy the results!
Validation.swf

Figure 4.10. Validation.swf


4.1.2. Hessian

  • Create file "validation.mxml" with the following content to use component HessianEntityValidator to validate the lastName property for the person entity:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" 
    xmlns:flamingo="com.exadel.flamingo.flex.components.flamingo.*">
    
    <flamingo:HessianEntityValidator id="validator" 
        destination="{destination.text}" 
        validationTarget="{target.text}" 
        source="{test}" 
        property="text" 
        required="false"/>
        
    <mx:Form width="100%" >
        <mx:FormItem label="Destination:" width="100%" >
            <mx:TextInput id="destination" width="100%"  text="http://localhost:8080/validation/seam/resource/hessian/Person" />
        </mx:FormItem>
        <mx:FormItem label="Validation target:" width="100%" >
            <mx:TextInput id="target" width="100%" text="lastName" />
        </mx:FormItem>
        <mx:FormItem label="Input value:" width="100%" >
            <mx:TextInput id="test" width="100%" />
        </mx:FormItem>
        <mx:FormItem>
            <mx:Button label="Validate" click="validator.validate()" />
        </mx:FormItem>
    </mx:Form>
    
</mx:Application>    
    

Note

For Spring change the value of text in TextInput with id="destination" to "http://localhost:8080/validation/flamingo/hessian/Person".

  • Click on the Run button to run the project:

Run the Project

Figure 4.11. Run the Project


  • Type in your browser the url to the .swf file: "http://localhost:8080/validation/validation.swf"
  • Enjoy the results!
Validation.swf

Figure 4.12. Validation.swf


4.2. Create New Flamingo Project Using Flamingo Generator Commands

To run Maven Flamingo Generator Commands you need to have Maven 2 installed. Make sure you have started the "flamingoinstall" shell script as described in Chapter 3: Section 3.1, “Downloading and Installing Flamingo 1.8.1”.

Flamingo provides you with the following commands to generate a project or some of its parts:

  • flamingo create project

  • flamingo create entity

  • flamingo create screen

  • flamingo generate beans

  • flamingo help

There is a "templates" folder inside "bin" that contains templates written on Groovy for commands create screen, create entity, generate beans used for files generation. You can modify these templates according to your needs and then run generation. For example, it may be useful to apply own design of generated Flex screens or implement necessary copyright header for all generated files of the project, etc.

Tip

If you want to see a detailed log of the generation process add "-v" to the command used, this option turns the verbose mode on, e.g.: flamingo create entity -v

4.2.1. Create a Project

  • Run Command Line and enter the "flamingo create project" command from any folder you are in;

  • Select the necessary application type when question "Please choose the type of application to generate (flamingo-seam, flamingo-spring)[flamingo-seam]" appears (options mentioned in the square brackets are the default ones taken from the "FlamingoSDK.properties" file, they will be used when you simply press the Enter button);

  • Then answer the questions appearing according to the previous choice :

Table 4.1. Seam Configuration

QuestionAnswer Description
Please enter the location in which your new application will be created (i.e. c:/java/development): Specify path to the location where the folder with the project will be created.
Enter the project name (e.g. myproject): [myproject] Project name will be used when creating a target file: .war or .ear.
Please enter the root package name for your project (e.g. com.mydomain.myproject): [com.sample] The name specified will be used as a package name for the source files.
Is this project deployed as an EAR (with EJB components) or a WAR (with no EJB support)? (ear, war): [ear] Select whether you want to create an Enterprise Archive file (EAR) and use EJB support or a simple Web Archive file (WAR). If you select WAR, the database sample code will not be suggested to be created.
Will this project have Flex or JavaFX user interface? (flex, javafx): [flex]Select a required technology for the client side.
Will this project use Hessian or AMF protocol? (amf, hessian): [amf]This question will appear only if Flex is selected for the required interface. According to a user's choice, a dependency will be configured: "amf-serializer-1.8.1.jar" or "hessian-3.1.3.jar", and the client source files will be generated.
Will this project use Seam Remoting or Flamingo servlets? (servlets, remoting, both): [servlets] If you select Seam Remoting, the SeamResource servlet will be configured with a standard path in the "web.xml" file. If you select Flamingo servlet, either AMF Remote servlet or Hessian Remote servlet (depends on your previous answer) will be configured in the "web.xml" file.
What kind of database are you using? (hsql, mysql, oracle, postgres, mssql, db2, sybase, none): [hsql] This one and all further questions will appear only if you selected EAR deployment for your project. If one of the database types is selected, the corresponding Hibernate dialect and JDBC driver are automatically defined for it. If "none" is specified, the wizard will stop and no sample database code will be generated.
Enter the JDBC URL for your database (e.g. jdbc:hsqldb:.): [jdbc:hsqldb:.]Please configure JDBC URL for your existing database. If you use not a "hsql" database, copy the "jar" file with the jdbc driver into the folder included into the server classpath application, e.g.: for JBoss - "jboss/server/default/lib".
Enter database username: [sa]Specify the username to perform connection to the database.
Enter database password: []Specify the password to perform connection to the database. Type "NOPASSWORD" to reset the value to an empty password. If the Enter button is clicked the system will use the password value specified for the previous project.
Do you want to update the database schema each time you deploy? (y, n): [y]If yes, Hibernate will update the database schema each time when your project is deployed. If no, only validation of the database schema and entity model will be performed.
Enter the entity class name (Flex source files to view and modify entities will be generated as well): [Person] Specify the entity class name to generate sample source code to view and edit entities of this class. Sample code will be generated on the server and client side.

 

Table 4.2. Spring Configuration

QuestionAnswer Description
Please enter the location in which your new application will be created (i.e. c:/java/development): Specify path to the location where the folder with the project will be created.
Enter the project name (e.g. myproject): [myproject] Project name will be used when creating a target file: .war or .ear.
Please enter the root package name for your project (e.g. com.mydomain.myproject): [com.sample] The name specified will be used as a package name for the source files.
Will this project have Flex or JavaFX user interface? (flex, javafx): [flex]This question will appear only if Flex is selected for the required interface. Select a required technology for the client side.
Will this project use Hessian or AMF protocol? (amf, hessian): [amf]According to a user's choice, a dependency will be configured: "amf-serializer-1.8.1.jar" or "hessian-3.1.3.jar", and the client source files will be generated.
What kind of database are you using? (hsql, mysql, oracle, postgres, mssql, db2, sybase, none): [hsql] If one of the database types is selected, the corresponding Hibernate dialect and JDBC driver are automatically defined for it. If "none" is specified, the wizard will stop and no sample database code will be generated.
Enter the JDBC URL for your database (e.g. jdbc:hsqldb:.): [jdbc:hsqldb:.]Please configure JDBC URL for your existing database. If you use not a "hsql" database, copy the "jar" file with the jdbc driver into the folder included into the server classpath application, e.g.: for JBoss - "jboss/server/default/lib".
Enter database username: [sa]Specify the username to perform connection to the database.
Enter database password: []Specify the password to perform connection to the database. Type "NOPASSWORD" to reset the value to an empty password. If the Enter button is clicked the system will use the password value specified for the previous project.
Do you want to update the database schema each time you deploy? (y, n): [y]If yes, Hibernate will update the database schema each time when your project is deployed. If no, only validation of the database schema and entity model will be performed.
Enter the entity class name (Flex source files to view and modify entities will be generated as well): [Person] Specify the entity class name to generate sample source code to view and edit entities of this class. Sample code will be generated on the server and client side.

  • Navigate to the target directory and examine the artifacts built. Application modules structure is described in the “readme.txt” file. To build entire project, type "mvn package" in the command line.

Note

Generated JavaFX project requires file "javafxrt.jar" to be built. Download this file as described in 3.2.4.1, and install into the local Maven repository using command

mvn install:install-file -Dfile=javafxrt.jar -DgroupId=net.java.dev.openjfx 
      -DartifactId=javafxrt -Dversion=1.0-SNAPSHOT -Dpackaging=jar 
      -DgeneratePom=true

4.2.2. Create Entity

In order to create an entity follow these steps:

  • Go to the root folder of the generated project: (e.g. c:/java/development/myproject);

  • Run Command Line and enter the "flamingo create entity" command;

  • Enter a new entity name.

Table 4.3. Create Entity

QuestionAnswer Description
Please enter entity class nameEnter a name for the entity class, e.g.: Book
Would you like to create JUnit test for a new entity? (yes, no) [yes]This option allows user to create a JUnit test with all necessary service classes for different entities depended on Seam/Spring kind of the project.

Tip

For new projects no default values will be offered. Type an option suggested in brackets or specify the defaults manually in the "flamingoproject.properties" file.

4.2.3. Create Screen

Command create screen is used to generate .mxml source files of CRUD (create, read, update, delete) screens for existing entities. In order to create a screen follow these steps:

  • Go to the root folder of the generated project: (e.g. c:/java/development/myproject);

  • Run Command Line and enter the "flamingo create screen" command;

In the result a screen with a form to edit entity and a screen listing entities of application data saved in the database will be generated. See a sample below.

During the create screen operation ActionScript files are generated automatically, so there is no need in additional running of the generate beans command.

Tip

For new projects no default values will be offered. Type an option suggested in brackets or specify the defaults manually in the "flamingoproject.properties" file.

4.2.3.1. Flamingo Create Screen Example

For the entities like these ones:

@Entity
public class Person implements Serializable {
    private Long id;
    private Integer version;
    private String name;
    private Set<Book> books;
    @OneToMany(mappedBy = "person", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    public Set<Book> getBooks() {
        return books;
    }
    public void setBooks(Set<Book> books) {
        this.books = books;
    }
    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    @Version
    public Integer getVersion() {
        return version;
    }
    public void setVersion(Integer version) {
        this.version = version;
    }
    @Length(max = 20)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 

@Entity
public class Book implements Serializable {
    private Long id;
    private String name;
    protected Person person;
    @ManyToOne(optional=false, cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @NotNull
    public Person getPerson() {
        return person;
    }
    public void setPerson(Person person) {
        this.person = person;
    }
    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    @Length(max = 20)
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

 

you will have the following application after screens generation:

Person List Screen

Figure 4.13. Person List Screen


Person Form Screen

Figure 4.14. Person Form Screen


Book Form Screen

Figure 4.15. Book Form Screen


4.2.4. Generate ActionScript Files from Java Files

Command flamingo generate beans generates AS files for java classes. In order to generate the files follow these steps:

  • Go to the root folder of the generated project: (e.g. c:/java/development/myproject);

  • Run Command Line and enter the "flamingo generate beans" command;

  • The system automatically determines whether you have Seam or Spring project. Answer the following questions for a Spring/Flex project:

Table 4.4. Generate Beans for Spring/Flex project

QuestionAnswer Description
Enter the related path to the .java files (starts with web/src/main/java/) [root_package_name]root_package_name is the package name for the source files specified when creating a project (e.g. com.sample).
Enter the name of existed entity file to generate .as files [all][all] generates .as files for all entities in the specified folder.

  • If some beans had already been created before the system will propose you to override them, you will be able to override them one by one, all beans at once or not to override them at all.

  • The following questions will appear for a Seam/Flex project:

Table 4.5. Generate Beans for Seam/Flex project

QuestionAnswer Description
Enter the related path to the .java files (starts with ejb/src/main/java/) [root_package_name]root_package_name is the package name for the source files specified when creating a project (e.g. com.sample).
Enter the name of existed entity file to generate .as files [all]Enter a name for the existing entity file to generate the files, e.g.: if you enter Person the flex/src/main/flex/com/sample/vo/Person.as bean will be generated for entity ejb/src/main/java/com/sample/Person.java entity.

Tip

For new projects no default values will be offered. Type an option suggested in brackets or specify the defaults manually in the "flamingoproject.properties" file.

Chapter 5. Flamingo Components

Flamingo has 4 client Flex components designed for native integration with Seam and Spring: Validator, CallSet, Binding and SeamRemoteObject, and 3 client JavaFX components: Validator, ServiceFactory and SeamServiceFactory. Three of Flex components are implemented to be used either with AMF or Hessian protocol and thus, have the following versions:

  • Validator: EntityValidator and HessianEntityValidator

  • CallSet: CallSet and HessianCallSet

  • Binding: BindingService and HessianBindingService

  • SeamRemoteObject supports Seam conversations in Flex applications and has only one version that can be used only for AMF at the moment.

 

JavaFX components are implemented to be used with the Hessian protocol only:

  • Validator: EntityValidator

  • ServiceFactory

  • SeamServiceFactory

Table 5.1. 

FlexJBoss SeamSpring
Validatoryesyes
CallSetyesyes
Bindingyesyes
SeamRemoteObjectyesn/a
JavaFX
EntityValidatoryesyes
CallSetplannedplanned
Bindingyesplanned
ServiceFactoryyesyes
SeamServiceFactoryyesn/a

See more about each component in the appropriate section.

5.1. Flex Components

In this chapter 4 client Flex components are described.

5.1.1. Validator

This component allows validating user input against Hibernate Validator annotations on the server. It is used in Flex applications which use Seam or Spring server configuration. There are 2 choices of the component, one for each of two protocols: EntityValidator for AMF and HessianEntityValidator for Hessian. The functionality is very similar to the <s:validate> Seam tag (see Seam Reference).

5.1.1.1. EntityValidator

This component uses the AMF protocol. It replaces the former SeamValidator starting from deprecated version 1.0.2.

5.1.1.1.1. Flex Client Components Reference

Here the properties and methods used by EntityValidator are described.

5.1.1.1.1.1. Properties

EntityValidator, used for the AMF protocol, contains 2 distinctive properties and a set of typical Flex validator properties:

Table 5.2. 

ElementRequiredDescription
idNoThe id of the component. It is specified only if creating the component in the .mxml file
destinationYesFlamingo distinctive property. This can be: a) full qualified class name of entity that contains a method annotated b) name of entity specified in the @Entity annotation, or simple class name if entity name is omitted c) name of the Seam component if specified for entity. In the example provided in the Sample Code section, valid values are person, Person and com.mycompany.myproject.PersonBean. For AMF, you need to add this destination to the "services-config.xml" file
validationTargetYesFlamingo distinctive property. This is a property name of the Seam component or entity class you want to validate
sourceYesSpecifies the Flex client object containing the property to validate.
propertyYesA String specifying the name of the property of the source object that contains the value to validate
requiredNoIf true, specifies that a missing or empty value causes a validation error. If false, no validation server call will be executed for the empty value. The default value of the parameter is false

5.1.1.1.1.2. Methods

EntityValidator has only one method which is inherited from a standard Flex Validator component: "validate". This method executes a call to the server and returns a validation error message if there is any.

5.1.1.1.2. Flex Server Components Reference

Seam or Spring component named com.exadel.flamingo.service.validator.entityValidator is used on the server side to manage validation processing. See Java documentation for class com.exadel.flamingo.service.validator.EntityValidatorImpl for more information.

Note

To have Validator working for the Spring application add the following line into your Spring context file:

<context:component-scan base-package="com.exadel.flamingo.service"/>
5.1.1.1.3. Code Sample

See a sample below:

  • To see validation in action you need to add a Person.java file on the server with the following content:

package com.mycompany.myproject;
import org.hibernate.validator.Length;
import org.jboss.seam.annotations.Name;
import javax.persistence.Entity;
@Name("person")
@Entity(name="Person")
public class PersonBean {
    private String lastName; 
    @Length(min=3, max=40)
    public String getLastName() {
        return lastName;
    }
}
  • Use this EntityValidator code sample in your .mxml file:

<flamingo:EntityValidator id="validator"
  destination="person"
  source="{valueId}"
  validationTarget="lastName"
  property="text" />
<mx:Form>
    <mx:TextInput id="valueId" />
    <mx:Button label="Validate" click="validator.validate()" />
</mx:Form>

In this example when the "Validate" button is clicked, the validation request is sent to the server where text entered into the valueId field will be validated for the Hibenate Validator @Length annotation correspondence (and any other Validator annotation presented at lastName).

  • If the text entered does not meet the requirements, the error message will be displayed for the field. Please note that this request is asynchronous and you can create validator for each of, e.g., 10 fields of your form that will automatically start triggering at the focusOut event and show error messages independently.

Note

Add destination person to the "services-config.xml" file as destination as if it is used for the RemoteObject component. See example in the AMF for Flex/Seam section of Chapter 3: Getting Started with Flamingo.

5.1.1.2. HessianEntityValidator

HessianEntityValidator has the same properties and methods as EntityValidator. It replaces the former SeamValidator starting from deprecated version 1.0.2. See the code sample for this component below.

5.1.1.2.1. Code Sample

An example of validation using the HessianEntityValidator component can be performed the same way as with the help of EntityValidator. Just use this code sample for your .mxml file:

<flamingo:HessianEntityValidator id="validator" 
  destination="seam/resource/hessian/person" 
  validationTarget="lastName" 
  source="{test}" 
  property="text" />
<mx:Form>
    <mx:TextInput id="test" />
    <mx:Button label="Validate" click="validator.validate()" />
</mx:Form>

See a real example how to use the Validator component in the "validation" sample project in Flamingo bundle.

5.1.2. CallSet

This component allows bundling of a set of operations which are propagated to the server. It is used in Flex applications with JBoss Seam and Spring server configuration.

5.1.2.1. CallSet

This component uses the AMF protocol.

5.1.2.1.1. Flex Client Components Reference

Here the properties, events and methods used by CallSet are described.

5.1.2.1.1.1. Properties

CallSet used for the AMF protocol contains the following properties:

Table 5.3. 

PropertyRequiredDescription
idNoThe id of the component. It is specified only if creating the component in the .mxml file
destinationYesThis is a destination specified in the "services-config.xml" file simply to identify channel to use and consequently servlet url mapping. Destination name itself is not relevant

Each CallSet, in its turn, includes a number of Call components that have their own properties:

Table 5.4. 

PropertyRequiredDescription
componentYesThe Seam or Spring server component name the method of which will be called
methodYesThe name of the method to be called
argumentsYesParameters to pass to the method. If these parameters are constant, they can be specified when declaring the Call object. If parameters vary they can be specified with the send method call. Please note that each argument should be an array (see the sample code below: CallSet Code Sample)

5.1.2.1.1.2. Events

The CallSet component includes the following events:

Table 5.5. 

EventDescription
resultThe result event is dispatched when a service call successfully returns. Returned value of each method invoked on the server is stored in ResultEvent passed to the result handler
faultThe fault event is dispatched when a service call fails. Handler for this event will never be called for HessianCallSet (see Known Issues for Hessian 2 in the "Supported Protocols" section)

5.1.2.1.1.3. Methods

The CallSet component has the following methods:

Table 5.6. 

MethodDescription
addCall(Call)Adds a Call to the end of the Calls list of the CallSet
addCallAt(Number, Call)Adds a Call to the specified position in the Call list of the CallSet
removeCallAt(Number)Removes Call from the specified position from the Call list in the CallSet
send(...args)Invokes server call for all Call methods specified in CallSet. Parameter is an array of arguments for each Call. The number of arguments should be equal to the number of Calls in the CallSet. If arguments are set during the CallSet object declaration, call send() without parameters in order to use declared arguments. If arguments are set and specified for the send call, the values in send take precedence

5.1.2.1.2. Flex Server Components Reference

Seam or Spring component named com.exadel.flamingo.service.callset.callSetManager is used on the server side to manage CallSet processing. See Java documentation for this class for more information.

Note

To have CallSet working for the Spring application add the following line into your Spring context file:

<context:component-scan base-package="com.exadel.flamingo.service"/>
5.1.2.1.3. Code Sample
  • Use this CallSet code sample in your .mxml file:

<mx:Script>
    <![CDATA[
        private function loginResultHandler(event:ResultEvent):void
        {
            var results:Array = event.result as Array;
            if (results[3])
            {
                Alert.show('Successfully logged in');
            } else {
                Alert.show('Login failure');
            }
        }
    ]]>
</mx:Script>
        
<flamingo:CallSet id="loginCallSet" 
  result="loginTestResultHandler(event)"
  destination="callSet">
    <flamingo:Call component="identity" method="setUsername"/>
    <flamingo:Call component="identity" method="setPassword"/>
    <flamingo:Call component="identity" method="login"/>
    <flamingo:Call component="identity" method="isLoggedIn"/>
</flamingo:CallSet>
        
<mx:Button id="loginBtn" label="Login" click="loginCallSet.send(["flamingo"],["secret"],[],[])"/>

This sample shows the way the CallSet component is used to bundle 4 server method calls in one server request to authenticate a user via the identity Seam component.

  • Add callSet destination to the "services-config.xml" file:

<services-config>
    <services>
        <service
            id="binding-service"
            class="flex.messaging.services.RemotingService"
            messageTypes="flex.messaging.messages.RemotingMessage">
            <destination id="callSet"/>
            <default-channels>
                <channel ref="seam-amf"/>
            </default-channels>
        </service>
    </services>
    <channels>
        <channel-definition id="seam-amf" class="mx.messaging.channels.AMFChannel">
            <endpoint
                uri="http://{server.name}:{server.port}/myapp/seam/resource/amf/"
                class="flex.messaging.endpoints.AMFEndpoint"/>
        </channel-definition>
    </channels>
</services-config>

Note

Please note that the actual name of the identity Seam component mentioned is org.jboss.seam.security.identity. This works because Flamingo automatically processes EL expressions transferred from the client side.

Flamingo supports execution of the whole CallSet inside of one transaction for a project with EJB support. In order to do that, add the following string into the “components.xml” file:

<component name="com.exadel.flamingo.service.callset.callSetManager" class="com.exadel.flamingo.flex.callset.EJBCallSetManager"/>

See a real example how to use the CallSet component in the "callSet" sample project in Flamingo bundle.

5.1.2.2. HessianCallSet

HessianCallSet has the same properties, events and methods as CallSet. See the code sample for this component below.

5.1.2.2.1. Code Sample
<flamingo:HessianCallSet id="loginCallSet" 
  destination="seam/resource/hessian/"
  result="loginTestResultHandler(event)">
    <flamingo:SeamHessianCall component="identity" method="setUsername"/>
    <flamingo:SeamHessianCall component="identity" method="setPassword"/>
    <flamingo:SeamHessianCall component="identity" method="login"/>
    <flamingo:SeamHessianCall component="identity" method="isLoggedIn"/>
</flamingo:HessianCallSet>

5.1.3. Binding

This component allows synchronization between JBoss Seam or Spring server objects and Flex client objects. There are 2 choices of the component, one for each of two protocols: BindingService for AMF and HessianBindingService for Hessian.

5.1.3.1. BindingService

This component uses the AMF protocol.

If you use BindingService to bind an object that is an entity (has the javax.persistence.Entity annotation) there is a possiblity for you in Flamingo to automatically merge the content of the object into the database when committing it to the server.

For Seam, you need to have the managed persistence context (JPA) correctly configured and have option "flamingoConfig.bindingManagerPersistsEntity true" specified in the "seam.properties" file.

For Spring, you need to have Hibernate SessionFactory correctly configured and file "flamingoConfiguration.properties" with content bindingManager.persistEntities=true defined in classpath.

Add the following string to Spring configuration:

<util:properties id="flamingoConfiguration" location="classpath:flamingoConfiguration.properties"/>
5.1.3.1.1. Flex Client Components Reference

Here the properties, events and methods used by BindingService are described.

5.1.3.1.1.1. Properties

BindingService used for the AMF protocol contains the following properties:

Table 5.7. 

PropertyRequiredDescription
idNoThe id of the component. It is specified only if creating the component in the .mxml file
destinationYesThe name of the Seam or Spring component you want to bind to on the server. For AMF, you need to add this destination to the "services-config.xml" file. For Hessian, a complete URL to the component including servlet path should be specified
sourceYesThe Flex client object you want to bind to the server object

5.1.3.1.1.2. Events

The Binding component includes the following events:

Table 5.8. 

EventDescription
resultThe result event is dispatched when a service call successfully returns
faultThe fault event is dispatched when a service call fails.

5.1.3.1.1.3. Methods

The Binding component has the following methods:

Table 5.9. 

MethodDescription
commitUpdates object on the server with data sent from the client side
updateUpdates object on the client with data taken from the server side

5.1.3.1.2. Flex Server Components Reference

Seam or Spring component named com.exadel.flamingo.flex.binding.bindingManager is used on the server side to manage binding processing. See Java documentation for this class for more information.

Note

To have Binding working for the Spring application add the following line into your Spring context file:

<context:component-scan base-package="com.exadel.flamingo.service"/>
5.1.3.1.3. Code Sample
  • Add the following Seam component:

package com.mycompany.myproject.seam;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
@Name("personBean")
@Scope(ScopeType.SESSION)
public PersonBean{
    private String firstName;
    private String lastName;
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}
  • Add the following content for binding on Flex:

package com.mycompany.myproject.flex.vo
{
[RemoteClass(alias="com.mycompany.myproject.seam.PersonBean")] 
[Bindable]
public class PersonVO
{
private var _firstName:String;
private var _lastName:String;
public function get firstName():String
{
return _firstName;
}
public function set firstName(value:String):void
{
_firstName = value;
}
public function get lastName():String
{
return _lastName;
}
public function set lastName(value:String):void
{
_lastName = value;
}
}
}
  • Add the following mxml code:

<mx:Application creationComplete="init()">
<mx:Script>
<![CDATA[
import com.mycompany.myproject.flex.vo.PersonVO;
import mx.controls.TextInput;
[Bindable]
private var user:PersonVO;
private function init():void 
{
user = new PersonVO();
user.firstName = "John";
user.lastName = "Smith";
}
]]>
</mx:Script>
       
<flamingo:BindingService id="personBinding" 
    destination="personBean" 
    source="{user}" />
       
<mx:TextInput text="{user.firstName}"/>
<mx:TextInput text="{user.lastName}"/>
<mx:Button label="Send data to server" click="personBinding.commit()"/>
<mx:Button label="Get data from server" click="personBinding.update()"/>
</mx:Application/>

Note

Add destination personBean to the "services-config.xml" file as destination as if it is used for the RemoteObject component. See example in the AMF for Flex/Seam section of Chapter 3: Getting Started with Flamingo.

Note

File "commons-beanutils.jar" is needed to perform binding on the server, please make sure it is in classpath.

Binding synchronizes object with any level of hierarchy of nested objects/collections. In case if collection is sent from the server to the client using Hessian, the content of this collection will be deserialized into objects of the Object class, i.e. the original object class will not be restored (see Known Issues in the Supported Protocols section related to binding: "mx.collections.ArrayCollection", "Deserialization to ActionScript Classes").

Object structure on client side defines a level of hierarchy binding will be performed with.

 

In order to take the most advantage from binding, use [RemoteClass] metadata for AMF and hessianTypeName class variable for Hessian (see an example below). Otherwise objects coming from the client side to the server will be deserialized into HashMap and collections will be filled with HashMap objects if generics for collections are not used on the server.

Currently no "stale data" events are generated during the commit/update operations; objects are not merged but completely overwritten.

 

Flamingo supports binding inside of one transaction for a project with EJB support. In order to do that, add the following string into the "components.xml" file:

<component name="com.exadel.flamingo.flex.binding.bindingManager"  class="com.exadel.flamingo.flex.binding.EJBBindingManager"/>

Note

Flamingo allows to sync data from/to Seam components named using annotations @Name, @Out, @Factory, @DataModel and others with two exceptions: a) binding to @DataModel and @Factory is read only, b) binding to <mx:Model> is currently supported from the server to the client side only; i.e. the "commit" operation cannot be performed in both cases.

See a real example how to use the Binding component in the "binding" sample project in Flamingo bundle.

5.1.3.2. HessianBindingService

HessianBindingService has the same properties, events and methods as BindingService. See the code sample for this component below.

5.1.3.2.1. Code Sample

The code sample for HessianBindingService is almost identical to the sample provided for BindingService component, see below:

<flamingo:HessianBindingService id="personBinding" 
destination="seam/resource/hessian/personBean" 
source="{user}" />

5.1.4. SeamRemoteObject

This component supports Seam conversations in Flex applications. SeamRemoteObject extends a standard RemoteObject, thus it can be used similarly. It is unlikely that more than one conversation will be used in any Flex application, so all objects of the RemoteObject class will share the same conversation ID. In order to have an ability to work with several conversations use the following methods of the SeamRemote object: SeamRemoteObject.getConversationId() and SeamRemoteObject.setConversationId().

5.1.4.1. Code Sample

Here is an example of usage of several SeamRemoteObject components in the context of one conversation:

  • Add files "ConversationStarter.java" and "ConversationStopper.java" on the server:

"ConversationStarter.java":

@Name("conversationStarter")
public class ConversationStarter {
    @Begin
    public void start() {
    }
}

"ConversationStopper.java":

@Name("conversationStopper")
public class ConversationStopper {
    @End()
    public void stop() {
    }
}
  • Use this code sample in your .mxml file:

<flamingo:SeamRemoteObject id="starter" destination="conversationStarter"/>
<flamingo:SeamRemoteObject id="stopper" destination="conversationStopper"/>
<mx:Form>
    <mx:FormItem>
<mx:Button label="Start conversation" click="starter.start();" />
<mx:Button label="Stop conversation" click="stopper.stop();" />
    </mx:FormItem>
</mx:Form>
  • Then specify conversationStarter and conversationStopper destination in the "services-config. xml" file.

When clicking on the "Start" button the conversation starts on the server, when "Stop" - the conversation is stopped. You can check this by clicking on the "Start" button twice: you will get an error message that the conversation is running already.

5.1.4.2. Flex Client Components Reference

Here the events and methods used by SeamRemoteObject are described.

5.1.4.3. Events

The SeamRemoteObject component includes the following events:

Table 5.10. 

EventDescription
resultThe result event is dispatched when a service call successfully returns
faultThe fault event is dispatched when a service call fails

5.1.4.4. Methods

The SeamRemoteObject component has the following methods:

Table 5.11. 

MethodDescription
getConversationIdGets an id of the current conversation that is shared between all objects of the SeamRemoteObject component
setConversationIdSets identifier of the conversation to continue working with

5.2. JavaFX Components

In this chapter 3 client JavaFX components are described.

5.2.1. Validator

This component allows validating user input against Hibernate Validator annotations on the server. It is used in JavaFX applications which use Seam or Spring server configuration. The component is designed for the Hessian protocol only and is called: HessianEntityValidator.

5.2.1.1. HessianEntityValidator

This component uses the Hessian protocol.

5.2.1.1.1. JavaFX Client Components Reference

Here the properties and methods used by HessianEntityValidator are described.

5.2.1.1.1.1. Properties

HessianEntityValidator has the following properties:

Table 5.12. 

ElementRequiredDescription
destinationYesThis can be: a) full qualified class name of entity that contains a method annotated b) name of entity specified in the @Entity annotation, or simple class name if entity name is omitted c) name of the Seam component if specified for entity. In the example provided in the Sample Code section, valid values are person, Person and com.mycompany.myproject.PersonBean. For AMF, you need to add this destination to the "services-config.xml" file
sourceYesSpecifies the JavaFX client component containing the property to validate. This component should be derived from javax.swing.text.JTextComponent
propertyYesA String specifying the name of the property of the source object that contains the value to validate
requiredNoIf true, specifies that a missing or empty value causes a validation error. If false, no validation server call will be executed for the empty value. The default value of the parameter is false
returnedMessageNoContains text in which the validation error is returned if there is any

5.2.1.1.1.2. Methods

JavaFX HessianEntityValidator has the following methods:

Table 5.13. 

MethodDescription
doValidation(String)It executes validation call to the server taking into consideration class properties destination and property. The String type is the only value validated. A validation error message is returned if there is any
validate()This method validates text in the visual component specified in the source property

5.2.1.1.2. JavaFX Server Components Reference

Seam or Spring component named com.exadel.flamingo.service.validator.entityValidator is used on the server side to manage validation processing. See Java documentation for class com.exadel.flamingo.service.validator.EntityValidatorImpl for more information.

Note

To have Validator working for the Spring application add the following line into your Spring context file:

<context:component-scan base-package="com.exadel.flamingo.service"/>
5.2.1.1.3. Code Sample

See a sample below:

package com.exadel.flamingo.javafx;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Color;
import javafx.scene.text.TextOrigin;
import javafx.ext.swing.SwingButton;
import javafx.scene.layout.VBox;
import javafx.scene.control.TextBox;
            
import com.exadel.flamingo.javafx.components;
            
var validator = HessianEntityValidator {
          destination: "person" 
          property: "lastName"
}
            
var textField: TextBox = TextBox {
      text: "test"
      columns: 7
      selectOnFocus:true
}
            
var sampleLabel = Text{
      y: 8
      font: Font { name:"sansserif", size: 12 }
      fill: Color.BLACK
      content: bind validator.returnedMessage
      textOrigin: TextOrigin.TOP
}
            
var validateButton = SwingButton  {
       text: "Validate"
       action: function(){
              validator.validate();
        }
}
            
Stage {
            width: 300
            height: 200
            title: "Validation Sample"
            scene: Scene {
                content: VBox {
                        translateX: 5
                        translateY: 5
                        spacing: 10
                        content: [                
                                HBox {
                                          content: sampleLabel
                                          spacing: 10
                                 },
                                 HBox {
                                                           content: textField
                                            spacing: 10
                                 },
                                 HBox {
                                                           content: validateButton
                                             spacing: 10
                                 }]
                        }
            }
}
            
          

In this example when the "Validate" button is clicked, the validation request is sent to the server where text entered into the textField field will be validated for the Hibenate Validator @Length annotation correspondence (and any other Validator annotation presented at lastName).

If there is any validation error message it will be displayed in the SimpleLabel.

See the server code sample in 5.1.1.1.3: Code Sample

5.2.2. Binding

This component allows synchronization between JBoss Seam server objects and JavaFX client objects. The component is designed for the Hessian protocol only and is called HessianBindingService.

HessianBindingService for JavaFX has the same properties, events and methods as BindingService and HessianBindingService for Flex. Please refer to the description of Binding provided for Flex and to the code sample provided for HessianBindingService.

5.2.3. ServiceFactory

Flamingo JavaFX Client Components includes class com.exadel.flamingo.javafx.ServiceFactory that helps easily create proxy objects on the client side. Use class SeamServiceFactory to create proxy objects supporting Seam conversations.

Table 5.14. 

MethodDescription
setUrl(String_url)Sets the base URL to access the server
getService(Class clazz, String componentName)With the help of this method a proxy object is created for Seam component with the componentName name. clazz is a local interface of the Seam server component

See samples how to use ServiceFactory in the JavaFX Hotel Booking demo.

5.2.4. SeamServiceFactory

The .jar file with Exadel Flamingo JavaFX Client Components includes a class that supports Seam conversations: com.exadel.flamingo.javafx.seam.SeamServiceFactory. This class is intended to create client proxy object that automatically supports conversations when performing a server call.

SeamServiceFactory has the following static methods:

Table 5.15. 

MethodDescription
setUrl(String_url)Sets the base URL to access the server
getService(Class clazz, String componentName)With the help of this method a proxy object is created for Seam component with the componentName name that automatically supports conversations when executing remote calls. clazz is a local interface of the Seam server component

5.2.4.1. Code Sample

Add files "ConversationStarter.java" and "ConversationStopper.java"on the server:

"ConversationStarter.java":

@Name("conversationStarter")
public class ConversationStarter {
    @Begin
    public void start() {
    }
}

"ConversationStopper.java":

@Name("conversationStopper")
public class ConversationStopper {
    @End()
    public void stop() {
    }
}

 

This is an example of the application that works with conversations:

package com.exadel.flamingo.javafx;
      
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.HBox;
import javafx.ext.swing.SwingButton;
import javafx.scene.layout.VBox;
      
import com.exadel.flamingo.javafx.seam.SeamServiceFactory;
      
SeamServiceFactory.setUrl("http://localhost:8080/helloworld/seam/resource/hessian");
      
var buttonStart = SwingButton  {
      text: "Start conversation"
      action: function(){
             SeamServiceFactory.getService(ConversationStarter.class,
                                    "conversationStarter").start();
      }
}
      
var buttonStop = SwingButton  {
      text: "Stop conversation"
      action: function(){
            SeamServiceFactory.getService(ConversationStopper.class,
                                   "conversationStopper").stop();
      }
}
      
Stage {
           width: 300
           height: 200
           title: "Validation Sample"
           scene: Scene {
               content: VBox {
                       translateX: 5
                       translateY: 5
                       spacing: 10
                       content: [                
                               HBox {
                                         content: buttonStart
                                         spacing: 10
                               },
                               HBox {
                                                        content: buttonStop
                                         spacing: 10
                                     }]
                       }
           }
}
      

When clicking on the "Start" button the conversation starts on the server, when "Stop" - the conversation is stopped. You can check this by clicking on the "Start" button twice: you will get an error message that the conversation is running already.

5.3. "Hotel Booking" Demo

You can find examples how to use all components for AMF and Hessian in the "Hotel Booking" Seam demo developed with Flamingo: http://demo.flamingo.exadel.com/. You can compare Flamingo version with the original one and see how amazingly fast Flamingo demo works!

Chapter 6. Flamingo Dynamic Persistent Methods

Flamingo provides a very powerful capability for operations on entities directly from the Flex user interface. General thinking is that access from user interface must be architected with the layer of facades (DAOs), but in some cases these facades introduce unnecessary complexity, and in other cases, having a framework providing these facades in a uniform matter is just more convenient. Flamingo provides dynamic methods to operate on entities directly without facades. Most of queries performed on projects are not that complex. These simple queries can be completely replaced by Flamingo dynamic persistent methods, as almost no effort is required to use them. These methods are split into two main categories:

  • Dynamic Finders

  • Dynamic Updaters

6.1. Dynamic Finders

Dynamic finders are a group of methods which have been designed in order to create queries on the fly without having to implement any additional logic on server or client side. These queries have the following syntax:

findBy[property]Operator(parameter(s))

where

  • Property - capitalized name of a property

  • Operator – operator supported by Flamingo

Example 6.1. Code Example

If there is the following entity:

@Entity
public class Person implements Serializable {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }   	
} 

then the following usage of dynamic finders is possible:

... 
<mx:RemoteObject id="person" destination="Person" result="resultHandler(event)"/>
...
private function resultHandler(event:ResultEvent):void
{
    entities = event.result as ArrayCollection;
}
...
person.findAll();
person.findByNameLike("John%");
person.findByNameNotEqual("John Smith");

where Name is a property of bean Person, and Like and NotEqual are operators used in this examples.


Currently the following operators are supported:

Table 6.1. 

Supported Operators
Equal
NotEqual
Like
And
Or
Not
IsNull
IsNotNull
LessThan
LessThanEquals
GreaterThan
GreaterThanEquals
Between

6.1.1. Query by Relationship

Flamingo also supports dynamic querying by relationship. You can easily search for an entity by its relationship to another entities. Just include relationship into the search operator, for example: suppose you have 2 entities with "one-to-many" relationship:

Example 6.2. Code Example

@Entity
public class Person implements Serializable {
....
private Set<Book> books;
@OneToMany(mappedBy = "person", fetch = FetchType.EAGER)
public Set<Book> getBooks() {
return books;
}
}
@Entity
public class Book implements Serializable {
             private Person person;
@ManyToOne(fetch = FetchType.EAGER)
public Person getPerson() {
return person;
}
}

Now you can call objects by relationship. Declare this remote object:

<mx:RemoteObject id="book" destination="Book"/>

To get a list of Books owned by currentPerson just request method book.findByPerson(currentPerson).


6.1.2. Sorting

You can also use sorting when sending a query to the database. In order to do that specify additional parameters in the find... method.

Example 6.3. Code Example

Here is an example of sorting for one column:

person.findAll({sortBy:'name', order:'desc'});

It shows all objects person sorted by their names in the descending order.

 

Here is an example of sorting for several columns at once:

person.findAll({sortBy:'id, name', order:'desc'});

It shows fields sorted by id in the descending order and then by name in the ascending order. This happens as ascending order is set by default and will be used if not specified separately.


6.2. Dynamic Updaters

Flamingo provides two dynamic updaters:

  • save

  • remove

The save method will persist all properties of a remote object mapped to the database, while the remove method will delete this entity from the database. Calling these methods is equally easy:

<mx:RemoteObject id="person" destination="Person" result="resultHandler(event)"/>
...
var modifiedPerson:Person;
modifiedPerson = ObjectUtil.copy(originalPerson) as Person;
modifiedPerson.name = "New Name";
person.save(modifiedPerson);
...
person.remove(modifiedPerson);

Chapter 7. Supported Communication Protocols

This chapter tells about binary format protocols AMF and Hessian supported by Exadel Flamingo and known issues with using Hessian 2.

Pay your attention to a summary table below to see the communication protocols supported for the client and the server parts of the application used by Exadel Flamingo.

Table 7.1. 

Client TechnologySupported Communication Protocols
SeamSpring
FlexAMF, HessianAMF, Hessian
JavaFXHessianHessian

7.1. Hessian 2

Hessian is a binary web service protocol that makes web services usable without requiring a large framework, and without learning yet another alphabet soup of protocols. It is well-suited to sending binary data without any need to extend the protocol with attachments.

Hessian is a binary cross-platform remoting protocol. Most cross-platform protocols are XML-based, and thus sacrifice a significant amount of performance in order to achieve interoperability. Hessian’s draw is that it achieves cross-platform interoperability with minimal performance degradation.

The benefits of Hessian 2 protocol usage:

  • It does not require an external schema or interface definitions

  • It is language-independent, including supporting scripting languages

  • It is simple, compact and fast

  • It supports encryption, compression, signature, and transaction context envelopes

Hessian shows excellent response time. Comparison of Hessian 2 with other protocols can be found at http://daniel.gredler.net/2008/01/07/java-remoting-protocol-benchmarks/.

We conducted some tests to compare performance of Hessian and AMF and they showed that Hessian 2 has, on average, approximately one and a half better performance results with little amounts of data (a full cycle was taken into consideration: serialization, transfer, deserialization).

7.1.1. Known Issues

Listed below is a list of known issues for Hessian 2:

  • "Date" issue. Be aware that Hessian may deserialize objects of the java.sql.Date class incorrectly, that means you will get a result on client different from what was sent from the server.

  • "mx.collections.ArrayCollection" issue. Hessian has no serializer for the mx.collections.ArrayCollection class, thus, while sending objects of this class to the server via the Hessian protocol they are serialized and deserialized into HashMap. Workaround for this may be the usage of the Array class instead.

  • Deserialization to ActionScript Classes issue. Specify the returnType property for HessianOperation while requesting typified compound objects from the server using the Hessian protocol; otherwise they will be deserialized into dynamic objects of the Object type.

  • "Fault" event issue. Request of the HessianOperation.send method generates a fault event in any result of operation (successful/unsuccessful); that limits usage of fault event listeners.

  • Uninitialized Number deserialization issue. When sending a Number object from client to the server and the value of the object is not initialized (NaN), Hessian deserializes such an object into the Double object and initializes it to 0.

7.2. AMF

Action Message Format (AMF) is a compact binary format that is used to serialize ActionScript object graphs. Once serialized an AMF encoded object graph may be used to persist and retrieve the public state of an application across sessions or allow two endpoints to communicate through the exchange of strongly typed data.

The benefits of AMF protocol usage:

  • File size - AMF objects are of a very small volume due to the fact that they are compressed using “zlib”

  • Quick serializing/unserializing - speed encoding/decoding in the AMF is very high, even with little memory and a slow processor

  • Support for standard data types as well as their own classes - you can serialize virtually any object

7.2.1. AMF-Serializer

As no specification was published for the AMF protocol by Adobe® during the development of Exadel Flamingo and no standalone implementation exists, Exadel Flamingo uses its own library: AMF-serializer which is licensed under the GNU LGPL. This library with source code is shipped with the Exadel Flamingo download bundle. For more information see "http://code.google.com/p/amf-serializer/".

Chapter 8. Security

This chapter discusses authentication and authorization mechanisms in Flamingo for Seam and Spring Security on the server side.

8.1. Authentication

Authentication is the process by which a user proves his or her identity to a system.

There are 2 kinds of authentication in Flex: Basic and Custom. Basic authentication is similar to standard basic J2EE authentication implemented by the browser means. Custom authentication is similar to form-based authentication that requires a login form creation.

The authentication features provided by Seam Security are built upon JAAS. This kind of authentication uses a built-in JAAS login module, SeamLoginModule, which delegates authentication to one of Seam components. Seam supports HTTP and Digest authentication as well.

In Spring the standard mechanism via Spring Security (former Acegi Security System) is used. Exadel Flamingo supports Spring Security version 2.0.0 and higher. For more information about authentication providers for Spring Security see at

http://static.springframework.org/spring-security/site/index.html

8.1.1. Flamingo Authentication

Flamingo provides mapping between Flex and Seam authentication in the following way: Flex Basic authentication is mapped to Seam HTTP Basic authentication and Flex Custom authentication is mapped to JAAS. Examples of each authentication method can be found in flamingo-1.8.1.zip, “Examples” folder.

  

The aim of Flamingo is to support in Flex standard security mechanisms of Seam or Spring without any additional configurations. Flamingo does not require you to secure destinations as it is usually done in Flex. All security access restrictions are taken from Seam or Spring directly.

8.1.1.1. Basic Authentication

When you use Basic authentication to secure access to destinations in Flex, you usually secure the endpoints of the channels that these destinations use in the "web.xml" file. You then configure the destination to access the secured resource in order to be challenged for a user name (principal) and password (credentials). The web browser performs the challenge, which happens independently of Flex. The web application container authenticates the user's credentials.

  

With Flamingo you don't need to configure secure channels for basic authentication. If you have basic authentication applied on the server either via standard Java EE configuration in the "web.xml" file or via native Spring Security or Seam configuration, you don't need any additional settings in Flex.

8.1.1.1.1. Seam Configuration

For Seam, the only thing needed is to configure

<web:authentication-filter>

in "components.xml" or

<security-constraint>

in "web.xml" (see the "security-basic" sample). During the server call users will be able to see an authentication dialog.

In Seam authentication is configured in the "components.xml" file:

<web:authentication-filter url-pattern="/seam/resource/*" auth-type="basic"/> 

Tip

Currently there is an issue related to Seam HTTP Basic authentication with using <web:authentication-filter>, that is likely fixed in Seam 2.1.0. Workaround for this will be to use standard J2EE Basic authentication configuration (<security-constraint>, <login-config> in "web.xml").

8.1.1.1.2. Spring Security Configuration

This is an example how you can configure basic authentication for Flex client in an application that uses Spring Security:

<http auto-config="true">
      <intercept-url pattern="/flamingo/**" access="ROLE_USER" />
      <intercept-url pattern="/**" filters="none" />
    </http>
    <authentication-provider>
      <password-encoder hash="md5"/>
        <user-service>
          <user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_USER" />
          <user name="dianne" password="65d15fe9156f9c4bbffd98085992a44e" authorities="ROLE_USER" />                         
        </user-service>
   </authentication-provider>

See sample in "spring-security.xml" in demo "spring-flex-authentication-basic" in the "examples" folder.

8.1.1.2. Custom Authentication

When using custom authentication you should call certain methods on the server to perform the authentication itself. For custom authentication, Flex uses a custom login adapter, known as a login command, to check a user's credentials and log a principal into the application server. If you also want to use custom authorization, you must link the specified role references to roles that are defined in your application server's user store. Flamingo does not require you to configure roles for custom authentication/authorization as all necessary data is taken from the server configuration.

Seam

The standard approach to usage of custom authentication is the use of the identity component as shown in example 5.2.1.3 with the help of the CallSet component. After that, user will be logged on the server. As an alternative to this, you can use the setCredentials() method for the RemoteObject class (HessianService does not support this mechanism):

<mx:RemoteObject id="service" destination="identity"/>
<mx:Button label="Authenticate" click="service.setCredentials('username', 'password'); service.isLoggedIn()"/>

Note

Please note, that method setCredentials() does not perform its own server call, the call itself is performed during the isLoggedIn() method invocation. Remote object methods setCredentials() and logout() correspond to methods login() and logout() of the identity component. The identity.isLoggedIn() method can be used to verify whether the user is logged in.

Spring

There are two ways how you can use custom authentication for Spring:

1. Create a Spring Service bean with methods like "login", "doLogout", "isLoggedIn" that will be requested from Flex. This bean will perform authentication using Spring Security API.

2. Use methods "setCredentials", "logout" of the RemoteObject component. For example:

<mx:RemoteObject id="service" destination="myService"/>
<mx:Button label="Call secure method" click="service.setCredentials('username', 'password'); service.callMethod()"/>

In this example, before calling method callMethod the authentication will be performed on the server according to Spring Security configuration set in the application.

Method "logout" of RemoteObject will remove currently authenticated principal from the security context. Methods "setCredentials" and "logout" affect not only the destination they were called from but the whole application as well.

8.2. Authorization

Authorization is the process of determining what types of activities a user is permitted to perform in a system.

8.2.1. Seam Authorization

Flamingo completely relies on and supports Seam authorization mechanism. Seam provides two modes of authorization:

  • simplified mode - this mode supports authentication services and simple role-based security checks

  • advanced mode - this mode supports all the features supported by the simplified mode, plus it offers rule-based security checks using JBoss Rules

8.2.1.1. Simplified

In this mode you can check which roles a user currently logged on has and then deny or grant access to some resource. The roles are usually defined on the server side in the method described in the "components.xml" file:

<security:identity authenticate-method="#{authenticator.authenticate}"/>

After calling identity.login() you can check a role using the identity.hasRole() server call.

8.2.1.2. Advanced

Checking Seam permission involves executing the rule engine, therefore it should be done on server. Typically you need to check permissions in the way described below:

<mx:Script>
    <![CDATA[
    private function permissionResultHandler(event:ResultEvent):void
    {
        if ( event.result ) {
            Alert.show("You have permission");
        } else {
            Alert.show("You do not have permission");
        }
    }
    ]]>
</mx:Script>
<mx:RemoteObject id="identityService" destination="identity">
    <mx:method name="hasPermission" result="permissionResultHandler(event)" />
</mx:RemoteObject>
<mx:Button label="Check permission" click="identityService.hasPermission('account',  'delete', null)"/>

8.2.2. Spring Authorization

There are several ways how you can configure authorization in an application using Spring Security 2.0. All these options can be set in the configuration file using the <global-method-security> element. They can be divided into two groups:

  • Annotation-based

  • Using AOP

For annotation-based way of configuration you can use either native @Secured annotation or use JSR-250 security annotations for Java 5 or higher.

For AOP you can declare Security Pointcuts using the <protect-pointcut> sub-element of <global-method-security>.

See samples in "spring-flex-authorization" in the "examples" folder.

Chapter 9. Seam Internationalization

Each user login session has an associated instance of java.util.Locale (available to the application as a component named locale). In order to set the locale manually via the application user interface, you should change the following properties of the localeSelector component: language, country, variant.

The current locale for the Flex application can be set during the compilation process with the help of the compiler option, for example "-locale en_US":

See "mx.resources.Locale" for more details.

The code sample below shows how the current client locale can be received and then set to use in Seam:

<mx:Script>
    <![CDATA[
        import mx.resources.Locale;
        private function setLocale():void
        {
            var l:Locale = Locale.getCurrent(Application.application.systemManager);
            localeSelectorService.setLanguage(l.language);
        }
    ]]>
</mx:Script>
<mx:RemoteObject id="localeSelectorService" destination="localeSelector">
    <mx:method name="setLanguage" />
</mx:RemoteObject>

Chapter 10. Advanced Topics

This chapter introduces more advanced notes on using Flamingo:

10.1. "RemoteObject" Destinations

Only destination and source properties set in the RemoteObject Flex component are processed on the server, and source takes precedence, if set. If source is not specified, destination is treated as a name of the Seam component. If source is specified, the Seam component is searched for by source.

10.2. "RemoteObject" and "HessianService" Methods/Properties Limitations

There are several limitations on the use of server methods with Flex components RemoteObject and HessianService: calls of methods logout(), disconnect() and other that are declared in classes RemoteObject, HessianService and their parent class AbstractService will not be invoked as remote server calls, but only local component calls. This limitation can be avoided by using the SeamCallSet component. For more information on methods and properties see Adobe livedocs: "AbstractService" and "RemoteObject".

10.3. "WebRemote" Configuration

By default, Seam Remoting only allows calling methods marked with the @WebRemote annotation. Flamingo by default is not dependent on this annotation, and can call any method of any Seam component. If necessary, you can limit calls to the @WebRemote methods. See the Note areas of subchapters Using Seam Remoting and Using Servlets in the Installation section for details. And there is another way of "WebRemote" configuration different from that: add the following string into the "seam.properties" file found in the root of the classpath:

flamingoConfig.webRemoteEnabled=true

10.4. Enumerated Types

As ActionScript3 has no linguistic support built in for enumerated types, Flamingo suggests a simple way to convert Java's enums types to AS3 String when using the AMF protocol as a transport. Thus, to map a field of enum type in Java class create a corresponding field of a String type in AS3 class.

Also, there is support of mapping for collections with enum used as a generic parameter. See examples below.

Here is an example for Java:

package com.exadel.example;
public class Card {
    public enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES }
    private Suit suit;
    public Suit getSuit() { return suit; }
    public void setSuit(Suit suit) {
        this.suit = suit;
    }
 }

This is an example for ActionScript3:

package com.exadel.example
{
[RemoteClass(alias="com.exadel.example.Card")]
public class Card
{
public var suit:String;
}
}

Chapter 11. Legal Notes

The material in this guide is Copyright (c) 2008, by Exadel, Inc. and others.

This product includes software developed by the Caucho Technology (http://www.caucho.com/).

11.1. License

This Content is provided to you under the terms and conditions of the GNU Lesser GENERAL PUBLIC LICENSE version 3 ("LGPL"). A copy of the LGPL is available at http://www.gnu.org/licenses/lgpl.txt

Unless otherwise indicated below, the terms and conditions of the LGPL apply to any source code in the Content and such source code may be obtained at http://www.exadel.com.