Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Taking a Java-Based App Offline Using Flash Builder, LiveCycle Data Services : Page 2

This article builds a sample application that can seamlessly transition between online and offline connectivity status.


advertisement

The auto-sync-enabled option is helpful if you want to have the server push changes made on the server side to the client. Be careful with this option, however, because it can generate a lot of network traffic and might have a significant performance impact. Depending on the number of concurrent users, an increase in the server resource specifications might be warranted.

 

Note: The one-to-many association from the Hibernate mapping is present in the project destination definition.



 

Just to get things rolling, start the HSQLDB database using the supplied startup script, copy the class files and hibernate.cfg.xml in the WEB-INF/classes directory, and add the two destinations to the LCDS sample directory (typically, {lcds}/tomcat/webapps/lcds-samples/WEB-INF/flex).

 

Front-end Code

 

On the Flash Builder side, you can bring the model object described earlier over automatically using the LCDS plug-in for Flash Builder 4's new capabilities. When creating the front-end module, perform the following steps:

    1. On the Create a Flex project wizard page, select J2EE as the application server type, select Use remote object access service, and then select the LiveCycle Data Services ES option, as shown in Figure 3.

     

     

    Figure 3. Creating the front-end module.

     

    2. On the Configure J2EE Server wizard page, configure the LCDS destinations, as shown in Figure 4.

     

     

    Figure 4. Set the default location for Tomcat.

     

    3. To trigger the code-generation feature, click Data > Connect to LCDS, then choose your previously defined destination, projectDestination, as shown in Figure 5.

     

     

    Figure 5. Select your project destination.

     

    4. Click Finish.

Many classes are automatically created-for example, Project.as, Comment.as, ProjectService.as, and _Super_Project.as. All the generated code is nicely enclosed in _Super_Project.as, allowing you to edit and eventually override methods in ProjectService.as. In fact, you need to override the fill function to take into account the earlier JPA @NamedQuery declaration:





override public function fill(arg0 : ArrayCollection):AsyncToken
{
	var ac:ArrayCollection = new ArrayCollection(); 
	var token:AsyncToken= _serviceControl.fill(ac, 'project.all', arg0);
	token.resultAC = ac;
	return token;          
}

Again, take a simplistic approach: a minimal user interface (UI) consisting of a top menu bar with the option of opening existing projects, exiting the application, and the classic Help > About. A status message at the bottom indicates whether network connectivity is either online or offline. When a project is opened, a grid appears containing Comment objects, editable inline when you click a row, as shown in Figure 6.

 

 

Figure 6.

The simple UI

 

These are basically two data grids. Editing comments in the main window triggers a save operation when you edit a row, and the Open Project pop-up window displays a list of projects to choose from:





<mx:Canvas id="container" left="12" right="12" top="12" bottom="12"> 
<mx:DataGrid id="list" left="0" right="0" top="15" bottom="25" doubleClickEnabled="true"
dataProvider="{comments}" editable="true" x="9" y="24" itemEditEnd="saveComment(event)"> <mx:columns>
<mx:DataGridColumn dataField="id" headerText="Id" width="35"/>
<mx:DataGridColumn dataField="subject" headerText="Subject"/>
<mx:DataGridColumn dataField="rating" headerText="Rating"/>
<mx:DataGridColumn dataField="comment" headerText="Comments"/>
</mx:columns> </mx:DataGrid> </mx:Canvas> <mx:DataGrid id="projectList" height="220" width="320" doubleClickEnabled="true" creationComplete="retrieveProjects
()" dataProvider="{projectsFillResult.lastResult}" doubleClick="openProject(projectList.selectedItem)"> <mx:columns> <mx:DataGridColumn dataField="id" headerText="Id" width="35"/> <mx:DataGridColumn dataField="name" headerText="Project Name"/> </mx:columns> </mx:DataGrid>

Be sure to set a cache identifier when the application initializes by attributing a unique value to the ds.cacheID property on the data source.

 

The conflictHandler should implement a conflict resolution that is presented to the user. For example, if two different users have edited the text of the same comment, a differential approach should be presented rather than simply displaying the whole text, so that a decision looks obvious to the user.

 

Taking the application offline and bringing it back online is done automatically. You implement the functionality by opening a SocketMonitor and adding a handler intended to listen for the network status change event:





private var monitor:SocketMonitor;
monitor = new SocketMonitor('localhost',2037); 
monitor.pollInterval = 30;
monitor.addEventListener(StatusEvent.STATUS, statusChangeHandler);  
monitor.start();

Many times in an enterprise, listening for network connectivity on a port where the application server runs is sometimes not enough: A single server might run multiple applications. A safer bet is to monitor to an endpoint that has the capability to detect whether the application in question is running or in maintenance mode or whether any other event might derail reliable access. The statusChangeHandler shows the network status, propagates any changes to the server, or populates data from the cache if the application is in offline mode:




private function statusChangeHandler(event:StatusEvent):void
{
	if (monitor.available)
	{
		statusLabel.text = statusImage.toolTip = 'Online';
		statusImage.source = onlineIcon;
		if (ds.connected)
		{
			propagateChanges();
		}
		else
		{
			connect();
		}
	}
	else
	{
		statusLabel.text = statusImage.toolTip = 'Offline';
		statusImage.source = offlineIcon;
		if (noData())
		{
			retrieveProjects();
		}
	}
}

To test the offline scenario, perform these steps:

    1. Shut down the server after opening a project. The status will change to offline along with the red icon.
    2. Edit one of the comments.
    3. Wait for the server to bounce back.

A message will pop up stating that the changes were propagated from the local cache back to the live server. If the application is started in debug mode, trace messages describe how the application acts depending on the network status.

 

Conclusion

 

In this article, you configured an application to detect its network connectivity transparently and automatically synchronize with the main server using LCDS. Furthermore, online clients can have the updated data saved by other clients pushed directly to their application, resulting in less frequent conflicts. You can mitigate conflicts automatically at the field level (or through a custom Java solution-using reflection comes to mind) or manually either when the user has to assume the final decision or when an automatic solution cannot be strategized.

 

The main challenges you'll face are mainly related to synchronization. Nevertheless, these challenges are better approached early on, when architecting such an application, rather than later, when technical decisions can result in bad user experience or limitations. Having a seamless transition between online and offline modes is a key differentiator to other solutions, where users would have to bring the data offline to edit it.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap