PharmaSales Application
Adobe AIR offers a data synchronization solution based on Data Management Services
for those who own licenses of LiveCycle Data Service ES 2.6. This solution is described
at the InsideRIA blog at http://tinyurl.com/6fa254.
But application developers who use an open source BlazeDS don’t have any generic
way of setting such data synchronization process. This section offers a smart compo-
nent called 
OfflineDataCollection
that’s based on the 
DataCollection
object described
in Chapter 6. This component will take care of the data synchronization for you.
OfflineDataCollection
is part of the Clear Toolkit’s component library clear.swc. You’ll
see how to use it while reviewing a sample PharmaSales application that supports the
sales force of a fictitious pharmaceutical company called Acme Pharm.
This application will have two types of users:
• A salesperson visiting doctors’ offices trying to persuade doctors to use the com-
pany’s latest drug, called Xyzin
• The Acme Pharm dispatcher who schedules daily routes for each salesperson
The corporate database schema supporting PharmaSales will look like Figure 9-11 (for
simplicity, there are no relationships between tables).
Figure 9-11. The PharmaSales database model
Every morning a salesman starts the PharmaSales application, which connects to the
corporate database (MySQL) and automatically loads his visit schedule for the day from
the table 
visit_schedule
. At this point, the data is being loaded into a local database
(SQLite) that exists on salesman’s laptop. The database will be automatically created
on the first run of the application. The salesman’s laptop has to be connected to the
Internet.
PharmaSales Application | 461
Pdf file thumbnail preview - Draw thumbnail images for PDF in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Support Thumbnail Generation with Various Options for Quick PDF Navigation
create pdf thumbnail image; view pdf thumbnails in
Pdf file thumbnail preview - VB.NET PDF Thumbnail Create SDK: Draw thumbnail images for PDF in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
Support Thumbnail Generation with Various Options for Quick PDF Navigation
generate pdf thumbnail c#; create pdf thumbnail
While visiting a particular doctor’s office, the salesman uses the PharmaSales applica-
tion to take notes about the visit. In this case, the salesman’s laptop is disconnected
from the Internet and all the records about visitations are saved in the local database
only. As soon as Sal, the salesman, starts this application in connected mode, the local
data with the latest visit information should be automatically synchronized with the
corporate database.
To help the salesman in finding doctors’ offices on the road, the application will be
integrated with Google Maps.
Installing PharmaSales
For testing the PharmaSales application, you’ll need the following software installed:
• Java development kit version 1.5 or higher
• Eclipse JEE 3.3 or higher with the Flash Builder 3 plug-in
• Apache Tomcat Servlet container
• MySQL Server 5 DBMS
In  Eclipse,  import  the  PharmaSales  application;  it  comes  as  two  projects:
air.offline.demo, which can be used in connected or disconnected mode by a salesper-
son, and air.offline.demo.web, which is used by the Acme Pharm dispatcher in con-
nected mode only.
If after importing the project you see an Unbound JDK error, go to the
properties of the air.offline.demo.web project, select the option Java
Build Path → Libraries, remove unbound JDK, select Add Library and
point at the directory where your JDK is installed, for example C:\Pro-
gram Files\Java\jdk1.6.0_12.
To simplify the installation, create a C:\workspace soft link pointing at your Eclipse
workspace directory as described in the section “Preparing for Team Work” in Chap-
ter 4. For example, if your workspace is located at D:\myworkspace, the junction utility
command will look like this:
junction c:\workspace d:\myworkspace
The PharmaSales Application for Dispatchers
The air.offline.demo.web project has a folder db that contains the file database.sql,
which is a DDL script for creation of sample pharma database in MySQL Server.
Download the MySQL GUI tools, create the database and the user dba with the pass-
word sql. Run these scripts and grant all the privileges to the dba user.
462 | Chapter 9: Working with Adobe AIR
How to C#: Preview Document Content Using XDoc.Word
RasterEdge XDoc.Word provide you with APIs to get a thumbnail bitmap of the first page in the word document file. You can be able to get a preview of this word
can't view pdf thumbnails; show pdf thumbnails
How to C#: Preview Document Content Using XDoc.PowerPoint
XDoc.PowerPoint provide you with APIs to get a thumbnail bitmap of the first page in the PowerPoint document file. You can be able to get a preview of this
pdf thumbnails in; show pdf thumbnail in
The easiest way to create this sample database is to open a command window and run
the mysql utility entering the right user ID and password for the user root. The following
line is written for the user root with the password root, assuming that the file data-
base.sql is located in the same directory as MySQL:
mysql -u root -p root < database.sql
The air.offline.demo.web project also has the file pharma.properties in the .settings di-
rectory with the database connectivity parameters. If you created the pharma database
under a different user ID than dba, modify the user and the password there accordingly.
If you didn’t run the Café Townsend (the CDB version) example from Chapter 1, create
a new server in the Eclipse JEE IDE by selecting File → New Server and point it to your
Tomcat installation. Add the project to the Tomcat server in Eclipse IDE and start the
server.
If you are not willing to install and run this application on your com-
puter, you can instead watch a screencast that shows the process of
configuring and running the PharmaSales application, which is available
at http://www.myflex.org/demos/PharmaAir/PharmaAir.html.
The Acme Pharm’s dispatcher is the only user of the application VisitSchedules.mxml
(the Flash Builder’s project air.offline.demo.web). Its main window allows scheduling
new visits and viewing existing visits for each salesperson (Figure 9-12).
Figure 9-12. Viewing visit schedules
PharmaSales Application | 463
How to C#: Set Image Thumbnail in C#.NET
PDF to text, C#.NET convert PDF to images, C#.NET PDF file & pages VB.NET How-to, VB.NET PDF, VB.NET Word, VB.NET Excel How to C#: Set Image Thumbnail in C#.NET.
create thumbnail from pdf; show pdf thumbnails in
How to C#: Preview Document Content Using XDoc.excel
RasterEdge XDoc.Excel provide you with APIs to get a thumbnail bitmap of the first page in the Excel document file. You can be able to get a preview of this
show pdf thumbnail in html; create thumbnail jpg from pdf
Click the Add button to open another view and schedule a new visit for any salesperson
(Figure 9-13).
Figure 9-13. Scheduling a new visit
Scheduled  visits  are  saved  in  the  central  MySQL  Server  database  in  the  table
visit_schedule
, and each time the salesperson logs on to the system from her laptop,
her visits are automatically downloaded to the local SQLite DBMS.
We won’t review all the code of this application; it was generated by Clear Data Builder
similarly to Café Townsend, as described in Chapter 1. CDB has generated this appli-
cation based on the abstract Java class 
VisitSchedule
shown in Example 9-8.
Example 9-8. VisitSchedule.java
package com.farata.demo.pharmasales;
import java.util.List;
/**
* @daoflex:webservice
*   pool=jdbc/pharma
*/
public abstract class VisitSchedule {
/**
* @daoflex:sql
 pool=jdbc/pharma
 sql=::  SELECT
  visit_schedule.id as id,
  visit_schedule.salesman_id as salesman_id,
  visit_schedule.address_id as address_id,
  visit_schedule.scheduled_date as scheduled_date,
  CONCAT(salesmen.fname, " ", salesmen.lname) as fullname,
  CONCAT(addresses.addr_line_1, ", ", addresses.city, ", ",
addresses.state) as fulladdress,
  visits.comments as comments
464 | Chapter 9: Working with Adobe AIR
How to C#: Generate Thumbnail for Word
Images. Convert Word to ODT. Convert PDF to Word. a Word File. File: Merge Word Files. File: Split Word Text Search. Insert Image. Thumbnail Create. Thumbnail Create
create pdf thumbnail image; html display pdf thumbnail
How to C#: Generate Thumbnail for PowerPoint
Document. Conversion. Convert PowerPoint to PDF. Convert PowerPoint File: Merge PowerPoint Files. File: Split PowerPoint Text Search. Insert Image. Thumbnail Create
enable pdf thumbnail preview; pdf thumbnail preview
  FROM (visit_schedule LEFT JOIN visits ON visit_schedule.id =
visits.visit_schedule_id), salesmen, addresses
  WHERE
  visit_schedule.salesman_id = salesmen.id AND
  visit_schedule.address_id = addresses.id
*
 ::
 transferType=VisitScheduleDTO[]
 keyColumns=id, salesman_id, address_id, scheduled_date
 updateTable=visit_schedule
*/
public abstract List getVisitSchedules();
/**
* @daoflex:sql
 pool=jdbc/pharma
 sql=::  SELECT
  visit_schedule.id as id,
  visit_schedule.salesman_id as salesman_id,
  visit_schedule.address_id as address_id,
  visit_schedule.scheduled_date as scheduled_date,
  CONCAT(salesmen.fname, " ", salesmen.lname) as fullname,
  CONCAT(addresses.addr_line_1, ", ", addresses.city, ", ",
addresses.state) as fulladdress,
  visits.comments as comments
  FROM (visit_schedule LEFT JOIN visits ON visit_schedule.id =
visits.visit_schedule_id), salesmen, addresses
  WHERE
  visit_schedule.salesman_id = salesmen.id AND
  visit_schedule.address_id = addresses.id AND
  CONCAT(salesmen.fname, " ", salesmen.lname)=:fullName
 ::
 transferType=VisitScheduleDTO[]
 keyColumns=salesman_id, address_id, scheduled_date
 updateTable=visit_schedule
*/
public abstract List getVisitSchedulesBySalesman(String fullName);
}
The generated Java code that implements the methods declared in the abstract class in
the example is located in the project air.offline.demo.web in the Java file Resources
\Libraries\Web App Libraries\services-generated.jar. You need to open the Eclipse Java
perspective to see this file.
The salesman and address drop-downs were populated using resources described in
Chapter  6.  AddressComboResource.mxml  (Example  9-9)  populates  the  address
drop-down.
Example 9-9. ComboBoxResource.mxml
<?xml version="1.0" encoding="utf-8"?>
<resources:ComboBoxResource
xmlns:resources="com.farata.resources.*"
PharmaSales Application | 465
C# Image: View & Operate Web Page Using .NET Doc Image Web Viewer
Support multiple document and image formats, like PDF and TIFF; the page order of source document file using mouse dragging in thumbnail preview section;
show pdf thumbnails; show pdf thumbnail in html
How to C#: Overview of Using XDoc.PowerPoint
See this C# guide to learn how to use RasterEdge PowerPoint SDK for .NET to perform quick file navigation. You may easily generate thumbnail image from
create thumbnails from pdf files; pdf thumbnail viewer
width="240"
dropdownWidth="240"
destination="com.farata.demo.pharmasales.Address"
keyField="id"
labelField="fulladdress"
autoFill="true"
method="getAddressesCombo"
>
</resources:ComboBoxResource>
The component SalesmanComboResource.mxml (Example 9-10) takes care of the sales-
man drop-down.
Example 9-10. SalesmanComboBoxResource.mxml
<?xml version="1.0" encoding="utf-8"?>
<resources:ComboBoxResource
xmlns:resources="com.farata.resources.*"
width="240"
dropdownWidth="240"
destination="com.farata.demo.pharmasales.Salesman"
keyField="id"
labelField="fullname"
autoFill="true"
method="getSalesmenCombo"
>
</resources:ComboBoxResource>
Now you’re ready to get into the nitty-gritty details of the project air.offline.demo, which
is used by salespeople and contains the code for monitoring network connectivity, data
synchronization, and integration with Google Maps.
The PharmaSales Application for Salespeople
The PharmaSales application starts with a logon screen (Figure 9-14) that requires the
user to enter a valid full name to retrieve the schedule for that person (the password is
irrelevant here).
Just to double-check that the newly inserted schedule gets downloaded to the client’s
computer, log on as a salesperson who has scheduled visits.
Detecting Network Availability
Note the two round indicators at the bottom of the logon screen that show both the
network and the application server statuses. There are two reasons why an AIR appli-
cation might not be able to connect to its server-side components: either there is no
connection to the network or the application server doesn’t respond. Take a look at
how an AIR application can detect whether the network and a URL resource are
available.
466 | Chapter 9: Working with Adobe AIR
How to C#: Overview of Using XDoc.Excel
See this C# guide to learn how to use RasterEdge Excel SDK for .NET to perform quick file navigation. You may easily generate thumbnail image from Excel.
create thumbnail from pdf; pdf thumbnail generator online
How to C#: Overview of Using XDoc.Word
C# users how to: create a new Word file and load Word from pdf; merge, append can be drawn and added to a specific location on Word file page. Create Thumbnail.
.pdf printing in thumbnail size; thumbnail view in for pdf files
Any  AIR  application  has  access  to  a  global  object  called
flash.desktop.NativeApplication
. This object has a number of useful properties and
methods that can give you runtime access to the application descriptor, provide infor-
mation about the number of the opened windows, and also provide other application-
wide information.
You  may want  to  get  familiar  with  yet another useful  class  called
flash.system.System
. For one thing, this class has a method 
gc()
that
forces the garbage collector to kick in to avoid memory leaks in your
AIR application.
To catch a change in the network connectivity, your application should check the
NativeApplication
’s property 
nativeApplication
, which points to an object dispatch-
ing events when the network status changes. Your application can almost immediately
detect a change in the connectivity by listening to the 
Event.NETWORK_CHANGE
event as
shown here:
flash.desktop.NativeApplication.nativeApplication.addEventListener(
Event.NETWORK_CHANGE, onNetworkChange);
Figure 9-14. The PharmaSales logon screen
PharmaSales Application | 467
Unfortunately, this event may be triggered with a 10- to 15-second delay after the net-
work status changes, and it does not bear any specific information about the current
status of the network. This means that after receiving this event, you still need to test
the availability of a specific network resource that your application is interested in.
The PharmaSales application uses Google Maps to help salespeople find
the doctors’ offices they need to visit. Hence if the network is not avail-
able, the application would lose the ability to work with maps.goo-
gle.com and will have to switch to Plan B, discussed later in the section
“Integrating with Google Maps” on page 486.
If you check the library path of a Flash Builder AIR project, you’ll find there a library
servicemonitor.swc, which includes 
SocketMonitor
and 
URLMonitor
classes. These classes
can monitor availability of a specific socket or URL resource.
You can start monitoring the status of a specific HTTP-based resource by calling
URLMonitor.start()
and periodically checking the property 
URLMonitor.available
.
Example 9-11 is the complete code of the NetworkStatus.mxml component, which
monitors both the status of the network (http://maps.google.com) and the Pharma-
Sales application server and displays either a red or green light depending on the health
of the corresponding resource.
Example 9-11. Monitoring network status: NetworkStatus.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:ControlBar xmlns:mx="http://www.adobe.com/2006/mxml" horizontalAlign="left"
width="100%" creationComplete="onCreationComplete()" height="55">
<mx:Canvas width="200" height="55">
<mx:Label text="Server status:"/>
<mx:Image id="serverStatusIcon" x="125" source="{serverConnected ?
'assets/connected.gif' : 'assets/disconnected.gif'}"/>
<mx:Label text="Google maps status: " y="26"/>
<mx:Image id="googleMapsStatusIcon" x="125" y="26"
source="{googleMapsConnected ? 'assets/connected.gif' :
'assets/disconnected.gif'}"/>
</mx:Canvas>
<mx:Script>
<![CDATA[
import air.net.URLMonitor;
import mx.messaging.config.ServerConfig;
//Monitor connection status every second
private static const TIMER_INTERVAL:int=1000;
private static var _googleMapsURLMonitor:URLMonitor;
private static var _serverURLMonitor:URLMonitor;
public function get googleMapsConnected():Boolean{
return _googleMapsURLMonitor && _googleMapsURLMonitor.available;
}
468 | Chapter 9: Working with Adobe AIR
public function get serverConnected():Boolean{
return _serverURLMonitor && _serverURLMonitor.available;
}
public function onCreationComplete():void{
if (_googleMapsURLMonitor == null){
initGoogleMapsURLMonitor();
}
_googleMapsURLMonitor.addEventListener(StatusEvent.STATUS,
showGoogleMapsStatus);
if (_serverURLMonitor == null){
initServerURLMonitor();
}
_serverURLMonitor.addEventListener(StatusEvent.STATUS,
showServerStatus);
}
private function initGoogleMapsURLMonitor():void{
var request:URLRequest=new
URLRequest("http://maps.google.com/");
request.method="HEAD";
_googleMapsURLMonitor=new URLMonitor(request);
_googleMapsURLMonitor.pollInterval=TIMER_INTERVAL;
_googleMapsURLMonitor.start();
}
private function initServerURLMonitor():void{
var xml:XML=ServerConfig.serverConfigData;
var channels:XMLList=xml.channels.channel.(@id == "my-amf");
var channelConfig:XML=channels[0];
var uri:String=
channelConfig.endpoint[0].attribute(ServerConfig.URI_ATTR).toString();
_serverURLMonitor=new URLMonitor(new URLRequest(uri));
_serverURLMonitor.pollInterval=TIMER_INTERVAL;
_serverURLMonitor.start();
}
private function showServerStatus(evt:StatusEvent):void{
serverStatusIcon.source=_serverURLMonitor.available ?
"assets/connected.gif" : "assets/disconnected.gif"
}
private function showGoogleMapsStatus(evt:StatusEvent):void {
googleMapsStatusIcon.source=_googleMapsURLMonitor.available ?
"assets/connected.gif" : "assets/disconnected.gif"
}
]]>
</mx:Script>
</mx:ControlBar>
In Example 9-11, the network status is being checked as often as specified in the polling
interval:
PharmaSales Application | 469
_googleMapsURLMonitor.pollInterval=TIMER_INTERVAL;
The 
NetworkStatus
component checks the health of an HTTP resource using the
URLMonitor
object  that  listens  to 
StatusEvent
in  the  function 
initNetwor
kURLMonitor()
. Based on our experience, the 
pollInterval
does not guarantee that no-
tifications of connectivity changes will arrive at the intervals specified in the 
TIMER_INTER
VAL
constant.
As  an  alternative,  you  can  create  a 
Timer
object  and  check  the  value  of
URLMonitor.available
in the timer’s event handler function. If you decide to go this
route, keep in mind that it has additional overhead, which comes with any timer object.
Example 9-11 demonstrates yet another useful technique to specify the URI of the
network resource without the need to hardcode it in the program as is done in the
method 
initNetworkURIMonitor()
:
new URLRequest('http://maps.google.com/')
The chances that the URL of Google Maps will change are rather slim. But the URL of
the PharmaSales server will definitely be different, say, in development, QA, and pro-
duction environments. The function 
initServerURIMonitor()
extracts the URI of the
server based on the information about the location of the AMF channel in the server-
config.xml of the JEE server that was specified during the creation of the Flex project.
This information is available inside the SWF file, and if your PharmaSales server runs
locally, the value of the 
uri
variable from the method 
initServerURIMonitor()
may look
as follows:
http://localhost:8080/air.offline.demo.web/messagebroker/amf
To test this component, you can emulate the network outage by physically unplugging
the network wire. To test whether the monitoring of the PharmaSales server works
properly, just stop the server where the Java portion of the air.offline.demo.web appli-
cation has been deployed (in our case, we were stopping the Apache Tomcat server
configured in Eclipse IDE).
After the Salesman Logs On
The PharmaSales application is used by salespeople. After a successful logon, the fol-
lowing code is invoked:
private function initCollections():void{
visitCollection=new OfflineDataCollection("com.farata.demo.pharmasales.Visit",
"getVisitsBySalesman", VisitDTO);
visitCollection.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE, showStatus);
visitDataCollection=new OfflineDataCollection(
"com.farata.demo.pharmasales.VisitData", "getVisitDataBySalesman",VisitDataDTO);
fill_onClick();
470 | Chapter 9: Working with Adobe AIR
Documents you may be interested
Documents you may be interested