There are many benefits to taking an enterprise application offline, especially in today’s world, when everyone is seemingly connected to the Internet. Enterprise users often find themselves outside their corporate firewall. But rather than dealing with a slow-to-respond IT department and less-than-straightforward security concerns, they want their applications ready to deal with such situations. In the case of a complex application, a subset of the application’s functionality should be available if the application’s main server is not reachable for one reason or another.
The article builds a sample application that can seamlessly transition between online and offline connectivity status. While offline, users will still be able to use the application until connectivity is restored and the changes can be pushed back to the server.
Enterprise Considerations
Identifying the offline use cases is of course a core business concern. This article exemplifies a fairly simple use case in which an application needs to be taken offline and users should be able to comment, annotate, and rate field results for an existing project. This seems like a minimal use case for offline, but you soon realize that taking a feature offline presents many challenges, such as how to handle basic create, read, update, delete (CRUD) operations; how to deal with existing object relationships and synchronization issues caused by concurrent access to the same data; conflict resolution; and the list does not end there.
Improving a software product’s usability should be a major factor here, so features like detection of online or offline status and seamlessly switching between the two, allowing the server to push updated data back to online clients, would constitute some nice touches to the application, consequently making it less prone to concurrent conflicts. In addition, such features prevent users from taking extra actions like manually starting synchronizations (the now-inactive Google Gears project comes to mind).
Glancing at the Adobe documentation, you quickly come to the realization that running the application in a browser (compiled as an Adobe Flash plug-in) would give the application little space for the local cache, which leaves you with one choice: running the offline application on top of the Adobe AIR runtime (which uses an embedded SQL-based database). One nice way of dealing with adaptation is to automatically redirect the user to the Adobe AIR application when the network status changes to offline and, if the runtime is not installed, informing the user that offline capabilities are not available and presenting the steps required perform the installation. You can address some of these challenges immediately by properly modeling your Document Object Model (DOM) and structuring the application with reusable components and application programming interfaces (APIs).
The Environment
Here are the minimum requirements for setting up this project:
* Java 1.5.
* Apache Maven 2.
* Apache Tomcat 6 (or any other modern servlet container). In the context of this article, you’re actually going to use the embedded version of Tomcat that ships with LCDS samples containing all the other dependent libraries and a memory-based HyperSQL (HSQL) database ready for use.
* The Eclipse integrated development environment (IDE), as Adobe Flash Builder is also built as an Eclipse plug-in.
* Adobe Flash Builder 4 beta 2, along with the Adobe Data Services 3 plug-in, as you are going to use the Fiber’s code-generation capabilities. You manage integrating the two components and breaking the different online-offline states in the application life cycle with LCDS. Figure 1 shows the environment structure.
* The back end consists of a Java web application based on Adobe LiveCycle Data Services (LCDS), with simple plain old Java objects (POJOs) persisted using Hibernate. For this application, you need:
* The front end is built using Flash Builder. For this application, you need:
Figure 1. The environment back end and front end structure
Back-end Code
Set up a simplistic back-end service consisting of a project model containing comments and ratings objects. You’re going to use Hibernate for persisting objects into a database; for simplicity’s sake, you’ll annotate the POJOs using Java Persistence Architecture API (JPA) annotations that LCDS will make good use of later on.
The simplistic plain old Java domain objects are Project, which has names and a list of enclosing Comment objects. The Comment objects have subject, comment, and rating fields, each with a numeric value:
@[email protected](name="projects")@NamedQueries({ @NamedQuery(name="project.all",query="from Project"), @NamedQuery(name="project.byId",query="from Project p where p.id = :id")})public class Project {@Id @[email protected](name="projectId")private Long id;@Column(name="name")private String name;@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)private List<Comment> comments;…public class Comment {@Id @[email protected](name="commentId")private Long id;@Column(name="subject")private String subject; @Column(name="comment")private String comment;@Column(name="rating")private int rating;
You’ve probably noticed the one-to-many association between the Project and Comment objects, having Hibernate cascading and lazy fetching. I also omitted the accessor methods for these POJOs; but by using Eclipse’s built-in Generate Getters and Setters feature, you can easily generate them automatically, as shown in Figure 2.
Figure 2. Eclipse can automatically generate getter and setter methods.
Reference these getters and setters in your Hibernate mapping file (hibernate.cfg.xml):
For convenience, I generated the database schema using the hibernate3-maven-plugin, which has the smarts to create it using the previous JPA annotations. A simple Maven package command creates a file located at target/hibernate3/sql/schema.ddl by using the following Maven declaration in the build phase:
And this is how the schema looks after feeding it into the LCDS HSQLDB utility:
CREATE MEMORY TABLE COMMENTS(COMMENTID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY,COMMENT VARCHAR(255),RATING INTEGER,SUBJECT VARCHAR(255)) CREATE MEMORY TABLE PROJECTS(PROJECTID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 1) NOT NULL PRIMARY KEY,NAME VARCHAR(255)) CREATE MEMORY TABLE PROJECTS_COMMENTS(PROJECTS_PROJECTID INTEGER NOT NULL,COMMENTS_COMMENTID INTEGER NOT NULL,CONSTRAINT SYS_CT_50 UNIQUE(COMMENTS_COMMENTID),CONSTRAINT FK62BEE019928A30BE FOREIGN KEY(COMMENTS_COMMENTID) REFERENCES COMMENTS(COMMENTID),CONSTRAINT FK62BEE019CE90EEB8 FOREIGN KEY(PROJECTS_PROJECTID) REFERENCES PROJECTS(PROJECTID))
To avoid creating separate assemblers for domain objects, use the LCDS-standard HibernateAnnotationsAssembler, because your POJOs already have Hibernate annotations. (You might want to implement the assembler interface if you need a custom solution or if you are architecting an application that uses data transfer objects that are different from your domain model, usually to address performance or scalability issues.) Here is the LCDS configuration file containing the destinations directives using the HibernateAnnotationsAssembler (data-management-config.xml):
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:
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.
General Motors (GM) recently announced its entry into the Eclipse Foundation. The Eclipse Foundation is a prominent open-source software foundation. In addition, GMC announced its contribution of “uProtocol” to facilitate
What is metadata? Well, It’s an odd concept to wrap your head around. Metadata is essentially the secondary layer of data that tracks details about the “regular” data. The regular
The earliest cell phones included boxy designs full of buttons and antennas, and they only made calls. Needless to say, we’ve come a long way from those classic brick phones
When it comes to programming, a good mechanical keyboard can make all the difference. Naturally, you would want one of the best mechanical keyboards for programmers. But with so many
In the age of digital transformation, the internet has become a ubiquitous part of our lives. From socializing, shopping, and learning to more sensitive activities such as banking and healthcare,
The world of software development is changing drastically with the introduction of Artificial Intelligence and Machine Learning technologies. In the past, software developers were in charge of the entire development
Cybercriminals constantly adapt their strategies, developing newer, more powerful, and intelligent ways to attack your network. Since security professionals must innovate as well, more conventional endpoint detection solutions have evolved
Artificial intelligence – commonly known as AI – means a form of technology with multiple uses. As a result, it has become extremely valuable to a number of businesses across
Artificial intelligence (AI) has been transforming industries and revolutionizing business operations. AI’s potential to enhance efficiency and productivity has become crucial to many businesses. As we move into 2023, several
Creating a website is not easy, but protecting your website is equally important. Implementing copyright laws ensures that the substance of your website remains secure and sheltered. Copyrighting your website
One of the biggest trends of the 21st century is the massive surge in analytics. Analytics is the process of utilizing data to drive future decision-making. With so much of
Kubernetes from Google is one of the most popular open-source and free container management solutions made to make managing and deploying applications easier. It has a solid architecture that makes