» Fig Leaf Software Home

We've Got You Covered.

Wednesday, July 30, 2014

Top 8 Things to Know About Private Training

Over the years, Fig Leaf Software has trained over 35,000 students in different courses from Google, Adobe, Acquia Drupal, Sencha and many others. Many people may not be aware, but Fig Leaf Software can deliver all of it’s training classes as private events! We have also travelled all over the world to train, and we can even deliver live-online classes in any time zone. Classes can be held at the client’s location, our location, or a neutral location that all students can attend. Here are some common questions we often receive about private training:

Is private training right for our organization?

If you have 4-5 students interested in the same class, private training is for you. Not only is private training cost effective, but one of the biggest advantages for setting up a private class is that you can customize the training to your needs. We routinely have clients who want a mixture of two classes, or simply want to remove or add a few units to the existing materials.

If I host the training at my location will I have to set up the computers?

Yes, however most classes only require about 5 minutes of setup per computer. Additionally, our training manager Jabari Bruce is available to assist with the setup. Worried about tough network restrictions? No worries, we have a few options when it comes to classroom setup, including using Amazon’s EC2 to host the class.

OK, we have a few students interested in training, where do we go from here?

Simple, just contact our training team at training@figleaf.com. If you are having any trouble we can help you decide which class(es) are right for you, and we can usually get you an estimate within 24 hours. We like to cap our classes at 12 students to keep the student to teacher ratio low, but we do have options for larger groups as well. Additionally, have all the students take a look at our class pre-requisites before the training starts. This can have a huge effect on how much the students get out of the class.

How long does it take to schedule a private class?

We can usually book a training class within 4-6 weeks, but if the instructor is available we may be able to get it scheduled sooner.
I have students in multiple locations all interested in training, can a private class still work?

Yes, we can teach all or a portion of the students online. This is live-online training, not a prerecorded video. We will setup an online environment, and provide all the remote students with a conference line so they can communicate with the instructor.

How does online training work?

The lecture component of the class will be handled through Adobe Connect and a phone conference bridge. For the best results you should have a dual-monitor system (or second computer). This helps replicate the classroom experience by watching the walkthrough exercises on one screen, and following along with the instructor on the other.

The access steps process:
  • Prior to the event you must run a connectivity test from their computer to make sure they can connect to our data centers. This ensures a smooth start when the training begins.
  • You will go to our hosted labs webpage to access the lab-environment remotely.
  • Using your assigned, unique access code you will be connected to a full-screen high performance remote desktop.

You can view more information about system requirements for online training at: http://training.figleaf.com/Locations/onlinefaq.cfm

Where do I find out if a class will run?

You can visit our training website: http://training.figleaf.com/index2.cfm. You can also contact us directly at 202-797-7711 x 107 or training@figleaf.com.

What should I estimate for travel costs?

For domestic classes you should estimate around $500 a day. You should estimate around $1,000 a day for international classes.

Schedule your private training course today by contacting our Training Coordinator, Jabari Bruce at training@figleaf.com or by phone at 202-797-7711 x107.

Friday, July 25, 2014

What's from the Orient and has 8 legs?

It's one of those errors that could only happen with computers.

Apparently, if you run IIS,
and you run ColdFusion,
and maybe you run Commonspot, 
and a specific Chinese web crawler hits your website, then your website will crash.

For over a week, the client's website had been going down.

Just a few months ago they had been migrated to a new server and upgraded to the latest software.  Windows Server 2008 R2, ColdFusion 10, Commonspot 8 (The CMS), IIS 7.5.  

Things were fine when the server was first set up, but now, several times a day, ColdFusion would hit 100% processor usage and die, requiring a restart to get the site back online.

I traced that issue to a bad webservice call - a webservice the client website utilized heavily had become unreliable, and on those occasions when it didn't respond to requests, ColdFusion pages would hang indefinitely in the system, eventually sucking up all the resources and killing the website.

I fixed this by swapping some cfinvoke calls for straight cfhttp calls to the webservice - there's an issue with cfinvoke where at certain stages of the webservice invocation (like waiting for a response), ColdFusion will go into a holding pattern of just waiting, regardless of timeout settings.  Cfhttp calls worked every bit as well and timed out successfully, thus eliminating the problem.
But it didn't save the website.  That still died several times a day, but it died in a different way.  IIS would show pages with a 503 'Service Unavailable' error.  ColdFusion server monitoring and FusionReactor, useful in diagnosing the last issue, were showing no long-running pages this time.  The server resources never hit their capacity.  Everything appeared to be fine and dandy, even as the website died every few hours.
The webservice issue had masked something else.  Once the original killer was dead, another one reared its ugly head - the server either hadn't been running long enough for this one to be noticed, or whatever crashes it had caused in the interim were assumed to be the webservice issue.
Server event logs and Performance Monitoring of the application pools started to hint at the issue - I found errors like these in the event logs:

