Working with large numbers of projects in Eclipse and any of the Eclipse based products such as Flex Builder, ColdFusion Builder or CFEclipse can become cumbersome and become a bottle neck in a good workflow.

One of the many ways to work better within this space is to make efficient use of your navigator (or project explorer) and searching dialogs. Working sets can be used to filter search results as well as your navigator view, but constantly switching them can be a pain. Window working sets however can be a globally applied and just a few tweaks can make using them easy. Here is what I recommend!

  1. Make sure you have the menu item turned on. Customize your current perspective (Window ==» Customize Perspective). Under command group availability, make sure "window working set" and "Working set manipulation" are checked.
  2. Create a shortcut: Go to Window ==» Preferences ==» General ==» Keys. I prefer to use F3, since it's a continent key and I don't use its default binds ever. Sometimes the scopes can be difficult to always get right, so I choose "all editor scopes", "In Console View" and "In Windows" for the best results.
  3. Make your views take advantage of "Window Working sets". The two most common usage points will be your Navigator and Search Results. In the option menus for both of these you can choose working sets from the list; however instead of separately choosing your projects per view, choose "Windows Working Set" radio button.
  4. Now you can hit {F3} or what ever your chosen hot key was at any time. You can change, edit or create new working sets from one interface and all your views will obey this choice. This is fantastic if you work on multiple large projects in a single days time especially.

 

I've worked on a number of projects lately that have required the reviewing of HTML mail generated by ColdFusion's CFMail. In every development environment I've worked in the mail server is either 0.0.0.0 or there is a dummy mail gateway. In in either case knowing what the HTML will really look like can be difficult.

To help me with this issue I whipped up this very simple Adobe AIR app to help me look at the results. It's not a perfect solution and cannot account for the multitude of environments that the email will be viewed from, but it will render plain text and HTML emails close to what they would be viewed as in a mail client; it's also nice that to app is dead simple/basic.

Just point the app at your ColdFusion instance's "bad mail" folder and make sure your email server is set to 0.0.0.0 in CF Administrator

Please upgrade your Flash Player This is the content that would be shown if the user does not have Flash Player 6.0.65 or higher installed.


CFMail Viewer : Trunk - http://svn.empiregpservices.com/svn/OpenSource/CFMailViewer/trunk
CFMail Viewer : Branch 0.5.0 - http://svn.empiregpservices.com/svn/OpenSource/CFMailViewer/branches/0.5.0/

SVN Username = public
SVN Password = public

 

CFMail Viewer Screen Shot

Memorial Day

May 31, 2010

In a time where our country is divided on the nessesity of war, please put thought into the negative words you utter about our soldiers; at least on this day if not any other. Please think about not only brave soldiers who have laid down their lives in battle, but the ones who survived to bring them home and their loved ones who were left behind! - Russell Brown

 

 

I ran into this little gem this morning and I was stummped. FireBug wasn't even showing an attempt to call any images, ruling out server side issues since the image calls were plainly in the source code.

Turns out some how my local host got added to an exception list for loading images; I didn't even know FireFox had this feature.

  1. Tools » Options
  2. Content Tab
  3. Make sure Load Images is Cheked
  4. Click the respective Exceptions button
  5. Remove sites that shouldn't be in there

I had about 8 sites located in this exception list, all but one made no sense why they were there. I can only assume that there is some hot key or trigger that causes a site to get tossed into this bucket.

I needed to adjust an accordion to make it look more natural and less snappy. I found lots of "how to use" easing pages with examples obviously but the differences between many of the easing functions like Exponential, Exponential, Linear, Quadratic, Quartic, Quintic and Sine are so small that watching them one at a time yields nothing helpful.

This little app should be helpful in comparing the different options you have. Tweaking options are limited, but enough to give you a good idea of what one to use. I excluded Elastic and Bounce from this example since they were very different from all the others and play a very obvious role/function.

 

