blob: a86cafc3827d8ec7736cb5b84c55229220c0cd54 [file] [log] [blame]
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Spring BlazeDS Integration Test Drive</title>
<link href="main.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>Spring BlazeDS Integration Test Drive</h1>
<p>The Spring BlazeDS Integration Test Drive is a set of samples that gets you up and running Flex with BlazeDS and Spring in minutes.</p>
<div class="highlight">
<h2>Samples Index</h2>
<h4>Remoting</h4>
<ul>
<li><a href="#inventory">Spring BlazeDS Integration 101</a>: Demonstrates the basics.</li>
<li><a href="#insync">inSync Contact Management Application</a>: A simple CRUD application built in eight steps.</li>
<li><a href="#company">Company Manager</a>: Similar to the inSync application, but uses <strong>annotation-based configuration</strong>. Also demonstrates object associations.</li>
</ul>
<h4>Messaging</h4>
<ul>
<li><a href="#chat">Chat</a>: Messaging basics</li>
<li><a href="#simplepush">Simple Data Push</a>: A simple data push example</li>
<li><a href="#traderdesktop">Traderdesktop</a>: A more sophisticated data push example showing how to use subtopics</li>
<li><a href="#collaboration">Collaboration</a>: A simple example showing how to use messaging to remotely drive another client's application</li>
</ul>
<h4>Security</h4>
<ul>
<li><a href="#security">Security integration 101</a></li>
</ul>
<h2>Importing the Projects in Flash Builder 4</h2>
<p>This step is optional: All the samples in this Test Drive run out-of-the-box. However, if you want to look at/experiment with the source code in the Flash Builder IDE while running the samples, do the following:</p>
<ol>
<li>Unzip the WEB-INF/flex-src/flex-src.zip to a folder, say {FlexSrc}</li>
<li>In Flash Builder 4, click <strong>File &gt; Import &gt; General &gt; Existing Projects into Workspace. </strong></li>
<li>Specify the above folder <strong>{FlexSrc}</strong>, as the root directory and click finish.<strong></strong></li>
</ol>
<h2>Configuration Walkthrough</h2>
<p><strong>web.xml</strong></p>
<p>In web.xml, the DispatcherServlet is configured to bootstrap the Spring WebApplicationContext as usual. In this simple configuration, all the <strong>/messagebroker</strong> requests are mapped to the DispatcherServlet.<br />
<p><strong>flex-servlet.xml</strong></p>
<p>In flex-servlet.xml, the BlazeDS message broker is configured as a Spring-managed bean using the simple message-broker tag. This bootstraps the BlazeDS message broker. <br />
With the message-broker in place, the Spring beans are configured as usual, and exposed for remote access using the remoting-destination tag. <br />
In this Test Drive, we split the configuration into multiple XML files:</p>
<ol>
<li>The application-specific beans are configured in <strong>spring/app-config.xml</strong> and exposed as remoting destinations in <strong>flex-servlet.xml.</strong></li>
<li>The beans that provide the basic infrastructure for the application (Database access) are configured in <strong>spring/infrastructure-config.xml</strong>. </li>
<li>Security is configured in <strong>spring/security-config.xml</strong>. For the purpose of this introduction, we use a basic authentication provider. </li>
</ol>
<p>In your own web application, you can use a different configuration arrangement, including single-file configuration.</p>
</div>
<h2>Remoting Samples</h2>
<a name="inventory"></a>
<div class="item">
<h3>Spring BlazeDS Integration 101</h3>
<h4>Run the sample:</h4>
<ol>
<li>Click <a href="spring-blazeds-101/index.html">here</a> to run the application.</li>
<li>Click &quot;Get Data&quot;: The DataGrid is populated with data returned by the findAll() method of the ProductDAO Java class. </li>
</ol>
<h4>Code walkthrough:</h4>
<p>Open Main.mxml in the spring-blazeds-101 project to look at the source code of the application.</p>
<p>Open the following files in a text editor to look at the source code for the server side of the application: </p>
<ul>
<li>{context-root}/WEB-INF/flex-servlet.xml</li>
<li>{context-root}/WEB-INF/spring/app-config.xml</li>
<li>org/springframework/flex/samples/product/ProducDAO.java</li>
</ul>
<p>Note that this application uses a simplistic DAO implementation with low level JDBC code and no real abstraction. This was done intentionally to provide a bare-bones example that focuses exclusively on the Spring/BlazeDS Integration plumbing. All the other examples of this Test Drive, use the JdbcTemplate abstraction of the Spring framework to build the data access objects.</p>
<p>Using RemoteObject, you can directly invoke methods of Java objects deployed in your application server, and consume the return value. The return value can be a value of a primitive data type, an object, a collection of objects, an object graph, etc.</p>
<p>Using the Spring BlazeDS integration, Spring beans are exposed using the remoting-destination tag. The productService bean is defined in app-config.xml and is exposed as a remoting destination in flex-servlet.xml.</p>
<p>Java objects returned by server-side methods are deserialized into either dynamic or typed ActionScript objects. This application doesn't have an explicit ActionScript version of the Product Java class. Product objects are therefore deserialized into dynamic objects. In InSync03 below, we start working with strongly typed model objects. </p>
</div>
<br />
<a name="insync"></a>
<div class="item">
<h3>InSync01: Searching Contacts</h3>
<h4>Run the sample:</h4>
<ol>
<li>Click <a href="insync01/index.html">here</a> to run the application.</li>
<li>Click the Search button to retrieve all the contacts in the database.</li>
<li>Enter a few characters in the Search input field before clicking the Search button in order to search by name.</li>
</ol>
<h4>Code walkthrough:</h4>
<p>Open insync01.mxml in the insync01 project to look at the source code of the application.</p>
<p>Open the following files to look at the source code for the server side of the application: </p>
<ul>
<li>flex-servlet.xml</li>
<li>app-config.xml</li>
<li>org/springframework/flex/samples/contact/ContactDAO.java</li>
</ul>
</div>
<br />
<div class="item">
<h3>InSync02: Using the RemoteObject Events</h3>
<h4>Run the sample:</h4>
<p>Click <a href="insync02/index.html">here</a> to run the application.</p>
<h4>Code walkthrough:</h4>
<p>Open insync02.mxml in the insync02 project to look at the source code of the application.</p>
<p>This version is similar to insync01, but demonstrates how to use the ResultEvent and FaultEvent to have a finer control over RemoteObject calls.<br />
</p>
</div>
<br />
<div class="item">
<h3>InSync03: Strong Typing</h3>
<h4>Run the sample:</h4>
<ol>
<li>Click <a href="insync03/index.html">here</a> to run the application.</li>
<li>Click the Search button to retrieve all the contacts in the database.</li>
<li>Enter a few characters in the Search input field before clicking the Search button to search by name.</li>
<li>Select a contact in the DataGrid.</li>
<li>Edit the contact in the Contact form and click &quot;Save&quot; to persist your changes.</li>
</ol>
<h4>Code walkthrough:</h4>
<p>Open insync03.mxml, Contact.as, and ContactForm.mxml in the insync03 project to look at the source code of the application.</p>
<p>In this version, we work with strongly typed contact objects. The Contact.as class is the ActionScript representation of org.springframework.flex.samples.contact.Contact.java. The [RemoteClass(alias=&quot;org.springframework.flex.spring.samples.contact.Contact&quot;)] annotation in Contact.as is used to indicate that instances of Contact.as sent to the server should be deserialized as instances of org.springframework.flex.spring.samples.contact.Contact at the server side, and that similarly, instances of org.springframework.flex.spring.samples.contact.Contact retrieved from the server should be deserialized as instances of Contact.as.<br />
</p>
</div>
<br />
<div class="item">
<h3>InSync04: Opening Multiple Contacts</h3>
<h4>Run the sample:</h4>
<ol>
<li>Click <a href="insync04/index.html">here</a> to run the application.</li>
<li>Click the Search button to retrieve all the contacts in the database.</li>
<li>Enter a few characters in the Search input field before clicking the Search button to search by name.</li>
<li>Double-click a contact in the DataGrid to open it in a separate Tab.</li>
<li>Edit the contact in the Contact form and click &quot;Save&quot; to persist your changes.</li>
</ol>
<h4>Code walkthrough:</h4>
<p>Open insync04.mxml in the insync04 project to look at the source code of the application.<br />
</p>
</div>
<br />
<div class="item">
<h3>InSync05: Adding New Contacts</h3>
<h4>Run the sample:</h4>
<ol>
<li>Click <a href="insync05/index.html">here</a> to run the application.</li>
<li>Click the Search button to retrieve all the contacts in the database.</li>
<li>Click the New Contact button.</li>
<li>Edit the new contact in the Contact form and click &quot;Save&quot; to create the contact.</li>
</ol>
<h4>Code walkthrough:</h4>
<p>Open insync05.mxml and ContactForm.mxml in the insync05 project to look at the source code of the application.</p>
<p>This version enables the user of the application to add contacts. In ContactForm, we remotely invoke the create() method of ContactDAO when dealing with a new contact, and the update() method when updating an existing contact.<br />
</p>
</div>
<br />
<div class="item">
<h3>InSync06: Adding Event Notification for &quot;Loosely Coupled&quot; UI Synchronization</h3>
<h4>Run the sample:</h4>
<ol>
<li>Click <a href="insync06/index.html">here</a> to run the application.</li>
<li>Click the Search button to retrieve all the contacts in the database.</li>
<li>Enter a few characters in the Search input field before clicking the Search button to search by name.</li>
<li>Double-click a contact in the DataGrid to open it in a separate Tab.</li>
<li>Modify the first name or last name of the contact and click &quot;Save&quot;. Notice that the DataGrid is updated to reflect your changes.</li>
<li>Add a new contact and click &quot;Save&quot; to create the contact. Notice that the contact appears in the DataGrid.</li>
<li>Delete a contact and notice that the contact is removed from the DataGrid.</li>
</ol>
<h4>Code walkthrough:</h4>
<p>Open insync06.mxml, ContactForm.mxml, and ContactEvent.as in the insync06 project to look at the source code of the application.</p>
<p>In this version, ContactForm dispatches events when a contact has been created, updated, or deleted. Other components of the application can register as listeners to these events to perform a specific task when a contact is created, updated or deleted. In this case, the main application registers as a listener to these events and refreshes the contact DataGrid to make sure it reflects the changes made in ContactForm.<br />
</p>
</div>
<br />
<a name="company"></a>
<div class="item">
<h3>Company Manager</h3>
<h4>Run the sample:</h4>
<ol>
<li>Click <a href="companymgr/index.html">here</a> to run the application.</li>
<li>Click the Search button to retrieve all the contacts in the database.</li>
<li>Enter a few characters in the Search input field before clicking the Search button to search by name.</li>
</ol>
<h4>Code walkthrough:</h4>
<p>Open companymgr.mxml, Company.as, Industry.as, and CompanyForm.mxml in the companymgr project to look at the source code of the application.</p>
<p>Open the following files to look at the source code for the server side of the application: </p>
<ul>
<li>org/springframework/flex/spring/samples/company/CompanyDAO.java</li>
<li>org/springframework/flex/spring/samples/company/IndustryDAO.java</li>
</ul>
<p>The CompanyDAO and IndustryDAO beans are not defined in app-config.xml nor exposed in flex-servlet.xml. They are configured using annotations (<code>@Service</code>,
<code>@RemotingDestination</code>, <code>@Autowired</code>, <code>@RemotingInclude</code>, and <code>@RemotingExclude</code>) in the class definition. This application is similar to inSync, but demonstrates object associations: the Company class has a property of type Industry.<br />
</p>
</div>
<br />
<h2>Messaging Samples</h2>
<a name="chat"></a>
<div class="item">
<h3>Chat</h3>
<h4>Run the sample:</h4>
<ol>
<li>Click <a href="chat/index.html">here</a> to run the application.</li>
<li>Access the same URL in another browser window to open a second instance of the chat application.</li>
<li>Type a message in one of the chat clients and click &quot;Send&quot;: the message appears in the two chat clients.</li>
</ol>
<h4>Code walkthrough:</h4>
<p>Open chat.mxml in the chat project to look at the source code of the application. The Message Service manages a set of destinations that Flex clients can publish and subscribe to. Flex provides two components, Producer and Consumer, that you use to publish and subscribe to a destination. To subscribe to a destination, you use the <code>subscribe()</code> method of the Consumer class. When a message is published to a destination that you subscribed to, the <code>message</code> event is triggered on the Consumer.</p>
<p>Open flex-servlet.xml to look at the message service configuration. The message service is configured using <code>&lt;flex:message-service /&gt;</code> inside <code>&lt;flex:message-broker /&gt;</code>. The &quot;chat&quot; destination is configured using <code>&lt;flex:message-destination id=&quot;chat&quot; /&gt;</code></p>
</div>
<br />
<a name="simplepush"></a>
<div class="item">
<h3>Simple Data Push</h3>
<h4>Run the sample</h4>
<p>This example demonstrates how to use the message service to push data from the server to the client. At the server-side, a Java component publishes simulated real time values to a message destination. The Flex client subscribes to that destination and displays the values in real time. </p>
<ol>
<li>To start the feed at the server-side, run the <a href="feedstarter/index.html">Feed Starter application</a> and start the "Simple Feed".</li>
<li>Click <a href="simplepush/index.html">here</a> to run the client application</a>.</li>
<li>Click the Subscribe button. Pushed values appear in the text field. You can click the Unsubscribe button to unsubscribe from the destination. </li>
<li>To stop the feed when you are done experimenting with the application, access the <a href="feedstarter/index.html">Feed Starter application</a> and stop the "Simple Feed".</li>
</ol>
<h4>Code walk through</h4>
<p>Open simplepush.mxml in the simplepush project to look at the source code of the application.</p>
<p>Open the following files to look at the source code for the server side of the application: </p>
<ul>
<li>org/springframework/flex/spring/samples/simplefeed/SimpleFeed.Java</li>
<li>flex-servlet.xml</li>
</ul>
<p>In SimpleFeed.java, the MessageTemplate class is used to publish messages to the "simple-feed" destination.</p>
In flex-servlet.xml, the &quot;simple-feed&quot; destination is configured using <code>&lt;flex:message-destination id=&quot;simple-feed&quot; /&gt;</code></div>
<br />
<a name="traderdesktop"></a>
<div class="item">
<h3>Traderdesktop</h3>
<h4>Run the sample</h4>
<p>Traderdesktop is a more sophisticated data push example showing how to use subtopics to selectively subscribe to specific messages. In this case, the user can subscribe to updates for specific stocks only. At the server side, a Java component publishes simulated market data to a messaging destination.</p>
<ol>
<li>To start the feed at the server-side, run the <a href="feedstarter/index.html">Feed Starter application</a> and start the "Market Feed".</li>
<li>Click <a href="traderdesktop/index.html">here</a> to run the client application</a>.</li>
<li>To stop the feed when you are done experimenting with the application, access the <a href="feedstarter/index.html">Feed Starter application</a> and stop the "Market Feed".</li>
</ol>
<h4>Code walk through</h4>
<p>Open traderdesktop.mxml in the traderdesktop project to look at the source code of the application.</p>
<p>Open the following files to look at the source code for the server side of the application: </p>
<ul>
<li>org/springframework/flex/spring/samples/marketfeed/MarketFeed.Java</li>
<li>flex-servlet.xml. The market-feed destination is configured using <code>&lt;flex:message-destination id=&quot;market-feed&quot; allow-subtopics=&quot;true&quot; subtopic-separator=&quot;.&quot; /&gt;</code></li>
</ul>
</div>
<br />
<a name="collaboration"></a>
<div class="item">
<h3>Collaboration</h3>
<h4>Run the sample:</h4>
<ol>
<li>Click <a href="collaboration/index.html">here</a> to run the application.</li>
<li>Access the same URL in another browser window to open a second instance of the chat application.</li>
<li>Enter some data in one browser and notice that the data appears in the other browser as well.</li>
<li>Select another tab in the accordion in one broswer, and notice that the other client's user interface is synchronized accordingly.</li>
</ol>
<h4>Code walkthrough:</h4>
<p>Open collaboration.mxml in the collaboration project to look at the source code of the application.</p>
</div>
<br />
<h2>Security Samples</h2>
<a name="security"></a>
<div class="item">
<h3>Security Integration 101</h3>
<h4>Run the sample:</h4>
<ol>
<li>Click <a href="spring-blazeds-security-101/index.html">here</a> to run the application.</li>
<li>Click &quot;Get Data&quot; without logging in first: you get an &quot;Access Denied&quot; exception.</li>
<li>Log in (use UserId: john / Password: john), and click &quot;Get Data&quot; again: you should now get the data.</li>
<li>Click &quot;Logout&quot; and &quot;Get Data&quot; again: you get the &quot;Access Denied&quot; exception again.</li>
<li>If you are already authenticated, you don't have to use the ChannelSet login. For example, access <a href="login.jsp">login.jsp</a>, and logon using john / john. <a href="spring-blazeds-security-101/index.html">Come back to the application</a> and click Get Data without logging in inside the application: you should get the data.</li>
</ol>
<h4>Code walkthrough:</h4>
<p>Open Main.mxml in the spring-blazeds-security-101 project to look at the source code of the application.</p>
<p>Open the following files in a text editor to look at the the server side configuration: </p>
<ul>
<li>app-config.xml</li>
<li>security-config.xml</li>
</ul>
<p>In app-config.xml, note that the &quot;find*&quot; methods of securedProductService are protected: they can only be accessed by members of ROLE_USER. A basic authentication provider is defined in security-config.xml.<br />
</p>
</div>
<br />
</body>
</html>