A process serving application pool 'DefaultAppPool' exceeded time limits during shut down. The process id was '6332'.  Event ID 5013

A worker process '6332' serving application pool 'DefaultAppPool' failed to stop a listener channel for protocol 'http' in the allotted time.  The data field contains the error number. Event ID 5138

A process serving application pool 'DefaultAppPool' suffered a fatal communication error with the Windows Process Activation Service. The process id was '3748'. The data field contains the error number. Event ID 5011
I found my go-to source of information - the internet - rather unhelpful in diagnosing these errors.  Suggestions included 'Find the error in your code' and 'Try replacing this .dll file with an older version of itself'.  After finding more promising info, I tried changing various application pool settings with no success.  

At a dead end, I looked for a way to try to get a better picture of what was going on inside the worker process threads.  You may need to install a server role (That role is IIS -> Heath and Diagnostics-> Request Monitor), as I did, to enable this.  Once it's there, from IIS you can select your server (not any of the websites), click on 'Worker Processes', and that will pop up a list of currently executing requests inside that worker process.
Inside a normal, healthy worker process you should see very little - a few requests executing with nice short times (those are in milliseconds), or maybe even nothing going on at the moment.

This is not what you want to see.

Ok, so that's a problem. 
My first thought was that there was something wrong with the pages, but no.  My own request for any of these pages would go through the application pool and CF, process, and a response was sent back to me - no problem.
My second thought was "Why are these all from similar IP addresses?"
A quick IP lookup revealed that the requests are coming from Guangzhou, China.  Odd traffic for an American site.  Armed with the IP address, I checked the IIS logs, where more of them showed up, helpfully self-identifying as 'Easouspider' requests.  There were several in the logs, and many of them completed successfully - anything that wasn't a .cfm page was fine, and there were successful .cfm page requests. 
Easou.com purports itself to be 'China's #1 mobile search engine', and they may well be - they're pretty big.  They're just crawling the web much like google and yahoo.  But for some reason, some requests from this particular crawler for .cfm pages for my client's server wouldn't go back out of the system.  They just sat in the application pools and nowhere else, gradually filling them up until something (usually errors) triggers application pool recycling.

Normal application pool recycling is pretty slick - IIS keeps the old pool running while it starts up the new one, and then does a handoff so the site doesn't drop, allowing all the requests in the old application pool to finish before fully transitioning to the new one.  That way your website doesn't appear to ever drop during a normal application pool transition.

That's when the truly diabolical thing was happening here - these hung requests are tough.  Persistent.  They do not want to let go.  IIS spends several minutes trying to wait for them to shut down so it can properly restart the application pool during a recycle - and that's the period when website would be dead, stuck in limbo with an old application pool that refused to die and unable to fully transition to the new one. 
Now, finding that the requests are stuck doesn't tell us exactly why it's happening.  The prevailing theory in the office is that requests from China are perhaps sending some odd character that IIS or CF doesn't like as part of the request, but even if we could narrow it down to that, what could we do about it?  I can't change how IIS or CF handles these requests.
So I blocked all IPs beginning with 183.60 from making requests to the site.  Better to cut off a part of China being able to access the site rather than allow the website to continue crashing.
It worked.  The site stopped crashing and ran smooth as butter.  The client was happy, I was happy, and all was well with the world.
A week later, another client called us in.  Their website was crashing mysteriously.

I checked the worker processes first this time, and there it was again.  Hung requests from IPs starting with 183.60.  The Chinese Spider was here too.  I had previously assumed this was an issue limited to the first client - despite having been upgraded recently, theirs was an older code base that had seen a lot of modification over the years, and nobody else had been crashing like they were until now.  This other client was a recent build, but apparently susceptible to the same issue.
After that, I checked every client we had - if two separate sites could go down like this, then others might be vulnerable as well. 

I was right.  I found the Chinese Spider's requests stuck in two more ColdFusion / Commonspot / IIS websites that we manage (though several others got a clean bill of health, we nonetheless have blocked the IP on all our clients for now as a safety precaution).  In those cases it appears that the crawler hadn't been hitting the sites too hard, so the application pool would recycle naturally before dying from too many hung requests.
If you manage a ColdFusion / IIS site, I'd recommend taking a quick peek inside those worker threads - if it was present in four of ours, I'd wager we're not the only folks experiencing this strange issue, even if it isn't bringing down your website yet.

