# Presentation: 458995

## Developing Shared Applications

- Susanne Lefvert
- lefvert@mcs.anl.gov
- University of Chicago

## Shared Applications

- Allows individuals to use programs
- together from remote locations

- Shared Browser
- Browse the web together
- Shared Presentation
- View and control remote presentations
- Shared VNC
- Secured screen sharing
- And many more...

## Shared Applications

## Outline

- Characteristics
- Sharing State
- Event Communication
- Developer Tools
- SharedAppClient
- DatastoreClient
- Access Grid Package Manager
- Example: Shared PDF
- Exercises
- Documentation

## Sharing State

**Venue**

**foo**

**foo**

**foo**

**Client 1**

**Client 2**

**Client 3**

*** Communicating via ZSI SOAP calls**

**Application Session**
**State:**

**foo**

## Event Communication

**bar**

**foo**

**foo**

**bar**

**bar**

**Client 1**

**Client 2**

**Client 3**

*** Event communication using Twisted**

**Venue**

**Event** **Channel**

**Application Session **

**Event** **Channel**

## SharedAppClient

**Your Application**

**SharedAppClient**

**SharedApplicationIW**

**Application Session **

**Event** **Channel**

**EventClient**

## SharedAppClient

- _[http://www.mcs.anl.gov/fl/research/accessgrid/documentation/developer/api/](http://www.mcs.anl.gov/fl/research/accessgrid/documentation/developer/api/)_

- Tool for developers that includes:
- SOAP communication
- Event exchange
- Logging
- Data cache
- Exception handling
- API
- AccessGrid.SharedAppClient

## SharedAppClient

- _API:_
***Join()*** – Connect to an application session
***InitLogging()*** – Get object for logging
***Shutdown()*** – Shut down soap interface and event client
***SendEvent()*** – Distribute an event to all clients
***RegisterEventCallback()*** – Register callback for event
***SetData()*** – Set shared state
***GetData()*** – Get shared state
***UpdateDataCache()*** – Update cached data
***GetPublicId()*** – Get my unique id
***GetVenueURL()*** – Get venue url

## DatastoreClient

- _API:_
***LoadData()*** – Get data from venue
***QueryMatchingFiles()*** – Get file names matching pattern
***GetFileData()*** – Get data description for a file
***Download()*** – Download file from venue
***Upload()*** – Upload file to venue
***RemoveFile()*** – Remove file from venue

## Packaging and Installation

- Build an Access Grid package: *SharedAppName.agpkg3*
- Use agpm3.py to install the application
- agpm3.py –help
- Open the package in the Venue Client
- Start the application session in the Venue Client

- [application]
- name = SharedMyApp
- mimetype = application/x-ag-shared-myapp
- extension = sharedmyapp
- files = SharedMyApp.py, otherFile
- [commands]
- Open = %(python)s SharedMyApp.py -a %(appUrl)s

## Example: Shared PDF

## Example: Shared PDFSharedAppClient

-  # Create shared application client
-  self.sharedAppClient = SharedAppClient(name)
-  self.log = self.sharedAppClient.InitLogging()
-  # Get client profile
-  clientProfile = ClientProfile(UserConfig.instance().GetProfile())
-  # Join the application session
-  self.sharedAppClient.Join(appUrl, clientProfile)
-  self.id = self.sharedAppClient.GetPublicId()
-  # Register callbacks for external events
-  self.sharedAppClient.RegisterEventCallback("openFile", self.OpenCallback)
-  self.sharedAppClient.RegisterEventCallback(“changePage",                                                                           self.ChangePageCallback)

## Example: Shared PDFGet Current State

- _State_: URL to file and current page number

- # Get current state
- self.file = self.sharedAppClient.GetData(“file")
- self.pageNr = self.sharedAppClient.GetData(“page")
- if self.file:
-     try:
-         self.dataStoreClient.Download(self.file, "tmp")
-         self.pdf.LoadFile("tmp")
-         self.pdf.setCurrentPage(self.pageNr)
-     except:
-         self.log.exception("PdfViewer.__init__: Download
- 				 failed %s"%(self.file))

## Example: Shared PDF

## Example: Shared PDFEvent Communication

- # -- sender ---
- def OnNextPageButton(self, event):
-         '''Invoked when user clicks the next button.'''
-         self.pageNr = self.pageNr + 1
-         self.pdf.setCurrentPage(self.pageNr)
-         self.sharedAppClient.SendEvent(“changePage", self.pageNr)
-         self.sharedAppClient.SetData("page", self.pageNr)
- # --- receiver ---
- def ChangePageCallback(self, event):
-         ''' Invoked when a changePage event is received.'''
-         self.pageNr = event.data
-         id = event.GetSenderId()
-         # Ignore my own events
-         if self.id != id:
-             wxCallAfter(self.pdf.setCurrentPage, self.pageNr)

- _Event_:  type – “changePage”, data – page number

## Example: Shared PDF

## Example: Shared PDFDatastoreClient

-   def PopulateCombobox(self, default = None):
-         # Get pdf files from venue
-         fileNames = []
-         wxBeginBusyCursor()
-         try:
-             self.dataStoreClient.LoadData()
-             fileNames = self.dataStoreClient.QueryMatchingFiles("*.pdf")
-         except:
-             self.log.exception("FileSelectorDialog.PopulateCombobox: Failed.")
-         wxEndBusyCursor()
-         # Update combobox
-         self.pdfList.Clear()
-         for file in fileNames:
-             self.pdfList.Append(file)

## Example: Shared PDFPackaging and Installation

- 1. Create SharedPDF.app:
- 2. SharedPDF.py + SharedPDF.app => SharedPDF.agpkg3 (zip package)
- 3. agpm3.py --p SharedPDF.agpkg3

- [application]
- name = Shared PDF
- mimetype = application/x-ag-shared-pdf
- extension = sharedpdf
- files = SharedPDF.py
- [commands]
- Open = %(python)s SharedPDF.py -v %(venueUrl)s -a %(appUrl)s

## Starting Application Session

## AGTk 2.4 – 3.0 Migration

- Connection id needed for venue data store; the id can be retrieved via the .app file.
- Twisted-wxPython interaction; add reactor imports and reactor.interleave(wxCallAfter).
- More restrictive rules on data format for events; only primitive data types allowed.
- Data received from the application service when using the method *sharedAppClient.GetData()* may be unicode; convert received data to correct python type.
- Use the new event method event.GetSenderId() to retrieve the public id of a sender.
- An application package should have extension agpkg3.

- _[http://www.mcs.anl.gov/fl/research/accessgrid/documentation/MigrationGuides/SharedApplicationsMigrationGuide.htm](http://www.mcs.anl.gov/fl/research/accessgrid/documentation/)_

## Exercises

**Exercise 1: **Shared Stoplight
**Exercise 2: **Shared Group Chat exercise

- _[http://www.mcs.anl.gov/fl/research/accessgrid/documentation/tutorial/Retreat2006/SharedApps/](http://www.mcs.anl.gov/fl/research/accessgrid/documentation/tutorial/Retreat2006/SharedApps/)_

## Exercise 1: Shared Stoplight

## Exercise 1: Shared Stoplight

- Three Tasks:
- Create an AG package, install, and start the application from the Venue Client.
- Add a new button – yellow
- Add a text field to change the title

## Exercise 1: Shared Stoplight

## Exercise 2: Shared Group Chat

## Documentation

- Reference Materials
- _[http://www.mcs.anl.gov/fl/research/accessgrid/documentation/developer.html](http://www.mcs.anl.gov/fl/research/accessgrid/documentation/developer.html)_
- Toolkit API
- _[http://www.mcs.anl.gov/fl/research/accessgrid/documentation/developer/api/](http://www.mcs.anl.gov/fl/research/accessgrid/documentation/developer/api/)_
- AGTk 2-3 Migration Guide
- _[http://www.mcs.anl.gov/fl/research/accessgrid/documentation/MigrationGuides/](http://www.mcs.anl.gov/fl/research/accessgrid/documentation/MigrationGuides/SharedApplicationsMigrationGuide.htm)_
- _[SharedApplicationsMigrationGuide.htm](http://www.mcs.anl.gov/fl/research/accessgrid/documentation/MigrationGuides/SharedApplicationsMigrationGuide.htm)_

**Notes:**
Here are some more documents...