Are you using multiple master templates for multiple site collections in SharePoint 2007? By default all search results are sent to "/_layouts/osssearchresults.aspx" for MOSS installs and to "/_layouts/searchresults.aspx" for WSS-only. The result is a search results page using the hardcoded "~/_layouts/application.master" master page and default theme; this is not good.

Solution:

  1. Go to the base of you site collection and "Modify All Site Settings". Near or at the top right you will find "Search Settings".
  2. Select "Use custom scopes"
  3. Enter a new path, I choose to use: /{sitecollectionbase}/SearchCenter
  4. Create new folders via sharepoint designer where nessesary
  5. Copy file osssearchresults.aspx from c:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\LAYOUTS to your new folder location.
  6. rename osssearchresults.aspx to Results.aspx
  7. Edit Results.aspx to reflect the master template and other required changes needed.

In a previous release of CF Builder there was a bug that some of you may have run into. The result of the bug was getting Eclipse pop-up errors when you tried to copy-n-paste with the keyboard shortcuts in cfm and cfc files. I entered a bug and it was fixed within a couple of days.

However after upgrading from the pre-release version to the latest public release, I will still getting the error. It was not until I blew away the .metadata\.plugins\org.eclipse.core.resources folder and started from scratch with my projects. So if your still hitting this issue or similar, please try this step to resolve it.

 

 

I am building a new site on my server that will be another Mango Blog. Mango is not setup for running multiple instances like it would be nice if it did, but very easily you can at least use the same file base. While this won't save you much on anything other than disk space for the CF Files and for the file cache if your CF server has that turned on; it certainly is nice to have one install location instead of 2 or 3.

To do this you will need to edit only 2 files:

  1. Application.cfm
    • Change the "this.name" setter on line 7ish to something that would be URL driven. In my case I used:
      this.appKey = replaceNoCase(cgi.server_name, "www.", "");
      this.name = "mango_#right(hash(this.appKey),50)#_v1_4";
    • The around line 41 you will find a reference to config.cfm. I've replaced this with: config_#this.appKey#.cfm
  2. admin/setup/Setup.cfm
    • Using the same method as Application.cfm I created an appKey var in the function saveConfig. Around line 268/269 will be two references to config.cfm; again replace these with: config_#this.appKey#.cfm

Now Mango Blog will be using config files based on the server name of the current site. The only secondary change I made was in the config files themselves.

  • Make sure the tablePrefix values are different
  • I adjusted my asset directories to be unique per site: assets/content/{new site name}/

In my environment I rarely see an Adobe Connect recording span 2 different days. However a few weeks ago we ran into an issue where some of the durations for recordings were being displayed as large negative numbers. I assumed at first I of course must have been the one to make this entry level mistake, but it turns out it was Adobe.

While the actual Adobe Connect interface shows the time span of this recording as ruffly 53 minutes, the API reports it as -1386. The math must be coming from someplace different and they are not taking into account that the start day might not be the same as the end date.

Woops

If you have had the fun of deploying the Adobe AIR runtime and applications to hundreds of computers in an organization you will have no doubt stumbled upon at least one or two the annoyances that pop-up. The runner up for most annoying issue in my experience is the uninstaller.

In my development of "sometimes-connected" applications I have always had to write/store data on the local machine. The lacking feature of the built in uninstaller is the complete inability to remove this data. In my environment I needed to be able to have a solid roll-back plan of a piece of software; this unsuprisingly includes any downloaded content.

To solve my delema I wrote a VBScript file to perform the uninstallation. Similar to my installation process I wrote an install wrapper with Install Jammer. I did it this way to allow for easier "distribution" via SMS. I will highlight a few steps here and provide the full script at the end of the post. This script is obviously meant for Windows only and should work on windows XP, Vista and Windows 7. I have yet to have to distribute an app to anything other than a windows box.

First I grab the installer ID from the install path.Set wmiObj = CreateObject("Scripting.FileSystemObject")
Set oTS = wmiObj.OpenTextFile("{ ** AIR APP INSTALL PATH ** }\META-INF\AIR\publisherid")
publisherid = oTS.ReadAll

Then I get the uninstall executable path/arguments.Set wmiObj = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
 
strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{ ** AIR APP ID NAME ** }." & publisherid
strValueName = "UninstallString"

wmiObj.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue

I then run the uninstaller: Set wmiObj = WScript.CreateObject ("WScript.Shell")
wmiObj.run strValue & " /quiet /qn"

Lastly I remove all leftover files:Set wmiObj = CreateObject("Scripting.FileSystemObject")
Set subFolders = wmiObj.GetFolder("C:\Documents and Settings").SubFolders

For Each folder in subFolders
    If wmiObj.FolderExists("C:\Documents and Settings\" & folder.name & "\Application Data{ ** AIR APP ID NAME ** }." + publisherid) Then
        'StdOut.WriteLine "Delete: " & "C:\Documents and Settings\" & folder.name & "\Application Data\{ ** AIR APP ID NAME ** }." + publisherid
        wmiObj.DeleteFolder("C:\Documents and Settings\" & folder.name & "\Application Data\{ ** AIR APP ID NAME ** }." + publisherid)
    End If
Next

 

Download My Full Example Script

For months I've thought about the power of virtual machines. I use them all the time now for production and staging servers and in the past I've used them for QA purposes in a lab. However I have never run a VM instance on my own box.

Recently I purchased a VMWare Workstation 6.5 license on the cheap and on a re-wipe of my laptop decided to put it into use. I now have multiple XP VMs, a Win Server and an OpenSUSE distro. I am now able to have multiple server setup options at my fingertips with ease.

Setup
After several setup attempts I think I have found a great mix.

  1. All of my development tools and code are located on my real machine.
  2. All of my services are located on a VM
  3. All of my services via UNC paths call on files from the HOST machine.
    • This allows me to have multiple servers from multiple VMs reference [easily] the same code set.


Things To Pay Attention To

  1. Setting up the networking can be difficult the first time, but it really is easy. I choose to run everything in NAT mode; just make sure your firewall settings are all correct. I've also made all of my Windows machines part of the same workgroup to make some file browsing easier.
  2. Permissions: In my case I created a VMUser in my VMs that was an admin/root and on my main box created that same user. I made sure VMUser had read/write too all of the relevant files. I then made sure all of my services were running as that user.
  3. Flex / Flash Development and Debugging: Because you will be launching your debugging on an IP such as 192.168.248.x instead of 127.0.0.1 your Flex Builder will be unable to attache to the debug tool from the browser. When you launch your flash/flex app right click on the flash app area. When you click you will see a menu item "Debugger"; click it. You will get the following pop-up. When you do change the selected option from localhost to other machine and enter 127.0.0.1. Viola, your debugger will now attache!


So far my experience is extremly positive. I recomend a minimum of 4 gigs; this is what I currently have and I would want no less. My next laptop will definetly have either 6 or 8 gigs to allow me to run multiples at the same time, or maybe even make a VM my full time editing area. VMs can do multi-monitor BTW! I would love to have my base OS be basically naked and be able to more easily do snapshots and go backwards in time. For me, setting up all the servers takes the most time. Now I can just backup my VMs and on a future wipe of my box, literally be up and running in say an hour instead of 5 or 6.

I Updated yesterday from an early release of Windows 7 to the retail release doing a complete wipe of my computer. After installing Flex Builder 3 I tried to do some work, yet every time I launched the program Windows 7 alerted me that I was running a program with an unknown publisher. After hitting my self in the head I released that unlike my regular Eclipse environment, Flex Builder was not using my VM but the one that is packaged. This packaged version is NOT signed.

For some reason this worked fine before; but now, not so much. Setting the [-vm c:\pathto\javaw.exe] in the eclipse.ini did not work, but changing the shortcut did work. Any insite into this is welcome!

So in short, on windows 7, force your VM to a legit installed JRE to get this pop-up message to go away if your getting it! The packaged one is not in favor with Windows 7 security!

After years of abuse of pop-ups and confirmation boxes users have become so honed at the skill of simply clicking the OK button on any kind of confirmation box that pops up that it has become almost nothing more than a reflex. This can cause some serious issues when it really matters.

In my flex application I needed to increase the chances of a user actually reading the notice in the pop-up box as much as reasonably possible within the user experience. The solution I decided to use is I believe fairly common to anyone with windows experience; it's also one I would use sparingly!

When the confirmation dialogue is presented the OK button is disabled at first. Instead a countdown timer is displayed on the button. After that timeout the user can then click "OK"; The cancel button is available at all times.


The code isn't rocket science and making use of the pop-up is so simple I won't even bore you with an example, but it is a nice quick fix if you need it.

Source view is enabled on the Flex demo

A little while ago I started using a screenshot of our flex app login to use as the background for a few of our web apps. As usage grew I ran into multiple color and title needs. So instead of doing things the simple way and just using Photoshop, I decided to make this an example of taking and using "screen shots" (not using mx.graphics.ImageSnapshot).

First I built a plain-jane panel component that I wanted to use as my background in my HTML based application

Then in my main MXML file I wrapped the login component and 3 empty canvases in one larger canvas. I did this in order to more easily control position inside the greater app while easily being able to build my Rectangles.

<mx:Canvas id="loginForm" backgroundColor="{this.backgroundColor.selectedColor}" width="400" height="296">   
    <local:LoginForm title="{this.windowTitle.text}" borderColor="{this.panelColor.selectedColor}" width="360" y="15" horizontalCenter="0"/>
    <mx:Canvas id="loginHeader" width="368" height="48" y="11" horizontalCenter="0"/>
    <mx:Canvas id="loginBody" width="368" height="59" y="78" horizontalCenter="0"/>
    <mx:Canvas id="loginFooter" width="368" height="67" y="219" horizontalCenter="0"/>
</mx:Canvas>


I positioned the 3 boxes to be in the size and position of my 3 desired screen shots: A header, a repeating body and a footer. In my code I use these to create a very easy way to visualize what I'm capturing. In the real world outside of my very specific goal these might be controllable by the end-user.

To create my screen caps first I take a snap of the entire formpublic function takeSnapshot():void {
    var imageSnap:ImageSnapshot = ImageSnapshot.captureImage(this.loginForm);
    var imageByteArray:ByteArray = imageSnap.data as ByteArray;

    var loader:Loader = new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, getBitmapData)
    loader.loadBytes(imageByteArray);
}


Then I loop over my 3 targets to create the specific sub-images that I need:
var bd:BitmapData = Bitmap(e.target.content).bitmapData

for each (var target:Canvas in [this.loginHeader, this.loginBody, this.loginFooter]) {
    rect = new Rectangle(target.x, target.y, target.width, target.height);

 bd2 = new BitmapData(target.width, target.height);
    bd2.copyPixels(bd, rect, pt);

    var m : Matrix = new Matrix();
    bd2.draw( bd2, m );

    encoder = new JPEGEncoder(100);
    ba = encoder.encode(bd2);

    rawImages[target.id] = ba;
}

this.amfService.save(this.downloadUUID, rawImages);



The flex app has view source enabled and the ColdFusion code for the backend is included as well...

 

Are you using flash.net.FileReference's download function and having your download fail? I was too and it took stumbling on a flash kb article to get me on the right path.

My issue:private function downloadFile():void {
    var f:FileReference = new FileReference();
    f.addEventListener(Event.COMPLETE, myFnc);
    f.download(myURLRequest, strDefaultFileName);
}

This should work in my mind... However it does not. It will most likely fail with absolute silence.

Instead, init a globabl FileReference.private var fileRef:FileReference;

private function init():void {
    this.fileRef = new FileReference();
    this.fileRef.addEventListener(Event.COMPLETE, myFnc);
}

private function downloadFile():void {
    this.fileRef = new FileReference();
    this.fileRef.addEventListener(myURLRequest, strDefaultFileName);
}

This my friends will now work. It shouldn't require this code layout IMO, but it does...

I got caught up in a little gotcha last night that took me a few minutes to fully fix.