Written by: Benjamin Bently

Wednesday, July 16, 2014

Extending Adobe Connect with Custom Pods and Applications

As a web meeting solution, Adobe Connect has all the features of every other web conferencing vendor.  Users can screen share, stream live video, broadcast audio, chat, whiteboard and much more.  However, with Adobe Connect, users can take their Connect Meetings to another level altogether by using Custom Pods and Applications inside a Connect Meeting Room.  By extending Connect, Meeting Hosts can go beyond normal web meetings and really increase user interaction and engagement.  We call this the Engagement Factor of Adobe Connect.

What is a Custom Pod?
A custom pod is an application that can run inside a Connect Meeting room to do something specific like:
  • Broadcast YouTube Video
  • Play games
  • Interact with maps and trackable quizzes
  • Create, brainstorm and collaborate with content
  • Stream music
  • And Much More

What does this mean?
This means that you can create any type of interactive application you want and run it inside your Connect Meeting Room.  Companies and organizations can create their own custom pods to help facilitate interaction and engagement and in effect extend Connect for their specific needs.  Interactive developers and designers can use Adobe’s SDK to create custom pods of their own.

Here is a link to a list of Custom Pods Connect clients can download and use inside their Connect Meeting Rooms:
http://www.adobe.com/products/adobeconnect/extend.html#3

Adobe’s approach of allowing users to extend Connect by using custom pods is simply visionary, and helps clients achieve unique business and organizational requirements by going beyond out-of-the-box web conferencing.

Don’t forget to join Fig Leaf Software and eSyncTraining for a live webinar to learn how to extend Adobe Connect with Custom Pods & Applications. This webinar will show how organizations can use custom pods within a Connect Meeting Room to increase engagement and interactivity.



Below are a few screenshots of these custom pods in action. 

Interactive Map:
MapScreenShot.jpg

Interactive Crossword:

GameCloud-Crossword.jpg
Brainstorm, Organize and Present with Mindomo:

Mindomo_ScreenShot.jpg

Streaming YouTube:

YouTubeConnect.jpg

Written by: Seth Land

Tuesday, July 1, 2014

2014 World Cup: Online Media Application for Voice of America

World Cup Soccer fans can stay on-top of their favorite team’s progress via a real-time data push from the Voice of America.  As the 2014 World Cup got underway in Brazil, Fig Leaf Software launched an online media application for VOA to display real-time information about each World Cup tournament. The goal of the site is to deliver a real time experience of the entire World Cup to users in West Africa, and because West African internet infrastructure is somewhat limited the site has to be extremely fast, lightweight, and mobile friendly.

A half-hour before each game each VOA World Cup microsite is refreshed so that game information starts to update as the game progresses.  Web viewers can track their favorite game without having to refresh their page.  

Catch all the 2014 World Cup action live and in real time here:




VOA World Cup Microsites - Behind the Scenes:
Each country’s football microsite is built in WordPress, with backend Node.js applications. Caching for the WordPress sites is provided by the W3 Total Cache plug-in working with Amazon CloudFront as a Content Delivery Network (CDN). Once implemented Fig Leaf Software setup JavaScript tracking to detect page load times. On average the sites are loading in 1.2 seconds globally, at between 3-6 seconds in West Africa, and in just .3 seconds in the United States and Europe.





For caching the initial HTML is delivered to the widgets, not the WordPress sites.  The system uses a dedicated Varnish server with a time to live (TTL) of 2 minutes. This is what gets embedded into the VOA web pages via an IFRAME: http://footballwidget.voanews.com/widget.php?type=full-game

Data-Provider:
  • Receives XML from a company that provides the real time data via FTP
  • Parses the XML and creates JSON
  • Writes the JSON to disk so the French and English WordPress sites can use it to display statistics about the games
  • Pushes the JSON to the second Node.js application

Faye Server with some security enabled:
  • Receives JSON from the Data-Provider
  • Broadcasts the JSON to web-clients who subscribe to it (Javascript in the HTML)

The entire system runs in Amazon
  1. Devevelopment server (small)
  2. English Production Server: WordPress, Node.js Data-Provider application, and Widget server (medium)
  3. French Production Server: WordPress (small)
  4. Varnish Cache Server for Widgets (small)
  5. Faye Server (micro)

