Copyright © 2008 Exadel, Inc.
This chapter contains a high-level introduction to Exadel Flamingo — what it is and what it does.
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.
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.
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.
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.
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.
Below is a list of the supported software versions necessary to start working with Flamingo.
Adobe® Flex™ 2.0.1 Hotfix 2 and higher - (http://www.adobe.com/go/kb402000)
Adobe® Flex™ 3.0
JavaFX SDK 1.2
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.
This chapter describes where you can get Exadel Flamingo, how to install it and work with a simple helloworld demo.
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.
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.
This section of the guide will discuss necessary server configuration for JBoss Seam.
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.
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.
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.
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>If Seam Remoting is not used in your project:
<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.
<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.
See also Chapter 6: Supported Communication Protocols to find more information about both Protocols and their configuration.
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>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.
Using Flamingo you can call not only stateless but stateful components as well, and the state will be saved from call to call.
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.
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:
Compile an .swf file using parameter "mxmlc -output client.swf -compiler.services services-config.xml client.mxml" in the command line.
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!
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:
Compile an .swf file using parameter "mxmlc -output client.swf -library-path+=hessian-flash-3.1.2.swc client.mxml" in the command line.
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
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".
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
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.
"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:
Create interface “IHelloAction.java” for the helloAction Seam component:
package com.exadel.flamingo.javafx.samples;
public interface IHelloAction {
public String hello(String name);
}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
Change ":" to ";" if using Microsoft® Windows.
Enjoy the results!
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.
This section of the guide will discuss necessary server configuration for Spring.
<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.
<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.
See also Chapter 6: Supported Communication Protocols to find more information about both Protocols and their configuration.
Now we will create a Spring bean to implement a simple HelloWorld demo:
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>
Using Flamingo you can call not only singleton beans but stateful beans as with the session scope.
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.
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.
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!
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.
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
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".
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.
You can create a new Flamingo project in two ways: using Adobe Flex Builder or Maven FlamingoApp Generator Plugin.
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:
Select Project Type: select "Basic (e.g. XML or web service from PHP/JSP/ASP.NET )". Click Next.
Specify a name for your project: e.g. "validation". Browse a destination folder where your project will be located. Click Next.
Set the build paths for the new Flex project: Library path > Add SWC:
Browse the "flamingo-flex-1.8.1.swc" file and click OK:
The .swc file is now added. Fields "Main Application File" and "Output Folder" are predefined by the system. Click on Finish.
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.
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>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.
Enter additional compiler arguments: "-services "services-config.xml"" to take into consideration the settings of destination set in the "services-config.xml" file:
Click on the Run button to run the project:
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>
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:
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.
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
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
| Question | Answer 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
| Question | Answer 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.
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=trueIn 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
| Question | Answer Description |
|---|---|
| Please enter entity class name | Enter 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. |
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.
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.
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.
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:
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
| Question | Answer 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
| Question | Answer 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.
|
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.
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.
| Flex | JBoss Seam | Spring |
|---|---|---|
| Validator | yes | yes |
| CallSet | yes | yes |
| Binding | yes | yes |
| SeamRemoteObject | yes | n/a |
| JavaFX | ||
| EntityValidator | yes | yes |
| CallSet | planned | planned |
| Binding | yes | planned |
| ServiceFactory | yes | yes |
| SeamServiceFactory | yes | n/a |
See more about each component in the appropriate section.
In this chapter 4 client Flex components are described.
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).
This component uses the AMF protocol. It replaces the former SeamValidator starting from deprecated version 1.0.2.
Here the properties and methods used by EntityValidator are described.
EntityValidator, used for the AMF protocol, contains 2 distinctive properties and a set of typical Flex validator properties:
Table 5.2.
| Element | Required | Description |
|---|---|---|
| id | No | The id of the component. It is specified only if creating the component in the .mxml file |
| destination | Yes | Flamingo 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 |
| validationTarget | Yes | Flamingo distinctive property. This is a property name of the Seam component or entity class you want to validate |
| source | Yes | Specifies the Flex client object containing the property to validate. |
| property | Yes | A String specifying the name of the property of the source object that contains the value to validate |
| required | No | If 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 |
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.
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.
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"/>
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.
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.
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.
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.
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.
This component uses the AMF protocol.
Here the properties, events and methods used by CallSet are described.
CallSet used for the AMF protocol contains the following properties:
Table 5.3.
| Property | Required | Description |
|---|---|---|
| id | No | The id of the component. It is specified only if creating the component in the .mxml file |
| destination | Yes | This 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.
| Property | Required | Description |
|---|---|---|
| component | Yes | The Seam or Spring server component name the method of which will be called |
| method | Yes | The name of the method to be called |
| arguments | Yes | Parameters 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) |
The CallSet component includes the following events:
Table 5.5.
| Event | Description |
|---|---|
| result | The 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 |
| fault | The 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) |
The CallSet component has the following methods:
Table 5.6.
| Method | Description |
|---|---|
| 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 |
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.
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"/>
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>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.
HessianCallSet has the same properties, events and methods as CallSet. See the code sample for this component below.
<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>
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.
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"/>
Here the properties, events and methods used by BindingService are described.
BindingService used for the AMF protocol contains the following properties:
Table 5.7.
| Property | Required | Description |
|---|---|---|
| id | No | The id of the component. It is specified only if creating the component in the .mxml file |
| destination | Yes | The 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 |
| source | Yes | The Flex client object you want to bind to the server object |
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.
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"/>
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/>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.
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"/>
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.
HessianBindingService has the same properties, events and methods as BindingService. See the code sample for this component below.
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().
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.
Here the events and methods used by SeamRemoteObject are described.
The SeamRemoteObject component includes the following events:
Table 5.10.
| Event | Description |
|---|---|
| result | The result event is dispatched when a service call successfully returns |
| fault | The fault event is dispatched when a service call fails |
In this chapter 3 client JavaFX components are described.
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.
This component uses the Hessian protocol.
Here the properties and methods used by HessianEntityValidator are described.
HessianEntityValidator has the following properties:
Table 5.12.
| Element | Required | Description |
|---|---|---|
| destination | Yes | 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 |
| source | Yes | Specifies the JavaFX client component containing the property to validate. This component should be derived from javax.swing.text.JTextComponent |
| property | Yes | A String specifying the name of the property of the source object that contains the value to validate |
| required | No | If 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 |
| returnedMessage | No | Contains text in which the validation error is returned if there is any |
JavaFX HessianEntityValidator has the following methods:
Table 5.13.
| Method | Description |
|---|---|
| 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 |
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.
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"/>
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
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.
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.
| Method | Description |
|---|---|
| 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.
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.
| Method | Description |
|---|---|
| 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 |
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.
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!
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
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 |
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).
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.
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);
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 Technology | Supported Communication Protocols | |
|---|---|---|
| Seam | Spring | |
| Flex | AMF, Hessian | AMF, Hessian |
| JavaFX | Hessian | Hessian |
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).
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.
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
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/".
This chapter discusses authentication and authorization mechanisms in Flamingo for Seam and Spring Security on the server side.
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 |
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.
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.
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"/>
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").
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.
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()"/>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.
Authorization is the process of determining what types of activities a user is permitted to perform in a system.
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
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.
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)"/>
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.
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>This chapter introduces more advanced notes on using Flamingo:
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.
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".
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
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;
}
}
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/).
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.