Other links:
More VOA content: http://football.voanews.com
Team Stats: http://footballwidget.voanews.com/widget.php?type=squads

Tuesday, June 24, 2014

Sencha Touch 2.3: Downloading and Saving Binary Files to Local Devices with PhoneGap/Cordova

Sencha Touch 2.3 has added a new Cordova/PhoneGap abstraction layer to the Ext.Device class. Unfortunately the documentation/guides don’t seem to have an example of downloading and saving a binary file to the device’s filesystem.
Since mobile connectivity can be unreliable and usually produces high latency, being able to cache large documents on the device is critical for developing high-performance apps.
Before you can get started, you’ll need to install phonegap:
  1. Install Java JRE
  2. Install Node.JS
  3. Install PhoneGap by typing the following at a command prompt:
    npm install -g phonegap
Next, you’ll need to use Sencha Command 4.x+ to create a phonegap project. Simply change directories to the root of your application’s folder and issue the following command:
sencha phonegap init [AppId]
Where [AppId] is your application’s id (e.g. com.figleaf.myapp)
This will create a /phonegap folder off your project root.
Change directories to the phonegap subdirectory and install common phonegap plugins to enable the Sencha Touch Ext.Device classes to detect device type, enable file system access, and get real-time network information:
  • phonegap plugin add org.apache.cordova.device
  • phonegap plugin add org.apache.cordova.file
  • phonegap plugin add org.apache.cordova.network-information
Now you can get started with adding the download feature!
Request access to the local filesystem by using the code below, which I typically place in the application’s launch function, caching the result in the application object.
1
2
3
4
5
6
7
8
9
10
11
Ext.device.FileSystem.requestFileSystem({
     
    type: PERSISTENT,
    size: 50 * 1024 * 1024, // 50mb -- gonna store video
    success: function(fs) {
        MyApp.app.Fs = fs;
    },
    failure: function() {
        Ext.Msg.alert("FileSystem Error","Could not access the local file system<br>You will not be able to save notifications for offline use.");
    }
});
The following controller function illustrates how to download a file with a progress indicator and save it locally on the device. Note that the local file URL is returned to the callback function and would typically be written to a data store.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
saveFile: function(url,recordId,prompt,callback) {
 var me = this;
 // create progress indicator
 var progIndicator = Ext.create('Ext.ProgressIndicator', {
    loadingText: prompt + " {percent}%",
    modal: true
 });
 // create unique filename
 var fileName = url.split('/');
 fileName = fileName[fileName.length - 1];
 fileName = "notification-" + recordId + '-' + fileName;
 // let's get the party started!
 Ext.Ajax.request({
    url: url,
    timeout: 180000,
    useDefaultXhrHeader: false,
    method: 'GET',
    xhr2: true,
    progress: progIndicator,
    responseType: "arraybuffer",
    success: function(response) {
        
       var blob = new Blob([response.responseBytes],
                            {type: response.getResponseHeader("Content-Type")});
         
        Ext.defer(
           function(p) {
               p.destroy();
           },
           250,
           this,
           [progIndicator]
       );
       // define file system entry
       var fe = new Ext.device.filesystem.FileEntry("/" + fileName, MyApp.app.Fs);
       fe.getEntry({
                
                file: fileName,
                options: {create: true},
                success: function(entry) {
                     
                    // get native file system url
                    // to saved document..will be file://[some path]
                    var fullPath = entry.nativeURL;
                     
                    // write binary data to file
                    entry.createWriter(function(fileWriter) { 
                        fileWriter.write(blob);               
                    });
                     
                    // return path of local file to
                    // callback function
                    if (callback) {
                       callback.call(me,fullPath);
                    }
                     
                },
                 
                failure: function(error) {             
                    Ext.Msg.alert("Transaction Failed (02)", error.message);
                }
        });
    },
    failure: function(error) {
       progIndicator.destroy();
       Ext.Msg.alert("Transaction Failed (03)", error.message);
    }
});
Note that while you’ll be able to test this code on device simulators, the Ext.device.filesystem.FileEntry.getEntry() method will fail if the app is run through desktop Chrome.
Happy coding!

Written by: Steve Drucker
[Cross-Promoted: Druck-I.T.]

About Us

Fig Leaf Software is an award-winning team of imaginative designers, innovative developers, experienced instructors, and insightful strategists.

For over 20 years, we’ve helped a diverse range of clients...

Read More

Contact Us

202-797-7711

Fig Leaf Software

1400 16th Street NW
Suite 450
Washington, DC 20036

info@figleaf.com