tag:blogger.com,1999:blog-242323012024-03-13T22:13:30.596-05:00What I'm Up Toprlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.comBlogger21125tag:blogger.com,1999:blog-24232301.post-19875473394817009752020-01-15T20:35:00.005-06:002020-01-15T20:45:43.497-06:00How To Create Temperature Monitor with Email Alerts<div dir="ltr" style="text-align: left;" trbidi="on">
I need to monitor the temperature in a room and make sure it doesn't get too cold in the winter, so I decided to setup a raspberry pi as my temperature sensor, and create a simple application/service that regularly checks the temperature and updates me via email.<br />
<br />
Once you know what you're doing it's really quite easy. I had to do a lot of research, so it took me longer than I'd like to admit, but it was fun setting everything up and learning. I stuck with python throughout because it simplifies everything.<br />
<br />
<h2 style="text-align: left;">
Reading the Temperature </h2>
First, you need a temperature sensor. There's a really good <a href="http://www.circuitbasics.com/raspberry-pi-ds18b20-temperature-sensor-tutorial/" target="_blank">tutorial</a> by circuitbasics.com. All you need is a raspberry pi 3b (older and cheaper ones probably work too), DS18B20, and a 4.7K resistor (anything between 1K and 10K would probably work). I also used a 2x4 .1" female header for soldering the temperature sensor circuit so that I can easily connect it to the raspberry pi.<br />
<br />
After connecting the temperature sensor circuit to the raspberry pi as shown in the tutorial and enabling the 1-wire interface, you'll be able to read the temperature sensor.<br />
<br />
<ol style="text-align: left;">
<li>Add this to the end of /boot/config.txt: <span style="font-family: "courier new" , "courier" , monospace;">dtoverlay=w1-gpio</span></li>
<li>Reboot the raspberry pi</li>
<li>Execute: <span style="font-family: "courier new" , "courier" , monospace;">sudo modprobe w1-gpio;sudo modprobe w1-therm</span></li>
<li>Execute: <span style="font-family: "courier new" , "courier" , monospace;">cat /sys/bus/w1/devices/28-*/w1_slave</span></li>
<li><span style="font-family: inherit;">The temperature is at the end (t=x) in thousandths of degrees Celsius</span></li>
</ol>
<div>
The tutorial also includes a bit of python code to read and output the temperature.</div>
<br />
<h2 style="text-align: left;">
Web Service</h2>
The web service was extremely simple to create. I used flask, and followed the <a href="https://pythonspot.com/flask-hello-world/" target="_blank">hello world tutorial</a> from pythonspot.com. Then I added the ip address for external access, customized the port number and merged the temperature reading python code from before. The web service I created simply returns the temperature in degrees Celsius because I wasn't interested in any other information.<br />
<br />
<h2 style="text-align: left;">
Raspberry Pi Startup</h2>
Next, I wanted the python based web service to run on startup so that it'll always be available. Following the <a href="https://www.instructables.com/id/Raspberry-Pi-Launch-Python-script-on-startup/" target="_blank">example</a> by instructables, I configured cron to start the service on boot. To verify, I restarted the raspberry pi, went to the URL in my browser and made sure the temperature showed up.<br />
<br />
<h2 style="text-align: left;">
Independent Polling Temperature Service</h2>
My last step was to setup a separate service on another computer that polls the temperature, verifies it, and notifies on error. I'm using a different computer because I want to get a notification if the room gets cold (below zero), and the chips on the raspberry pi are only commercial grade (0 to 70C). It would probably still work until -10C, but I still decided to keep it separate.<br />
So I wrote a python service that reads the temperature, compares it to thresholds and sends an email if it's too cold. I check the temperature hourly, but that's easily changed, I also have a very high temperature threshold because the temperature sensor reads hot (it's kept warmer than ambient by the raspberry pi) and I track the temperatures and email trends daily. If reading the temperature ever fails I also send an email, which I found to have a lot of false positives so I added a couple of retries when reading the temperature. I also write messages to syslog (I'm polling from a Linux box) so that I can easily see recent temperature readings.<br />
I did fool around with setting up my polling application as a service that would automatically restart, but didn't fully get that working.<br />
<br />
Anyway, here's my <a href="https://raw.githubusercontent.com/prlj13/temperature-poller/master/temperature_checker.py" target="_blank">temperature poller</a>. It has been running for a couple of weeks without a glitch.<br />
<br />
<h2 style="text-align: left;">
Source Email Address</h2>
One last note, I created a separate email address to send the notification emails from because I had to reduce the security on it. I don't use the email address for anything except sending these emails so if it does get hacked it's not a big deal.<br />
<br />
Let me know if you're interested in other source and I'll post that too.<br />
<br /></div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-70724360633948901042019-01-13T11:17:00.000-06:002019-01-13T11:17:09.463-06:00Accidentally Sending Emails to the Wrong Person?<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="color: #444444; font-family: monospace;"><span style="font-size: 17px;">Everyone has sent a message to the wrong person at least once. Maybe it's an text message and you accidentally respond to the wrong conversation, or added the wrong name to an email. Quite often it isn't a huge deal because of the fact we've all done it. You'll receive a message that makes absolutely no sense, maybe responding with a "?", or you get a follow up soon after telling you to please ignore it.</span></span><br />
<span style="color: #444444; font-family: monospace;"><span style="font-size: 17px;"><br /></span></span>
<span style="color: #444444; font-family: monospace;"><span style="font-size: 17px;">Sending increasing personal information is embarrassing, and in business sending private or confidential information can be a huge problem.</span></span><br />
<span style="color: #444444; font-family: monospace;"><span style="font-size: 17px;"><br /></span></span>
<span style="color: #444444; font-family: monospace;"><span style="font-size: 17px;">In Outlook, it's quite easy to add a macro that double checks the recipients before an email is sent, comparing the domain name (ex. gmail.com, companyy.com, etc.). Typically when I send emails to multiple recipients they have the same domain name, ignoring the domain of the company I work for. </span></span><br />
<span style="color: #444444; font-family: monospace;"><span style="font-size: 17px;"><br /></span></span>
<span style="color: #444444; font-family: monospace;"><span style="font-size: 17px;">So here's what I use to make sure I don't accidentally CC the wrong person. I added the VBA code at the bottom of the post to Outlook, and I get a verification popup every time I send an email to multiple domains that aren't in my ignoreDomains and ignoreStartsWith lists.</span></span><br />
<span style="color: #444444; font-family: monospace;"><span style="font-size: 17px;"><br /></span></span>
<span style="color: #444444; font-family: monospace;"><span style="font-size: 17px;">Another thing that can be done, which I do as well because quite often I think of extra things to add to an email right after sending it, is to add a rule to delay sends by X minutes.</span></span><br />
<span style="color: #444444; font-family: monospace;"><span style="font-size: 17px;"><br /></span></span>
<span style="color: #444444; font-family: monospace;"><span style="font-size: 17px;">Useful Links:</span></span><br />
<br />
<ul style="text-align: left;">
<li><a href="https://www.datanumen.com/blogs/run-vba-code-outlook/" target="_blank">Add VBA code to outlook</a></li>
<li><a href="https://stackoverflow.com/questions/16044846/run-macro-when-email-is-sent" target="_blank">How to run a macro when an email is sent</a></li>
<li><a href="https://support.office.com/en-us/article/delay-or-schedule-sending-email-messages-026af69f-c287-490a-a72f-6c65793744ba" target="_blank">Delay sending all emails by X minutes</a></li>
</ul>
<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">Option Explicit</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">Private Function ignoreDomains() As Variant</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ignoreDomains = Array("example.com", "example2.com")</span><br />
<span style="font-family: Courier New, Courier, monospace;">End Function</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">Private Function ignoreStartsWith() As Variant</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ignoreStartsWith = Array("jay@trustworthy.com", "bob@trust.com")</span><br />
<span style="font-family: Courier New, Courier, monospace;">End Function</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">Private Sub Application_ItemSend(ByVal objItem As Object, cancel As Boolean)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim email As mailItem</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim warn As Boolean</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim message As String</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> If ("MailItem" = TypeName(objItem)) Then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Set email = objItem</span><br />
<span style="font-family: Courier New, Courier, monospace;"> warn = domainMismatch(email, message)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> cancel = verifyCancelSend(warn, "This email is addressed to multiple domains." & vbCrLf & vbCrLf & message)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> End If</span><br />
<span style="font-family: Courier New, Courier, monospace;">End Sub</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">Private Function verifyCancelSend(ByRef warn As Boolean, msg As String) As Boolean</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim retVal As Boolean</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> If (warn) Then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Beep</span><br />
<span style="font-family: Courier New, Courier, monospace;"> retVal = (MsgBox(msg & vbCrLf & vbCrLf & "Would you like to cancel sending the email?", vbYesNo, "Cancel Send Confirmation") <> vbNo)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> End If</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> verifyCancelSend = retVal</span><br />
<span style="font-family: Courier New, Courier, monospace;">End Function</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">Private Function domainMismatch(mi As mailItem, message As String) As Boolean</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim retVal As Boolean</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim rc As Recipient</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim domain As String</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim baseDomain As String</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim ignoreStartValue As Variant</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim ignoreDomainValue As Variant</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim ignoreStart As Boolean</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Dim ignoreDomain As Boolean</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> message = ""</span><br />
<span style="font-family: Courier New, Courier, monospace;"> baseDomain = ""</span><br />
<span style="font-family: Courier New, Courier, monospace;"> retVal = False</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> For Each rc In mi.Recipients</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ignoreStart = False</span><br />
<span style="font-family: Courier New, Courier, monospace;"> For Each ignoreStartValue In ignoreStartsWith()</span><br />
<span style="font-family: Courier New, Courier, monospace;"> If (LCase(ignoreStartValue) = LCase(Left(rc.Address, Len(ignoreStartValue)))) Then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ignoreStart = True</span><br />
<span style="font-family: Courier New, Courier, monospace;"> End If</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Next</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> If (Not ignoreStart) Then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ignoreDomain = False</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> domain = LCase(Right(rc.Address, Len(rc.Address) - InStr(rc.Address, "@")))</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> For Each ignoreDomainValue In ignoreDomains()</span><br />
<span style="font-family: Courier New, Courier, monospace;"> If (ignoreDomainValue = domain) Then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> ignoreDomain = True</span><br />
<span style="font-family: Courier New, Courier, monospace;"> End If</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Next</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> If (Not ignoreDomain) Then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> If "" = baseDomain Then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> message = rc.Address</span><br />
<span style="font-family: Courier New, Courier, monospace;"> baseDomain = domain</span><br />
<span style="font-family: Courier New, Courier, monospace;"> End If</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> If (baseDomain <> domain) Then</span><br />
<span style="font-family: Courier New, Courier, monospace;"> retVal = True</span><br />
<span style="font-family: Courier New, Courier, monospace;"> message = message & vbCrLf & rc.Address</span><br />
<span style="font-family: Courier New, Courier, monospace;"> End If</span><br />
<span style="font-family: Courier New, Courier, monospace;"> End If</span><br />
<span style="font-family: Courier New, Courier, monospace;"> End If</span><br />
<span style="font-family: Courier New, Courier, monospace;"> Next</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> domainMismatch = retVal</span><br />
<span style="font-family: Courier New, Courier, monospace;">End Function</span><br />
<br /></div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-77417458025263955662018-04-09T20:32:00.001-05:002018-04-09T20:32:07.179-05:00How to Setup Outline VPN at Home and Save the Cloud Hosting Costs<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
A while ago I had OpenVPN setup, but it was quite a bit of work. Then I upgraded something and it broke, and I never got around to fixing it. So setting up VPN access to my home network has been on my to do list for a while. Then I noticed the release of Jigsaw's (Alphabet/Google) Outline VPN, and figured I'd give it a try.</div>
<div>
<div>
<br /></div>
<div>
Setting up Outline VPN took a lot longer than it should have because I didn't find a really good resource for installing it at home. Everything I found left out some of the key details I was interested in. Specifically, I wanted to know a bit about what's going on, and wanted to minimize the number of ports I have open and/or forwarded on my home router. </div>
<div>
<br /></div>
<div>
First, I have Ubuntu 16.04, so the steps will be best described for that OS. However, it shouldn't be that difficult to translate them to a different OS.</div>
</div>
<ol style="text-align: left;">
<li>Verify you have an externally accessible IP address. </li>
<ol>
<li>Log into the router or cable modem your ISP provided</li>
<li>Check the setup or status page</li>
<li>There will be a WAN IP address. If it's not within one of the following sets, <a href="https://en.wikipedia.org/wiki/Private_network" target="_blank">private IP addresses</a>, then you're good to go (10.0.0.0 - 10.255.255.255, 172.16.0.0 - 172.31.255.255, 192.168.0.0 - 192.168.255.255)</li>
</ol>
<li><a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-docker-on-ubuntu-16-04" target="_blank">Install Docker</a> - Follow the link for the complete steps, or try the following:</li>
<ol>
<li>curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -</li>
<li>sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"</li>
<li>sudo apt-get update</li>
<li>sudo apt-get install -y docker-ce</li>
</ol>
<li>The following steps generally following Outline VPN standard installation steps</li>
<li>Download the install script and save it locally</li>
<ol>
<li>sudo wget https://raw.githubusercontent.com/Jigsaw-Code/outline-server/master/src/server_manager/install_scripts/install_server.sh > install_server.sh</li>
</ol>
<li>Set the port used by Outline Manager, by editing install_server.sh. Then either update get_random_port to return a number between 1024 and 65535, or update the script at around line 99 to use the specific port number instead of calling get_random_port (which returns a random port)</li>
<ol>
<li>ex. Replace 'echo $num;' with 'echo 65333;'</li>
</ol>
<li>Update your router and/or firewall to forward the specific port to the computer that you're installing Outline on.</li>
<li>Install Outline VPN, execute (-x is optional, and is for debugging purposes). Take note of the apiUrl and certSha256 output at the end of the command assuming it's successful.</li>
<ol>
<li>cat install_server.sh | sudo bash -x</li>
</ol>
<li>Assuming the manager port is not blocked, the install will complete.</li>
<li>Download Outline Manager from the following site</li>
<ol>
<li>https://getoutline.org/en/home</li>
</ol>
<li>Run <i>Outline</i> <i>Manager</i> and select the bottom option</li>
<li>Enter the apiUrl and certSha256 from step 7 in the <i>Outline</i> <i>Manager</i> and click OK</li>
<li>So that you can track usage, in the connected <i>Outline Manager</i>, add a key and give it a useful name.</li>
<li>Click <i>SHARE </i>and copy the generated URL using the device you want to connect to your VPN</li>
<li>The URL will look something like the following. Again go to your firewall and/or router and forward the <PORT NUMBER> to the computer that you're installing Outline on.</li>
<ol>
<li>https://s3.amazonaws.com/outline-vpn/index.html#/invite/ss%3A%2F%2abcdefg...%3D%40<IP ADDRESS>%3A<PORT NUMBER>%2F%3Foutline%3D1</li>
</ol>
<li>Go to the URL from step 13. You will be directed to install the Outline application, and add the server.</li>
<li>You're done. To test, click <i>CONNECT </i>and try to access something from your home network<i>.</i></li>
</ol>
<br />
I use mine for my nightly backups of pictures and videos I've taken on my phone to my <a href="https://nextcloud.com/" target="_blank">NextCloud</a> installation that I don't want publicly accessible.<br />
<br />
<br />
If you run into problems during the install, stopping and removing all the related docker images will be useful:<br />
<br />
<ul style="text-align: left;">
<li>sudo docker stop shadowbox;sudo docker rm shadowbox;sudo docker stop watchtower;sudo docker rm watchtower</li>
</ul>
<br />
<br />
Useful links:<br />
<br />
<ul style="text-align: left;">
<li><a href="https://getoutline.org/en/home" target="_blank">Get Outline</a></li>
<li><a href="https://jigsaw.google.com/" target="_blank">Jigsaw</a></li>
<li><a href="https://www.reddit.com/r/outlinevpn/comments/8669py/stuck_at_starting_watchtower_ok/" target="_blank">Reddit outlinevpn</a></li>
</ul>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com1tag:blogger.com,1999:blog-24232301.post-57735171001199542932017-07-25T21:29:00.002-05:002017-07-25T21:38:07.438-05:00Your Brain, a Temple or Sacred Place<div dir="ltr" style="text-align: left;" trbidi="on">
<div>
<br /></div>
<div>
I was reading the article <a href="http://www.livemint.com/Leisure/6vLjwbrZYZUwMOpy9XO8uN/How-to-consume-news.html" target="_blank">How to consume News</a> a couple of mornings ago, and the last point must have really resonated with me because my mind wondered on the drive to work. The last point is:</div>
<div>
<br /></div>
<div>
■ Most of all, be kind and respectful to your brain. Treat it like you would treat your home or a temple or a sacred place. Control what goes in there with extreme prejudice. You have finite mental horsepower. Use it on things that are worth it.</div>
<div>
<br /></div>
<div>
So I thought, treat your mind like a temple, that's kind of like treating your body as a temple, where someone takes care of their body and what they put into it. Eating healthy, or watching what you eat can have significant benefits. Over the past couple of decades there has been a huge push towards eating healthy. The opposite, junk food, and eating it regularly negatively affects your body and overall performance, just watch <a href="https://www.youtube.com/watch?v=jAnCOHCVjyU" target="_blank">Super Size Me</a>. So junk food is bad for you and your body, is there a parallel for your brain and if so what would it be?</div>
<div>
<br /></div>
<div>
Let's think about junk food for a moment. It generally has high amounts of sugar and/or fat, and our body craves it because it's high in energy. Let's focus on sugar, where we get a burst of energy, a temporary high, followed by a low. That can start a vicious cycle of highs and lows, including mood swings.</div>
<div>
<br /></div>
<div>
Can we make parallels between junk food and information and/or news? Do we get the same highs and lows from fast breaking news? The latest terror threat, scandal, etc. Even the urge to look at an accident while you drive by somewhat seems to fit. In some cases the high, adrenaline, is longer than a sugar high, but it is temporary. We gossip about the latest thing, but then in a day or two that news is old, forgotten and didn't really benefit us in the long term. And where do reality TV shows fit, immersed in someone else's trumped up and exaggerated reality instead of your own, or to escape your own (reminds me of an episode of <a href="https://www.netflix.com/ca/title/70264888" target="_blank">Black Mirror</a>). We wasted a bunch of time and energy absorbing this unimportant information, and then we move onto the next thing.</div>
<div>
<br /></div>
<div>
What about our psyche or brains? Negative news dominates in this day and age, is this similar to how junk food once dominated our diets. Will we learn that this is unhealthy, and that we should be controlling/monitoring what our eyes and ears see and hear, how long will this take for us to learn.</div>
<div>
<br /></div>
<div>
Assuming there such a thing as junk information or junk news, we should be trying to avoid it. Our brains can only handle a certain amount of information, so what if we're bombarding them with garbage. Should we be trying to consume healthy information? Will there be a push in society to control what gets to our eyes and ears just like we do our mouths?</div>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-80229844176760562662017-05-01T22:09:00.002-05:002017-05-01T22:09:25.780-05:00Adding Feature Switches to your Django Project in 10 Minutes<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: inherit;">The first time I heard about feature switches was at a <a href="https://www.meetup.com/agilewpg/" target="_blank">Winnipeg Agile Group</a> meeting a year or two ago. They peaked my interest immediately and seemed like a must when trying to practice DevOps.</span><br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;">I wanted to try them out on my own, so I did some investigating. I have a <a href="https://www.djangoproject.com/" target="_blank">Django</a> hobby project and figured it would be a perfect target for trying out feature switches. I started by writing down some of the features I though would be useful:</span><br />
<br />
<ul style="text-align: left;">
<li>Stored in a database</li>
<li>Support changes on-the-fly</li>
<li>Global enable/disable</li>
<li>Must support multiple conditions</li>
<ul>
<li>client IP address</li>
<li>user</li>
<li>group</li>
<li>date/time</li>
</ul>
<li>Use them in several scenarios:</li>
<ul>
<li>code (models.py, views.py in Django)</li>
<li>templates (Django)</li>
<li>entire projects (urls.py in Django)</li>
</ul>
</ul>
<div>
Since Django has a lot of open source projects, I decided to do a Google search to see what's available. I found a <a href="https://djangopackages.org/grids/g/feature-flip/" target="_blank">comparison</a> with a bunch of old projects (+1 years since updated) that I avoided because they're likely not being maintained anymore, and decided to try out <a href="https://github.com/YPlan/gargoyle" target="_blank">gargoyle</a> since it had most (if not all) of the features I thought would be useful. The original project is deprecated, however Yplan forked it and is actively maintaining the project. So I downloaded the latest release and manually added it to my project. I followed their suggestion and also added <a href="https://github.com/YPlan/nexus" target="_blank">nexus</a>, then later found I needed to add the dependencies <a href="https://github.com/YPlan/django-modeldict" target="_blank">modeldict</a> and <a href="https://pypi.python.org/pypi/django-jsonfield/1.0.1" target="_blank">jsonfield</a> (link to the project that worked).</div>
<div>
<br /></div>
<div>
However, when I logged in using my admin user and tried to add my first feature switch in the nexus UI, I repeatedly got the error "Enter valid JSON". I tried a couple of different syntaxes thinking maybe it's expecting quotes, or doesn't support certain characters. No luck.</div>
<div>
<br /></div>
<div>
Then I found a <a href="https://www.bountysource.com/issues/34807032-broken-with-latest-version-of-django-jsonfield" target="_blank">compatibility post</a>, and figured maybe my jsonfield project is incompatible. So I searched for a different version. Fortunately the next version I tried fixed the problem, and I was off to the races. I had my first feature switch saved in the database.</div>
<div>
<br /></div>
<div>
Next up, add some code that uses it. Based on the really good <a href="http://gargoyle.readthedocs.io/en/latest/" target="_blank">gargoyle documentation</a>, I made a slight modification to one of my views and the corresponding template. Loading the page I found my feature switch looked like it was working. To verify I toggled the feature switch back and forth in the nexus UI and refreshed the page each time.</div>
<div>
<br /></div>
<div>
Done. That was too easy.</div>
<div>
<br /></div>
<div>
Please contact me if you have any questions, or are interested in the post and what I do. </div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Below are most of the technical details:</div>
<div>
<br /></div>
<div>
<ul style="text-align: left;">
<li>Web Framework</li>
<ul>
<li><a href="https://www.djangoproject.com/" target="_blank">Django</a>, v1.10.4</li>
</ul>
<li>Django projects</li>
<ul>
<li><a href="https://github.com/YPlan/gargoyle">https://github.com/YPlan/gargoyle</a> (v1.27)</li>
<li><a href="https://github.com/YPlan/django-modeldict">https://github.com/YPlan/django-modeldict</a> (v1.5.4)</li>
<li><a href="https://pypi.python.org/pypi/django-jsonfield/1.0.1">https://pypi.python.org/pypi/django-jsonfield/1.0.1</a> (v1.0.1)</li>
<li><a href="https://github.com/YPlan/nexus">https://github.com/YPlan/nexus</a> (v1.5.0)</li>
</ul>
<li>Don't use this one, it didn't work for me:</li>
<ul>
<li><a href="https://github.com/dmkoch/django-jsonfield">https://github.com/dmkoch/django-jsonfield</a> (v1.0.1)</li>
</ul>
<li>settings.py additions:</li>
<ul>
<li>Add 'gargoyle' and 'nexus' to INSTALLED_APPS</li>
</ul>
<li>urls.py addition:</li>
<ul>
<li>Add the following: url(r'^nexus/', include(nexus.site.urls)),</li>
</ul>
<li>view.py additions:</li>
</ul>
<div>
<div>
def index(request):</div>
<div>
<div>
if (gargoyle.is_active('feature_key', request)):</div>
<div>
switched_variable = 'enabled'</div>
<div>
else:</div>
<div>
switched_variable = 'disabled'</div>
<div>
return render(request, 'project/index.html', {'switched_variable': switched_variable })</div>
</div>
</div>
<ul style="text-align: left;">
<li>template additions:</li>
</ul>
<div>
<div>
{% load gargoyle_tags %}</div>
<div>
{% ifswitch feature_key %}</div>
<div>
<DIV>SWITCH: ENABLED</DIV></div>
<div>
{% else %}</div>
<div>
<DIV>SWITCH: DISABLED</DIV></div>
<div>
{% endifswitch %}</div>
<div>
<DIV>Switch:{{ switched_variable }}</DIV></div>
</div>
</div>
<div>
<br /></div>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-80753773971980000102017-01-03T20:40:00.002-06:002017-01-03T20:40:37.889-06:00Liferay 6.1 - connecting to LDAP server<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: justify;">
I've been working on a portal project recently using <a href="http://www.liferay.org/" target="_blank">Liferay</a>. After getting Liferay installed on a local VM I was tasked with connecting it to an LDAP server for user authentication and importing groups for permissions.<br />
<br />
Adding an LDAP server is simple. Liferay has buttons for
testing the connection, user import (with preview) and group import
(with preview) that are extremely helpful. Obviously, all of your
settings will depend on the LDAP server you're connecting to. In my
case I didn't need to change any of the user and group default
settings. I did have to change the defaults for the connection.<br />
<br />
I found that using the Liferay control panel was the best way to connect to the LDAP server and determine the settings you need. What you do with the settings after that really depends on your situation. I'm a developer, and the project required extensive Liferay customizations. Therefore, I moved the settings into an Ext plugin which we managed in SVN and deployed to multiple environments. Alternatively, each environment can be manually however you may find this to be difficult to manage.<br />
</div>
<div style="text-align: justify;">
<div style="text-align: justify;">
I wanted my own LDAP server because I needed to create my own
set of users, groups, and have complete control over the structure.</div>
<div style="text-align: justify;">
I installed <a href="http://www.openldap.org/" target="_blank">openLDAP</a>
locally and connected to it using jxplorer. Then I created a bunch of
groups and users by importing an ldif file. My database looked good,
and connecting/navigating it using jxplorer worked fine. </div>
</div>
<div style="text-align: justify;">
<div style="text-align: justify;">
To help verify/debug connecting to LDAP servers I used <a href="http://jxplorer.org/" target="_blank">jxplorer</a>, which is free and available for all of the common OSs.</div>
<div style="text-align: justify;">
</div>
<b>The Technical Details</b> </div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
In my case the LDAP server is a test server, and was really easy to connect. The hardest part was finding where the LDAP settings are located in the Liferay control panel. To get to the LDAP settings:</div>
<ol style="text-align: justify;">
<li>Login to Liferay (http://localhost:8080, in my case test@liferay.com:test)</li>
<li>Navigate to the control panel (<i>Go To</i>-><i>Control Panel</i>)</li>
<li>Then under <i>Portal </i>in the left navigation, go to <i>Authentication</i>-><i>LDAP</i></li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjFFmQqSjnaMcAmAw_cjaasO2ikMNPuhRoEwbjGhdirr-yekp6rXUW0gVk5WhfqUWZFllGNq1a2-GCZTRE80cOrBpAQvOXvpRmm-3YhxcRkgJpLIJNAVl7X0zhCZhdQcD50gJF/s1600/ldapnav.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjFFmQqSjnaMcAmAw_cjaasO2ikMNPuhRoEwbjGhdirr-yekp6rXUW0gVk5WhfqUWZFllGNq1a2-GCZTRE80cOrBpAQvOXvpRmm-3YhxcRkgJpLIJNAVl7X0zhCZhdQcD50gJF/s320/ldapnav.png" width="320" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The options for LDAP are pretty self-explanatory:</div>
<ul style="text-align: justify;">
<li>Enabled - enable LDAP authentication</li>
<li>Required - require LDAP authentication (the only exception I'm aware of is the default admin user created when first logging into Liferay)</li>
<li>Import Enabled - import LDAP users and groups into Liferay</li>
<li>Export Enabled - export user and group changes made in Liferay to LDAP</li>
<li>Use LDAP Password Policy - I recommend selecting this, otherwise when users first login they will be forced to change their password</li>
</ul>
<div style="text-align: justify;">
There are some useful <a href="http://www.liferay.com/documentation/liferay-portal/6.1/user-guide/-/ai/ldap" target="_blank">LDAP options</a> (for Liferay 6.1) that you can add to your portal-ext.properties file as well. In my case I'm using the glassfish hosted version of Liferay 6.1, so my portal-ext.properties file is in liferay-portal-6.1.20-ee-ga2/glassfish-3.1.2/domains/domain1/applications/liferay-portal/WEB-INF/classes. The following are some of the more useful settings that I used.<code><br /></code></div>
<ul style="text-align: left;">
<li><code>ldap.import.on.startup=false</code><code></code></li>
<li><code>ldap.import.interval=10</code></li>
<li><code>ldap.import.create.role.per.group = true</code></li>
<ul>
<li><code>This is to create a role for each group, and add each group member to that role</code></li>
<li><code>I use this because all our permissions are role based</code></li>
</ul>
<li><code>ldap.import.enabled=true</code></li>
<li><code>ldap.export.enabled=true</code></li>
<li><code>ldap.import.method=group </code></li>
<ul>
<li><code>Only import users that are part of groups</code></li>
<li><code>The other option is user, i.e. only import groups that have users</code></li>
</ul>
</ul>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
In my case I needed to fill out my Base DN to import the users (dc=example,dc=com).</div>
<div style="text-align: justify;">
<ul>
<li> Connection</li>
<ul>
<li>Base Provider URL - ldap://192.168.1.55:389</li>
<li> Base DN - dc=example,dc=com</li>
<li>Principal - cn=Manager,dc=example,dc=com</li>
<li>Credentials - ***** </li>
</ul>
<li>Users</li>
<ul>
<li>All defaults</li>
</ul>
<li>Groups</li>
<ul>
<li>All defaults </li>
</ul>
<li>Export</li>
<ul>
<li>Users DN - dc=example,dc=com</li>
<li>User Default Object Classes - top,inetOrgPerson,person</li>
<li>Groups DN - dc=example,dc=com</li>
<li>Group Default Object Classes - top,groupOfUniqueNames</li>
</ul>
</ul>
</div>
<br />
<b>Minor Issues I Encountered</b><br />
<br />
<div style="text-align: justify;">
The first issue you might run into is a certificate problem (if using ldaps). Logging in will simply fail, and there won't be anything in the logs either. To fix the problem you have to add the LDAP certificate to the Java cacerts store.<br />
<br />
Then, Liferay could only connect. Trying to import users and groups failed. Eventually I determined that the problem was because I hadn't added the user I use to login to LDAP to the LDAP database. I'm not sure why Liferay requires this and jxplorer doesn't, or for that matter why the user isn't automatically added to the database during installation/setup, but it's not.</div>
<div style="text-align: justify;">
<br />
During the import I ran into an problem. I had issues (debugged continually restarting Liferay and using the liferay log file which was very time consuming) with screen names. I simplified all my users so that they only contain alpha-numeric characters for all properties (cn, sn, uid, etc...).<br />
<br />
Another possible issue you may run into is how LDAP is storing passwords. By default Liferay seems to expect plain text, so that's what I'm using on my LDAP server. Obviously you don't want to do this in production. However, during development plain text is fine.<br />
<br />
<b>LDIF Snippet for Generating Users</b><br />
<br /></div>
<div style="text-align: justify;">
Here's a snippet of the LDIF file I imported to setup my users and groups (<i>LDIF->Import file</i> in jxplorer):</div>
<div style="text-align: justify;">
<br /></div>
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:DontVertAlignCellWithSp/>
<w:DontBreakConstrainedForcedTables/>
<w:DontVertAlignInTxbx/>
<w:Word11KerningPairs/>
<w:CachedColBalance/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><span style="font-family: "courier new"; font-size: 10.0pt;"></span><br />
<span style="font-family: "courier new"; font-size: 10.0pt;">dn: cn=u1,ou=users,dc=example,dc=com<br />cn: u1<br />sn: u1<br />objectClass: top<br />objectClass: inetOrgPerson<br />objectClass: organizationalPerson<br />objectClass: person<br />uid: u1<br />ou: users<br />givenName: u1<br />title: Mr.<br />mail: u1@</span><span style="font-family: "courier new"; font-size: 10.0pt;"><span style="font-family: "courier new"; font-size: 10.0pt;">liferay</span>.com<br />userpassword: u1<br /><br />dn: cn=u2,ou=users,dc=example,dc=com<br />cn: u2<br />sn: u2<br />objectClass: top<br />objectClass: inetOrgPerson<br />objectClass: organizationalPerson<br />objectClass: person<br />uid: u2<br />ou: users<br />givenName: u2<br />title: Mr.<br />mail: u2@</span><span style="font-family: "courier new"; font-size: 10.0pt;"><span style="font-family: "courier new"; font-size: 10.0pt;">liferay</span>.com<br />userpassword: u2<br /><br />dn: cn=u3,ou=users,dc=example,dc=com<br />cn: u3<br />sn: u3<br />objectClass: top<br />objectClass: inetOrgPerson<br />objectClass: organizationalPerson<br />objectClass: person<br />uid: u3<br />ou: users<br />givenName: u3<br />title: Mr.<br />mail: u3@liferay.com<br />userpassword: u3</span><br />
<br />
<br />
<span style="font-family: "courier new"; font-size: 10.0pt;">dn: cn=g1,ou=Groups,dc=example,dc=com<br />objectClass: top<br />objectClass: groupOfUniqueNames<br />cn: g1<br />description: g1<br />uniquemember: cn=u1,ou=users,dc=example,dc=com<br />ou: groups<br /><br />dn: cn=g2,ou=Groups,dc=example,dc=com<br />objectClass: top<br />objectClass: groupOfUniqueNames<br />cn: g2<br />description: g2<br />uniquemember: cn=u2,ou=users,dc=example,dc=com<br />ou: groups<br /><br />dn: cn=g3,ou=Groups,dc=example,dc=com<br />objectClass: top<br />objectClass: groupOfUniqueNames<br />cn: g3<br />description: g3<br />uniquemember: cn=u3,ou=users,dc=example,dc=com<br />ou: groups</span><br />
<span style="font-family: "courier new"; font-size: 10.0pt;"><br /></span>
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-qformat:yes;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-fareast-font-family:"Times New Roman";
mso-fareast-theme-font:minor-fareast;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
</style>
<![endif]--></div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-10073314380200020442016-04-05T21:59:00.000-05:002016-04-05T21:59:33.986-05:00Giving an old wireless router (WRT54G) a new life<div dir="ltr" style="text-align: left;" trbidi="on">
Over the holiday break, I had some spare time to work on projects around the house. One of the projects was to give my old wireless router (WRT54G) a new life as a repeater.<br />
<br />
I can't say enough about my current wireless router, an <a href="https://www.securifi.com/almondplus" target="_blank">Almond+ by Securifi</a>, it works great, it's easy to use and has tons of automation features. However, it's located at the front of my house and coverage isn't great at the back of my yard. To solve my 1st world problem, I reconfigured my old WRT54G.<br />
<br />
Here's a couple of things to keep in mind during the process:<br />
<br />
<ul style="text-align: left;">
<li>It's good to have separate internet access throughout the process so that if you have to look anything up, you can find a solution quickly. My smartphone did the trick for me.</li>
<li>Be patient, after restarting the WRT54G sometimes the web interface (LuCi) and SSH access were slow to come up (connection lost message, etc...). Wait a minute and try again</li>
</ul>
<div>
To start, I dusted off my WRT54G and got to work. I checked out openwrt, and found my router in the <a href="http://wiki.openwrt.org/toh/start" target="_blank">OpenWRT Table of Hardware</a> (make sure you pay attention to version numbers listed on the bottom of your router) and read the <a href="http://wiki.openwrt.org/toh/linksys/wrt54g" target="_blank">WRT54G device page</a>. It's a good idea to read the entire page, but really the most important section is <i>Installing OpenWRT</i>. </div>
<div>
<br /></div>
<div>
I installed backfire v10.03.1 brcm-2.4 on my v3 router. It was simple to follow their steps, and I had no problems at all.</div>
<div>
<br /></div>
<div>
Next, because I wanted to extend my existing WLAN, I configured the router to be a wireless client bridge (bridgedclient mode). You can find the recipe <a href="http://wiki.openwrt.org/doc/recipes/bridgedclient" target="_blank">here</a>.</div>
<div>
<br /></div>
<div>
The most complicated part of the process was configuring the router for my WLAN. Here are a couple of notes to help:</div>
<div>
<ul style="text-align: left;">
<li>You'll need a telnet client and/or SSH client installed on the computer you're using to access the router and configure it</li>
<li>The router is running Linux, so I used vi (<a href="http://www.lagmonster.org/docs/vi.html" target="_blank">vi cheat sheet</a>) to edit the files, which is a text editor and is a bit confusing if you're not familiar with it</li>
<li>All the configuration files are in /etc/config/</li>
<li>The default IP address of the WRT54G is in /etc/config/network, and was set to 192.168.1.1 so I had to first change my laptop's IP to the same network so that I could access the router (via a wired Ethernet connection).</li>
<li>To change my laptop's IP:</li>
<ul>
<li>Disable DHCP (control panel -> network connections -> lan connection properties -> TCP/IP v4 properties, set the IP to 192.168.1.200 and default gateway to 192.168.1.1</li>
</ul>
<li>Make sure re-enable DHCP on your laptop so that you can access the WRT54G after it is restarted</li>
</ul>
</div>
<br />
So that I don't forget the static IP of my WRT54G, I wrote it on the bottom of the device. Then I plugged it in near the back of my house, and now I have extended WLAN coverage.</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-54177204462051784332016-02-27T12:48:00.000-06:002016-02-27T12:48:45.724-06:00Why is the JVM on my Linux Server using so much CPU?<div dir="ltr" style="text-align: left;" trbidi="on">
<span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">Once in a while the CPU usage on one of our development servers rails and hits 100% and never lets up. A couple of times it actually hit 200% (2 threads burning 2 cores at 100%) or more before we noticed. These are not good situations, and something you want to get to the bottom of and fix before it starts happening in your production environment.</span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">The lazy thing to do is restart the entire server, or restart the process that's railed. But this is just ignoring the problem. Avoidance is what you should be doing. Here's how you get to the bottom of what's going on:</span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">1. Get the PID causing the problem, run <i>top </i>to get the list of processes using the most CPU<i>, </i>it'll be the first entry. As you can probably guess, it was my JVM.</span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">2. Get the IDs of the threads in the process causing the problem (my PID was 2089): <i>top -H -p 2089</i></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /> PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND<br />11405 liferay 20 0 11.7g 6.8g 14m R 99.4 88.5 23074:07 java<br />10000 liferay 20 0 11.7g 6.8g 14m R 99.4 88.5 23079:00 java<br /> 3390 liferay 20 0 11.7g 6.8g 14m S 3.9 88.5 22:42.06 java<br /> 2089 liferay 20 0 11.7g 6.8g 14m S 0.0 88.5 0:00.02 java<br /> 2098 liferay 20 0 11.7g 6.8g 14m S 0.0 88.5 0:01.85 java<br /> 2111 liferay 20 0 11.7g 6.8g 14m S 0.0 88.5 3:15.03 java<br /> 2112 liferay 20 0 11.7g 6.8g 14m S 0.0 88.5 3:11.32 java</span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">From the top listing, it's easy to see the first two threads are the problem, 11405 and 10000 are using almost 100% of the CPU each. Convert the thread IDs to hex for step 4.</span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">11405 -> 0x2C8D<br />10000 -> 0x2710</span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">3. Take a thread dump of your JVM: <i>/usr/java/jdk1.6.10/bin/jstack<wbr></wbr> 2089 > /tmp/td.log</i></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">4. Search your thread dump for the threads causing your problem (found in step 2). For example, I found the following:</span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">"pool-400-thread-53" prio=10 tid=0x00007fde4801efd0 nid=0x2c8d runnable [0x00007fdde3ba4000]<br /> java.lang.Thread.State: RUNNABLE<br /> at java.util.HashMap.getEntry(Has<wbr></wbr>hMap.java:347)</span> at java.util.HashMap.containsKey(<wbr></wbr>HashMap.java:335)<br />
at java.util.HashSet.contains(Has<wbr></wbr>hSet.java:184)<br />
at com.vaadin.ui.CustomTable.unre<wbr></wbr>gisterPropertiesAndComponents(<wbr></wbr>CustomTable.java:2322)<br />
at com.vaadin.ui.CustomTable.getV<wbr></wbr>isibleCellsNoCache(CustomTable<wbr></wbr>.java:2219)<br />
<span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"> ...</span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">Looking through the stack trace for 0x2c8d, I was eventually able to find a custom class and a line number that allowed me to narrow down the source of the problem.</span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">Finding the general area of the problem is usually the easy part. The hard part is eliminating the source of the problem, which I'll leave up to you.</span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0">Good luck.</span><span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><br /></span></div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-70760142557479293792016-01-25T20:18:00.001-06:002016-01-25T20:18:25.979-06:00Beware of Liferay on a GlassFish Application Server<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr">
If you're using Liferay to build a portal or website, I highly recommend using Liferay with bundled Tomcat. Learn from other's headaches, it's not worth the trouble of trying to use something other than Tomcat.<br />
<br />
Originally, we were trying to use GlassFish 3.x.x because we have a support contract. We got our environments up and running reasonably quickly. Our environments were the following:<br />
<br />
<ul style="text-align: left;">
<li><i>Local Dev</i> (Windows 7) - Tomcat7 (bundled Liferay Developer Studio), MySQL V5 DB</li>
<li><i>Dev</i> (Ubuntu VM) - Liferay 6.1.2 deployed to GlassFish , MySQL V5 DB</li>
<li><i>Test</i> (RHEL) - Liferay 6.1.2 deployed to GlassFish , Oracle 10G</li>
<li><i>QA</i> (RHEL) - Liferay 6.1.2 deployed to GlassFish, Oracle 10G</li>
<li><i>Production</i> (RHEL) - Liferay 6.1.2 deployed GlassFish, Oracle 10G</li>
</ul>
<br />
Once we started doing significant work, developing portlets and customizing Liferay (hooks, themes, ext plugin, etc...) we started running into problems.<br />
<br />
I had difficulties migrating data between environments, which was important early in development. While trying to migrate the database from one environment to another (Control Panel -> Server -> Administration -> Data Migration), I repeatedly got errors and the migration failed. I determined that migrating from one environment to another never worked when using Liferay deployed to GlassFish. The migrations always failed with a null pointer exception. Analysing the error in the logs and a Google search didn't lead to a solution to the problem.<br />
<br />
However, I did eventually find a workaround for migrating data between environments, but it wasn't practical due to our network configuration (Firewalls blocking traffic between certain environments). The workaround was to connect my <i>Local Dev</i> environment, by temporarily modifying my portal-ext.properties file, to the source database for the data migration. Basically I found that the version of Liferay bundled with Tomcat was the only Liferay installation able to perform the data migration successfully.<br />
<br />
We did encounter other problems using GlassFish as well. We put a lot of effort into clustering Liferay deployed to GlassFish without success. After scouring the Liferay forums and discussing our options with Liferay support we decided to give up on GlassFish and use Tomcat instead.<br />
<br />
After switching to Tomcat, we had clustering working with minimal effort and our data migration issues were solved. In hindsight we would have saved a lot of time and effort by simply using Tomcat from the start. It's important to note as well, that we haven't had any stability/reliability issues due to Tomcat, and have almost been live for 2 years. </div>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-27520935797642914112015-05-04T23:14:00.000-05:002015-05-04T23:14:39.504-05:00Polishing your Portal with a High-Load Page<div dir="ltr" style="text-align: left;" trbidi="on">
When your servers become overloaded with requests, they're unable to your end users with the experience you desire. It's important in these situations to fail gracefully so that your end users (customers, employees or whomever it may be) don't become frustrated with your site. We wanted to provide a customized high-load page so that our site:<br />
<br />
<ul>
<li>Fails gracefully for users trying to connect, and minimally affects users who are already connected</li>
<li>Looks a more polished and professional</li>
<li>Is guaranteed to provide a known QoS to our customers</li>
</ul>
<br />
The portal we're customizing is based on Liferay. In our case, we didn't like the error page that Liferay provides by default when using the <i>session.max.allowed</i> property, so we decided to do some customizations. <br />
<br />
To do so we added a redirect to a high load page based on the user session count. The high load page is an extremely simple page. We're using static HTML served by Tomcat, and we made it as light weight as possible. Serving the page with Apache HTTP would be better, however we don't have the option to do so in our system.<br />
<br />
There were 4 steps to adding this page:<br />
<br />
1. Add custom properties to portal-ext.properties file<br />
<br />
2. Create a class that tracks the session count<br />
<div>
- Use a listener to track the number of sessions , increasing count on creation and decreasing count on destroy</div>
- There are several examples of doing this on the web, i.e.<div>
- http://tomcat-configure.blogspot.ca/2009/01/tomcat-session-listener-example.html</div>
<div>
- The listener must be added to the web.xml in your Liferay ext plugin<br /><br />3. Check session count in all desired classes that extend HttpServlet<br /> - Must be done in the Liferay ext plugin, follow proper ext patterns explained at www.liferay.com<br /> - If too high (above threshold in portal-ext.properties), redirect to low load page and invalidate session<br /> - Redirection page should be in portal-ext.properties to allow it to be reconfigured without recompiling the code (and redeploying the ext plugin)<br /><br />4. Create a very simple target page that will result in minimal server load<br /> - In our case I just created a directory in webapps (using tomcat) with an index.html file</div>
<div>
- index.html contained simple message explaining we're experiencing higher than normal load, please re-visit the site later</div>
<div>
<br />
<br /></div>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-2965698723257563672015-02-13T22:10:00.002-06:002015-02-13T22:15:17.171-06:00Automatically Email Zigbee/Z-wave Sensor Changes from the Almond+ WiFi Router<div dir="ltr" style="text-align: left;" trbidi="on">
Disclaimer: I do not work for Securifi<br />
<br />
Last year I backed the <a href="https://www.kickstarter.com/projects/2037429657/almond-80211ac-touchscreen-wifi-router-smart-home" target="_blank">Almond+ WiFi router on Kickstarter</a> (<a href="http://www.securifi.com/" target="_blank">Securifi</a>). After a couple of delays which weren't entirely unexpected from this type of project, I received it in the mail. Since then, it has been working quite well.<br />
<br />
Before delivering the <a href="http://www.securifi.com/almondplus" target="_blank">Almond+</a>, Securifi sent out an option for backers to order sensors from them. Since they were ~$30 each, I figured I would get a couple and try them out. I ordered a flood sensor, AC switch, window/door switch and a motion sensor.<br />
<br />
Securifi has a cloud service that allows you to remotely connect to your router, monitor sensors, etc... They're working on pushing sensor statuses to a mobile app you install on your smartphone, however last I checked they have some bugs they're still fixing. There are several people waiting patiently for this functionality, including myself. I also decided to quickly code a poller.<br />
<br />
Since you can get sensor statuses from the routers web interface, I decided to write a python polling script that will scrape the sensor values from your router and send an email whenever they change. I threw the script together pretty quickly, so it's not the greatest code but it works.<br />
<br />
I setup the script as a service that automatically runs on startup on a computer running Ubuntu Linux.<br />
<br />
A couple of quick notes:<br />
<ul style="text-align: left;">
<li>Update all the xxxx in the Python source code as appropriate</li>
<li>You may have to tweak ALMOND_URL for different versions of firmware</li>
<ul>
<li>I have version Software Version : AP2-R070-L009-W016-ZW016-ZB005 </li>
</ul>
<li>I did have issues with the gmail password, and had to follow some steps found at the accounts website (see comment above variable) to setup the application</li>
<li>With a couple of changes, I'm sure you can get it working with email services other than gmail, or if you're more ambitious change it entirely to use some other communication (twitter, ifttt would be very powerful, etc...)</li>
<li>I added a bit of code to interpret the status of the sensors I have, I haven't tried it with any other sensors but I don't see why they wouldn't work</li>
<ul>
<li>Custom code can easily be added for other sensors to make their status more human readable </li>
</ul>
</ul>
Click <a href="https://drive.google.com/file/d/0B_Hz84A_T3fRM1RybnowUmxqQmc/view?usp=sharing" target="_blank">here </a>for the Python source code.<br />
<br />
Post any questions, suggestions, and changes/additions you make in the comments section below.<br />
<br /></div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-21635185258941153892013-10-07T18:29:00.002-05:002013-10-07T18:29:31.016-05:00How do you deploy multiple versions of the same portlet in Liferay?<div dir="ltr" style="text-align: left;" trbidi="on">
While developing a portal site, it can be very helpful to support deploying multiple versions of the same portlet. Some of the reasons that our development team have encountered include:<br />
<br />
<ul style="text-align: left;">
<li>Helping to debug issues that are introduced in new versions</li>
<li>Comparing functionality and performance between two portlets, while keeping everything else equal</li>
<li>Comparing functionality and performance between two portlets, while keeping everything else equal</li>
<li>When a portlet is used multiple times on a single site, it can be advantageous to use multiple versions of the same portlet so that all dependent portlets don't have to be updated when new features are added to the portlet that is used multiple times</li>
<li>In Liferay, JAR files are not cleaned up when a portlet is redeployed. Therefore, if the JAR files a portlet uses are updated and it is redeployed, both the original JAR files and new JAR files will be in the <i>lib</i> directory. This can cause issues if the new JAR files contain different versions of classes.</li>
<ul>
<li>We have run into this situation a couple of times, and it leads to confusing and unexpected results</li>
</ul>
</ul>
To properly version a portlet, you need to do two things which we achieved by adding version numbers to both:<br />
<ol style="text-align: left;">
<li>Make the directory the war file is deployed to unique so that Liferay treats them as separate portlets (in the <i>webapps</i> directory)</li>
<li>Make the name of the portlet that shows up in Liferay's Add menu unique so that you can control the version of the portlet that is added to a page, and later on determine which version of the portlet is on each page </li>
</ol>
<b>Controlling <i>webapps</i> directory</b><br />
<br />
Through experimentation, I found that the <i>webapps</i> directory is based on the WAR filename. The exact WAR filename is used as the name of the <i>webapps</i> directory, except when the WAR filename contains the string "-portlet". When the WAR filename contains specific character sequences, everything after them is ignored. The character sequences that I know about are: <i>-portlet; -hook; -ext. </i>Here are a couple of examples:<br />
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
</div>
<table border="1" cellpadding="0" cellspacing="0" class="MsoTableGrid" style="border-collapse: collapse; border: medium none; height: 127px; margin-left: auto; margin-right: auto; text-align: left; width: 492px;">
<tbody>
<tr style="mso-yfti-firstrow: yes; mso-yfti-irow: 0;">
<td style="border: 1pt solid windowtext; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
<b style="mso-bidi-font-weight: normal;">WAR Filename</b></div>
</td>
<td style="-moz-border-bottom-colors: none; -moz-border-left-colors: none; -moz-border-right-colors: none; -moz-border-top-colors: none; border-color: windowtext windowtext windowtext -moz-use-text-color; border-image: none; border-style: solid solid solid none; border-width: 1pt 1pt 1pt medium; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
<b style="mso-bidi-font-weight: normal;"><i style="mso-bidi-font-style: normal;">webapps</i> directory</b></div>
</td>
</tr>
<tr style="mso-yfti-irow: 1;">
<td style="-moz-border-bottom-colors: none; -moz-border-left-colors: none; -moz-border-right-colors: none; -moz-border-top-colors: none; border-color: -moz-use-text-color windowtext windowtext; border-image: none; border-right: 1pt solid windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
calendar_1.0.3.1.war</div>
</td>
<td style="border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-style: none solid solid none; border-width: medium 1pt 1pt medium; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
calendar_1.0.3.1/</div>
</td>
</tr>
<tr style="mso-yfti-irow: 2;">
<td style="-moz-border-bottom-colors: none; -moz-border-left-colors: none; -moz-border-right-colors: none; -moz-border-top-colors: none; border-color: -moz-use-text-color windowtext windowtext; border-image: none; border-right: 1pt solid windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
calendar_1_0_4_0.war</div>
</td>
<td style="border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-style: none solid solid none; border-width: medium 1pt 1pt medium; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
calendar_1_0_4_0/</div>
</td>
</tr>
<tr style="mso-yfti-irow: 3;">
<td style="-moz-border-bottom-colors: none; -moz-border-left-colors: none; -moz-border-right-colors: none; -moz-border-top-colors: none; border-color: -moz-use-text-color windowtext windowtext; border-image: none; border-right: 1pt solid windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
myportlet-portletAA.war</div>
</td>
<td style="border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-style: none solid solid none; border-width: medium 1pt 1pt medium; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
myportlet-portlet/</div>
</td>
</tr>
<tr style="mso-yfti-irow: 4;">
<td style="-moz-border-bottom-colors: none; -moz-border-left-colors: none; -moz-border-right-colors: none; -moz-border-top-colors: none; border-color: -moz-use-text-color windowtext windowtext; border-image: none; border-right: 1pt solid windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
crazystuff-ext.war</div>
</td>
<td style="border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-style: none solid solid none; border-width: medium 1pt 1pt medium; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
crazystuff-ext/</div>
</td>
</tr>
<tr style="mso-yfti-irow: 5; mso-yfti-lastrow: yes;">
<td style="-moz-border-bottom-colors: none; -moz-border-left-colors: none; -moz-border-right-colors: none; -moz-border-top-colors: none; border-color: -moz-use-text-color windowtext windowtext; border-image: none; border-right: 1pt solid windowtext; border-style: none solid solid; border-width: medium 1pt 1pt; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
myaccount-hook12-production.war</div>
</td>
<td style="border-color: -moz-use-text-color windowtext windowtext -moz-use-text-color; border-style: none solid solid none; border-width: medium 1pt 1pt medium; padding: 0in 5.4pt; text-align: left; width: 239.4pt;" valign="top" width="319"><div class="MsoNormal" style="line-height: normal; margin-bottom: 0.0001pt;">
myaccount-hook/</div>
</td>
</tr>
</tbody></table>
<br />
<b>Controlling the portlet name (in Liferay)</b><br />
<br />
The first thing that needs to be done is to make the portlet ID unique so that Liferay can track it. The portlet id is in liferay-display.xml. I simply concatenate the version number onto the end of the portlet ID.<br />
<br />
Next is to update the portlet name. The name must be updated and kept consistent in portlet.xml and liferay-portlet.xml. To be consistent, I simply concatenate the version number to the end of the portlet name.<br />
<br />
One thing to keep in mind is that there is a <a href="https://issues.liferay.com/browse/LPS-34663" target="_blank">known </a><a href="https://issues.liferay.com/browse/LPS-34663" target="_blank">bug </a>in
Liferay, where an exception is thrown if the portlet name has a
hyphen ('-') in it. We also found issues with periods ('.') in the
name and in the WAR filename. So what we do is avoid using either of these characters (as well as spaces), and
replace them with underscores ('_').<br />
<br />
<b>Maven</b><br />
<br />
<br />
In our case, we are using Maven. So to simplify portlet versioning, we keep the version number in the POM file and variables throughout the other files where necessary. The variables are automatically replaced with the version number when the WAR file is generated.<br />
<br />
In the POM file we setup the WAR filename to be <i>${pom.name}_${pom.version}.war</i> to minimize the number of changes required when changing the name and version of the portlet or hook. Note that Maven can't be used with ext plugins.<br />
<br /></div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com1tag:blogger.com,1999:blog-24232301.post-32280222879787255682013-08-05T21:17:00.003-05:002013-12-24T09:41:27.369-06:00Liferay - Multi-Stage Development and Data Management<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr">
Our development environments and data migration strategy is
something that has evolved during the project, and will continue to
evolve during development. Process and design improvements are
encouraged and investigated in an attempt to optimize the end product.</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
When multiple developers are involved in a large project,
multi-staging is extremely important. It allows developers to work
simultaneously and independently, without affecting each other. It also
allows stability and loss testing along with a bunch of advantages. The
number of stages required should depend on several things (this is obviously not a complete list):</div>
<ul style="text-align: left;">
<li>
Size of the project</li>
<li>
Complexity</li>
<li>
Number of developers</li>
</ul>
<div style="text-align: left;">
Two stages is the minimum required for any project, one for development
and one for production. However, it's highly recommended to have a <i>Test </i>environment between <i>Development </i>and <i>Production</i>. The <i>Test </i>environment
should be identical, or at least as close to the <i>Production</i> development
as possible to minimize risk when deploying updates to <i>Production</i>.</div>
<div style="text-align: left;">
<br />
In our situation we have three stages, which are:</div>
<ul style="text-align: left;">
<li>
Development</li>
<li>
Test</li>
<li>
Production</li>
</ul>
<div style="text-align: left;">
Furthermore, we are currently debating adding a fourth stage, QA, that
would be always kept identical to the <i>Production</i> environment.</div>
<div style="text-align: left;">
<br /></div>
<div dir="ltr">
To meet our requirements, the <i>Production </i>environment is
designed to be highly available with session replication. Each stage
incrementally becomes more similar to the <i>Production </i>environment. The
incremental changes spread out the issues that are due to environment
variations, easing debugging. Each environment is designed specifically
for a purpose. </div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
Initial development is performed on a local desktop or
laptop, which is not listed above. The local environment is the most
flexible, easily restarted and best for independent development and
debugging. Each developer has a complete environment running locally on
their desktop/laptop. This environment, which is used for rapid
development, initial integration and testing by the developer,
debugging, etc... It gives developers the maximum freedom to work
without affecting each other, which is very important near the start of
the project because restarting services is quite common. Locally we're
developing using Liferay Developer Studio on Microsoft Windows.</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
We're using <i>Development </i>for initial integration between
developers and testing. It is running on RHEL. The <i>Test </i>environment
adds session replication, is located in a DMZ with public access and
uses an Oracle database. The differences in the development and great
environment increase reliability and performance. They also make the
test environment extremely similar to the <i>Production</i> environment.</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
Data migration between environments quickly became important to synchronize<br />
configurations and reduce overall effort. We use built in features of Liferay to migrate documents, content and configurations.</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
To migrate web content as well as documents, we export and
import LAR (Liferay ARchive) files. They're easy to use, however
sometimes we notice issues with improper migration and have to repeat
the export and/or import. Issues we've encountered include missing
content and permissions.</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
You can use staging to migrate pages and other
configuration, however we we are using the database migration (Control
Panel -> Server Administration -> Data Migration) in Liferay.
Data migration is a bit more work to use, but right now we aren't
synchronizing individual pages -- which is the main advantage of staging
-- we generally want to synchronize everything.</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
The headaches that go along with database migration are
having to initialize the target database (shutting down the instance of
Liferay that's using the database, and deleting all tables within the
database) and then restarting both Liferay instances. It is much more
powerful though, allowing us to migrate from any environment to another.
We find that it is extremely useful to migrate from <i>Development </i>or <i>Test</i>
to our local environment during integration and testing. It will also
be important to migrate from production to test, development or locally
when debugging and trying to recreate problems that occur in production.</div>
<div dir="ltr">
<br /></div>
<div dir="ltr">
To aid with data migration we switched from using the
default hypersonic database to using MySQL in all the environments
before test. The <i>Test </i>and <i>Production </i>environments are using an Oracle
database. Using mysql was done for several reasons. </div>
<ol style="text-align: left;">
<li>Allows database backups and quick restores because the
database does sometimes become corrupt. We have nightly backups of our
local and development databases.</li>
<li>Allows database migration to and from any environment</li>
<li>Allows direct access to the database for debugging and clearing lock records (Lock_ table)</li>
</ol>
<div dir="ltr">
Originally we were hosting Liferay on Glassfish, but we ran
into several issues including session replication and data migration.
Since then we have switched to using tomcat as our application server,
and have not had any application server problems since.</div>
<div dir="ltr">
<br /></div>
So for now, we have a pretty complete development strategy
with respect to staging, backups and data migration. We did not arrive
at this state right away. Several of the decisions were made during
development in an attempt to streamline processes, reduce effort,
improve efficiency and end up with a more easily maintainable end
product; something that our team is constantly working to achieve.</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-60223229700007449002013-06-08T11:11:00.003-05:002013-06-08T11:11:54.846-05:00RSS - Replacing Google Reader with ifttt and email<div dir="ltr" style="text-align: left;" trbidi="on">
I used to be a Google Reader user, and used it religiously. I used the web interface, and had NewsRob on my phone. It was great. Where ever I was, I had access to all my news feeds, and never missed an article. I had my feeds nicely organized by subject, and kept on top of them. Checking my feeds was a regular part of my day, quickly skimming titles for articles I was interested in and archiving items using other tools so that I could read them later when I had the time.<br />
<br />
When I heard that Google Reader was getting axed I wasn't sure what I'd change to. I tried a couple of alternatives that people posted (ex.<a href="http://lifehacker.com/5990881/five-best-google-reader-alternatives" target="_blank"> Lifehacker's Five Best Google Reader Alternatives</a>). Specifically <a href="http://www.feedly.com/" target="_blank">Feedly </a>and <a href="http://www.netvibes.com/" target="_blank">NetVibes</a>, but they weren't quite what I was looking for. NetVibes is good, but I had periodic synchronization issues (entire RSS feeds would become unread) and it only syncs 100 items at a time, so it isn't that useful offline.<br />
<br />
I continued to use NetVibes for a month or so, and then it clicked. I was interacting with feeds a lot like email (and in fact Google started using the same UI for both Google Reader and Gmail). So I figured why not just develop something that will convert RSS feed items into emails, then just use whatever email client I want to manage the articles. Some of the advantage of managing feed items as emails is that:<br />
<ul style="text-align: left;">
<li>Email addresses are free</li>
<li>Email is sticking around and commonly used </li>
<li>There are numerous email clients</li>
<li>A lot of people are working on improving email clients and managing emails</li>
</ul>
I had developing a daemon that read RSS feeds and generated emails based on them on my to do list for a while. I knew it wouldn't be too difficult to do, because I had developed daemons that generated emails previously (I wrote a simple one in Python that checked the stock status of the Nexus 4 every 5 minutes and sent me an email when it changed).<br />
<br />
The much easier solution, which I came to before wasting development work, was to use <a href="http://www.ifttt.com/" target="_blank">ifttt</a>. I already use it to forward specific <a href="https://plus.google.com/" target="_blank">G+</a> posts to <a href="http://www.yammer.com/" target="_blank">Yammer</a>, <a href="http://www.twitter.com/" target="_blank">Twitter</a>, etc... and it works great.<br />
<br />
I created recipes for each RSS feed I follow. I configured the recipes so that they're easy to manage <br />
within ifttt and the emails are easily manageable. Here are the steps I followed to get setup:<br />
<ul style="text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGxG7Gzn3Qsuf3P08deVgA38dirlFyokjV2PXGQusTynHdkoa0WQym3stsgK6LvAvVA20zE0q-W8jVXzx45ZpA35DvM9tpivv44geYPvlr0djDYXd0tmByXQwBFK3imUWOA7Fb/s1600/overview.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGxG7Gzn3Qsuf3P08deVgA38dirlFyokjV2PXGQusTynHdkoa0WQym3stsgK6LvAvVA20zE0q-W8jVXzx45ZpA35DvM9tpivv44geYPvlr0djDYXd0tmByXQwBFK3imUWOA7Fb/s200/overview.png" width="200" /></a>
<li>Sign up for a gmail account</li>
<li>Sign up for an ifttt account</li>
<li>Create a recipe for each RSS feed</li>
<ul>
<li>Add RSS tag to recipe description (#RSS)</li>
<li>Add RSS feed name to recipe description</li>
<li>Trigger: RSS feed (need the URL)</li>
<li>Action: Send an email, prefix the subject with an acronym for the RSS feed</li>
</ul>
</ul>
The prefixes in the subject allow you to quickly look through items and determine the feed they came from. You can also use the prefix to sort/filter incoming emails and redirect them to folders (most email) or add the appropriate labels (gmail).<br /><div>
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMEUUtX2lfNm8kj61_7jzdnEnx1um6eHyxbymrZyfbpdNSI19I5Vue8EnW5a7R-wjMCM0oyqsuzj3Eebx-PMjXVxtT0E5zThVCCJ_G12YfS27o8MgOTu2wrCjur53JF3NsNuH1/s1600/details.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgMEUUtX2lfNm8kj61_7jzdnEnx1um6eHyxbymrZyfbpdNSI19I5Vue8EnW5a7R-wjMCM0oyqsuzj3Eebx-PMjXVxtT0E5zThVCCJ_G12YfS27o8MgOTu2wrCjur53JF3NsNuH1/s320/details.png" width="188" /></a><br />
<br />
Archiving items for reading later or reference is very easy to do with emails as well, which is another nice benefit.<br />
<br />
Some final notes: <br />
<ul style="text-align: left;">
<li>You can use an existing email address. If you do, I suggest adding something in the subject line of the email that allows you to create a custom filter to separate the feed items from normal emails.</li>
<li>Keep the prefixed used in the subject short so that it doesn't dominate the subject line space when looking at the emails in your email client (especially when using a small screen like your phone)</li>
</ul>
<br /></div>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-61378315639949269602013-03-05T12:51:00.002-06:002013-03-05T15:08:37.264-06:00Remote Contractors - Lessons Learned<div dir="ltr" style="text-align: left;" trbidi="on">
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
<w:DontFlipMirrorIndents/>
<w:OverrideTableStyleHps/>
<w:UseFELayout/>
</w:Compatibility>
<w:DoNotOptimizeForBrowser/>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><br />
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="0" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
</style>
<![endif]--><br />
<h1 style="mso-list: l1 level1 lfo2;">
<span style="mso-bidi-font-family: Cambria; mso-fareast-font-family: Cambria;"><span style="mso-list: Ignore;"></span></span></h1>
<h2 class="MsoListParagraph" style="margin-left: 0in; text-align: justify;">
<b><span style="font-weight: normal;"><span style="font-size: large;"><b>1. Executive Summary</b></span></span></b></h2>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
A customer contracted us to update one of their applications. Since the project was not technically challenging and involved a significant amount of repetitive effort, outsourcing was deemed to be low risk.</div>
<div class="Textbody" style="text-align: justify; text-justify: inter-ideograph;">
The
project trials outsourcing development effort to remote contractors in an
effort to better understand what is involved and when outsourcing is beneficial.<span style="mso-spacerun: yes;"> </span>To reduce development costs and maximize
profits, as well as the highly repetitive nature of the project, it was decided
that some of the development effort would be outsourced.</div>
The following describes project details and focuses primarily
on lessons learned while working with remote contractors.<br />
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
<br /></div>
<h2 style="text-align: left;">
<span style="font-size: large;">2.<span style="font-size: large;"> </span><span style="-moz-font-feature-settings: normal; -moz-font-language-override: normal; font-family: "Times New Roman"; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;"></span>Introduction</span></h2>
<h3 style="text-align: left;">
<span style="font-size: small;">2.1.<span style="-moz-font-feature-settings: normal; -moz-font-language-override: normal; font-family: "Times New Roman"; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;">
</span>Objectives</span></h3>
<div class="Textbody" style="text-align: justify; text-justify: inter-ideograph;">
The
purpose of the project was to upgrade an existing application.<span style="mso-spacerun: yes;"> </span><span style="mso-spacerun: yes;"></span>The application utilizes a couple of different
technologies and programming languages. The required updates were clearly defined by the client.</div>
<br />
<h3 style="text-align: left;">
<span style="font-size: small;">2.2.<span style="-moz-font-feature-settings: normal; -moz-font-language-override: normal; font-family: "Times New Roman"; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;">
</span>Approach</span></h3>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
The approach was to outsource part of the project to contract developers
based in India.<span style="mso-spacerun: yes;"> </span>This was done as a
trial, with the desire to exploit outsourcing in future projects.<span style="mso-spacerun: yes;"> </span>The project was selected as an ideal
candidate for outsourcing because the effort and tasks were well known and low
risk.<span style="mso-spacerun: yes;"> </span></div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
It was decided to outsource as much of the
development as possible, while keeping any complicated development effort internal.<span style="mso-spacerun: yes;"> </span>This
was done because the design pattern for a significant amount of the effort is quite straight-forward, so it can be easily
documented, taught to contractors, and reviewed for adherence.</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
Other development effort was kept internal because there was a
desire to increase the knowledgebase of developers within the company, adding
to their familiarity with the development environment and applications.<span style="mso-spacerun: yes;"> </span>For the project, it was important to keep the
knowledge base and experience in-house, so specific less repetitive tasks were
not outsourced.<span style="mso-spacerun: yes;"> </span>We also wanted to keep
the more interesting and challenging work internal to benefit employees and to
ensure it was done properly.</div>
<div class="MsoNormal" style="text-align: justify; text-justify: inter-ideograph;">
<br /></div>
<h2 style="text-align: left;">
<span style="font-size: large;">3.<span style="-moz-font-feature-settings: normal; -moz-font-language-override: normal; font-family: "Times New Roman"; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;">
</span>Lessons Learned</span></h2>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
There are several lessons learned from the project, including
ones specific to outsourcing effort.</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
<br /></div>
<h3 style="text-align: left;">
<span style="font-size: small;">3.1.<span style="-moz-font-feature-settings: normal; -moz-font-language-override: normal; font-family: "Times New Roman"; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;">
</span>Development Environment</span></h3>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
Due to the limited overlap of business hours, it’s very easy
to waste time getting development environments working.<span style="mso-spacerun: yes;"> </span>Originally, the plan was to host a couple of
Virtual Machines (VM) locally and get the contractors to remotely access
them.<span style="mso-spacerun: yes;"> </span>This would allow us to tightly
control and monitor the development environment used by contractors, as well
has limiting their access to the end customer’s source code.<span style="mso-spacerun: yes;"> </span>However, this did not work at all.<span style="mso-spacerun: yes;"> </span>The latency that the contractors were
observing made development extremely difficult.<span style="mso-spacerun: yes;">
</span>Typing and mouse movements were likely delayed by approximately
one-third of a second (ping www.pluggd.in).</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
To eliminate the latency issue, VMs were packaged and made
available to the developers.<span style="mso-spacerun: yes;"> </span>In my
opinion, remote contractors have to use local development environments for a
majority of their work to be productive.<span style="mso-spacerun: yes;">
</span></div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
I highly recommend using VMs to encapsulate the development
environment.<span style="mso-spacerun: yes;"> </span>If this approach is taken,
the following steps can help the process go smoothly:<br />
<ul style="text-align: left;">
<li>Have the VM packaged and available well before
the start date of the contractors. </li>
<li>Transferring it will take a significant amount
of time.</li>
<li>If possible, get them to transfer it over the
weekend to minimize wasted hours</li>
<li>Contractors should use a user with the minimum
amount of permissions required</li>
<li>Thoroughly test the VM remotely to ensure it
will work for the contractors right away, and for the entire project.<span style="mso-spacerun: yes;"> </span>It is difficult to make changes to the VM
after the fact</li>
</ul>
</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
If a development environment is going to be provided to
contractors that they can install, provide a detailed step-by-step installation
guide, making it as simple as possible.</div>
<div class="Textbody">
<br /></div>
<h3 style="text-align: left;">
<span style="font-size: small;">3.2.<span style="-moz-font-feature-settings: normal; -moz-font-language-override: normal; font-family: "Times New Roman"; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;">
</span>Productivity and Task Assignment</span></h3>
<div class="MsoNormal" style="text-align: justify; text-justify: inter-ideograph;">
Initially,
assume that contractors require very specific tasks that include detailed
descriptions.<span style="mso-spacerun: yes;"> </span>Concisely specifying tasks
minimize assumptions and will ensure that they are completed as desired.<span style="mso-spacerun: yes;"> </span>Assumptions likely differ due to differences
in education, culture and project familiarity.<span style="mso-spacerun: yes;">
</span>After a while, once becoming more comfortable with the work and
capabilities of the contractors, the level of detail required in descriptions
can probably be reduced.</div>
<div class="MsoNormal" style="text-align: justify; text-justify: inter-ideograph;">
Assume
that contractors will take 3-5 days to get familiar with new development
patterns.<span style="mso-spacerun: yes;"> </span>During this period, progress
will be slow.<span style="mso-spacerun: yes;"> </span>Once familiar, the
contractors will reach their full potential and productivity will peak.<span style="mso-spacerun: yes;"> </span>This is most relevant for highly repetitive
tasks.</div>
<div class="MsoNormal" style="text-align: justify; text-justify: inter-ideograph;">
From
experience with this project, it’s safe to assume that contractors will work
slower and will be less efficient than local resources.<span style="mso-spacerun: yes;"> </span>Without doing significant investigation into
the numbers, it’s assumed that the contractors were approximately 75% as
productive.<span style="mso-spacerun: yes;"> </span>This could be due to various
reasons such as: language barrier; no direct supervision outside of their
company; individual capabilities.<span style="mso-spacerun: yes;"> </span>An
exact number could be calculated by analyzing the estimated and actual hours of
work items for various resources tracked in Rational Team Concert (RTC).</div>
<div class="Textbody" style="text-align: justify; text-justify: inter-ideograph;">
Expect
to spend 30-60 minutes per day reviewing the work of the contractors to ensure
quality.<span style="mso-spacerun: yes;"> </span>Initially, 2-3 hours of review was
required because there was a lot of feedback required.<span style="mso-spacerun: yes;"> </span>This review time decreased to 30-60 minutes
once they became familiar with the design pattern.</div>
<div class="Textbody" style="text-align: justify; text-justify: inter-ideograph;">
RTC
was used to manage work items and as a code repository.<span style="mso-spacerun: yes;"> </span>Although RTC has tools and workflows that are
designed for reviewing and accepting developer’s code into the repository, only
the reviewing functionality was used.<span style="mso-spacerun: yes;">
</span>The reviewing functionality allowed us to efficiently examine proposed
changes, including source code diffs and syntax highlighting.<span style="mso-spacerun: yes;"> </span>The ability to accept and reject submitted
source code changes would have been useful.<span style="mso-spacerun: yes;">
</span>However, it was not used due to lack of familiarity with RTC.</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
Due to the learning curve, keeping contractors working on
similar and repetitive tasks was most efficient.<span style="mso-spacerun: yes;"> </span>Each time a work item with a different work
flow was started there was a learning curve that had to be overcome.<span style="mso-spacerun: yes;"> </span>This included the contractor being less productive,
as well as requiring more supervision, review and feedback.<span style="mso-spacerun: yes;"> </span>Expect the learning curve to be larger than
with local resources, likely due to less overlap in business hours, indirect
contact and a language barrier causing miscommunications.</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
Be wary whenever a new task or workflow is being performed by
contractors.<span style="mso-spacerun: yes;"> </span>Review the results
closely.<span style="mso-spacerun: yes;"> </span>The contractors tended to be
good at repeating tasks, however struggled with new tasks that required
undefined design patterns.<span style="mso-spacerun: yes;"> </span>For example,
they struggled with extending development patterns to other source code languages.<span style="mso-spacerun: yes;"> </span>Design patterns had to be
clearly defined and documented.<span style="mso-spacerun: yes;"> </span>Then,
the contractors were trained and their initial work closely monitored.</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
Getting the contractors to do testing and validation work
didn’t work very well.<span style="mso-spacerun: yes;"> </span>They missed some
relatively obvious defects introduced during the updates, both in the
user interface and the business logic of the application.<span style="mso-spacerun: yes;"> </span>It must be noted though, that they weren’t
pushed very hard or given a lot of time for this work.<span style="mso-spacerun: yes;"> </span>Given more time and direction, they may have
been more successful.<span style="mso-spacerun: yes;"> </span>Last, they may
have had difficulties with testing and validation work because they didn’t
fully understand the applications.<span style="mso-spacerun: yes;">
</span>Further training would have helped with this.</div>
<div class="Textbody" style="text-align: justify; text-justify: inter-ideograph;">
<br /></div>
<h3 style="text-align: left;">
<span style="font-size: small;">3.3.<span style="-moz-font-feature-settings: normal; -moz-font-language-override: normal; font-family: "Times New Roman"; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;">
</span>Communication</span></h3>
<div class="MsoNormal" style="text-align: justify; text-justify: inter-ideograph;">
The
contractors were provided with a class and methods that encapsulated most of
the changes required.<span style="mso-spacerun: yes;"> </span>This greatly simplified their training,
development workflow and effort.<span style="mso-spacerun: yes;"> </span>It also
minimized their changes, which in turn reduced the possibility of introducing
bugs, straying from the design pattern, and our source code review effort.</div>
<div class="MsoNormal" style="text-align: justify; text-justify: inter-ideograph;">
A
design document was also provided to the contractors, clearly detailing their aspect
of the project, development environment and their work flow.<span style="mso-spacerun: yes;"> </span>Examples of all the source code that required
updating was provided in the document.<span style="mso-spacerun: yes;"> </span>However, the design document alone was not
enough.<span style="mso-spacerun: yes;"> </span>A screen sharing session with a
Skype conference call was used to step through the workflow they were to
follow.<span style="mso-spacerun: yes;"> </span>The screen sharing session was
definitely required, and was likely more effective than the design document.</div>
<div class="Textbody" style="text-align: justify; text-justify: inter-ideograph;">
As it
is with managing any inexperienced or unfamiliar resource, it was important to frequently
follow up with them, ensure that they are working on tasks, that they were
keeping busy and hadn’t hit a roadblock.<span style="mso-spacerun: yes;">
</span>Often roadblocks were easily solved by a second set of eyes, and
resources tended to avoid asking for help or advice and remain
unproductive.<span style="mso-spacerun: yes;"> </span>It was made clear to
contact us whenever running into issues and/or if they had nothing to work on. <span style="mso-spacerun: yes;"> </span>This was fundamental to keeping the developers
productive.<span style="mso-spacerun: yes;"> </span>Note that it is still important
to regularly check up on them because sometimes they don’t realize the problem,
or continue working without realizing they are astray.</div>
<div class="Textbody" style="text-align: justify; text-justify: inter-ideograph;">
It is
important to provide all possible contact information, and the situation to use
each communication path.<span style="mso-spacerun: yes;"> </span>Several methods
of communication were provided, including phone, Skype calling, Skype IM, email
and comments on work items in RTC.<span style="mso-spacerun: yes;"> </span>Each
has advantages and disadvantages, and it’s important to use them effectively
and for the contractors to feel that you’re easily accessible.</div>
<div class="Textbody" style="text-align: justify; text-justify: inter-ideograph;">
At
times the contractors chose the wrong method of communication.<span style="mso-spacerun: yes;"> </span>Therefore, it’s important to correct them
ASAP and clearly define the method of communication that is appropriate for
each situation or problem.<span style="mso-spacerun: yes;"> </span>For example,
adding a comment to a work item is great and highly recommended for
documentation purposes.<span style="mso-spacerun: yes;"> </span>However, if the
contractor is blocked and can’t continue working until the comment is resolved,
adding a comment to a work item is not adequate.<span style="mso-spacerun: yes;"> </span>Feedback on the comment could be delayed,
leaving the contractor waiting and unproductive.<span style="mso-spacerun: yes;"> </span>Therefore, some other form of communication
that guarantees immediate feedback should also be used.</div>
<div class="Textbody">
<br /></div>
<h3 style="text-align: left;">
<span style="font-size: small;">3.4.<span style="-moz-font-feature-settings: normal; -moz-font-language-override: normal; font-family: "Times New Roman"; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;">
</span>Online Project Management Software</span></h3>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
Online project management software is essential when working
with remote contractors.<span style="mso-spacerun: yes;"> </span>To properly
manage resources and keep them productive, documenting, assigning and queuing
tasks is required.<span style="mso-spacerun: yes;"> </span>Documenting the tasks
reduces the need for direct communication, and queuing tasks ensures there is a
backlog of work to keep resources busy.<span style="mso-spacerun: yes;">
</span>Both are important because there is a reduced number of overlapping work
hours that allow direct communication regarding issues and new tasks.<span style="mso-spacerun: yes;"> </span>Maintaining a queue of tasks keeps developers
busy even when there is not the time to assign more work due to higher
priorities and distractions.</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
Repositories of tasks that include details and estimated
effort, are assigned to developers and are regularly updated also allow
managers to monitor progress and productivity on their own time without interfering
with developers.<span style="mso-spacerun: yes;"> </span>It is also a relatively
good documentation tool.</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
It is good practice to maintain a queue of tasks for resources
to work on so that if they hit a roadblock and others are not available to help
remove the roadblock, developers will not run out of tasks to work on.<span style="mso-spacerun: yes;"> </span>They can document the roadblock and request
help, then move onto another task while waiting for feedback.<span style="mso-spacerun: yes;"> </span>If appropriate, it also allows developers to
select tasks from a shortlist of equal priority tasks.<span style="mso-spacerun: yes;"> </span>This gives them a bit of variety and
empowerment, helping to keep them interested in the project and work when they
need a change of pace.</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
When using online project management software, it is
imperative that all resources involved in the project use the repository and
keep it up to date.<span style="mso-spacerun: yes;"> </span>Otherwise the
repository becomes dated and useless, and can’t be used for documentation
purposes.</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
The online project management software used for the project
was RTC.<span style="mso-spacerun: yes;"> </span>It was more than adequate for
the project, and provides several features that were not exploited.<span style="mso-spacerun: yes;"> </span>It was only used for source control and to
create and manage work items.<span style="mso-spacerun: yes;"> </span>Arguably,
it was overkill for the size and requirements of the project, and at times
seemed slow and cumbersome.</div>
<div class="MsoListParagraph" style="margin-left: 0in; text-align: justify; text-justify: inter-ideograph;">
Some alternatives to RTC are Redmine, Trac and Trello.<span style="mso-spacerun: yes;"> </span>Redmine and Trac are both open source free
alternatives that can easily be self-hosted.<span style="mso-spacerun: yes;">
</span>They provide the ability to manage and schedule tasks, as well as
integration into external source code repositories.<span style="mso-spacerun: yes;"> </span>Trello is a hosted solution that seems to be
well suited to Agile development.<span style="mso-spacerun: yes;"> </span>The
interface is very intuitive and easy to use, although it does lack effort
tracking, and general reporting and status features.<span style="mso-spacerun: yes;"> </span>Last, since Trello is not internally hosted,
before using it you should review their privacy statement and avoid including
sensitive information.</div>
<div class="Textbody">
<br /></div>
<h2 style="text-align: left;">
<span style="font-size: large;">4.<span style="-moz-font-feature-settings: normal; -moz-font-language-override: normal; font-family: "Times New Roman"; font-size-adjust: none; font-stretch: normal; font-style: normal; font-variant: normal; font-weight: normal; line-height: normal;">
</span>Conclusion and Recommendations</span></h2>
<div class="MsoNormal" style="text-align: justify; text-justify: inter-ideograph;">
There
is a lot of potential in reducing costs by outsourcing development to remote
contractors.<span style="mso-spacerun: yes;"> </span>However, overlooking the
added management and learning curves could be costly.<span style="mso-spacerun: yes;"> </span>For the project involved, the development
outsourced was primarily focused on updating an existing application,
which involved relatively simple work flows and the development was highly
repetitive.<span style="mso-spacerun: yes;"> </span>By doing so, management,
learning curves and code reviews were minimized.<span style="mso-spacerun: yes;"> </span>The contractors were involved with a very
limited amount of development that was more technically challenging, so it’s
difficult to determine how effective outsourcing this type of development would
be.</div>
<div class="MsoNormal" style="text-align: justify; text-justify: inter-ideograph;">
Due
to latency issues, it should be assumed that remote contractors must develop
using local environments.<span style="mso-spacerun: yes;"> </span>The
communications latency present when contractors access remote environments is
far too great to be productive.<span style="mso-spacerun: yes;"> </span>So that
a project utilizing outsourcing starts more smoothly in the future, a complete development
environment should be created, verified, packaged and delivered to the
contractors prior to their starting date.<span style="mso-spacerun: yes;">
</span>Development workflows and expectations should be well documented and provided
to the contractors as well.<span style="mso-spacerun: yes;"> </span>Furthermore,
these should be reviewed with each contractor via a phone or Skype call, and a screen
sharing session.</div>
<div class="MsoNormal" style="text-align: justify; text-justify: inter-ideograph;">
Online
project management software is a necessity due to the geographic distribution
of the project team and the limited overlap of business hours.<span style="mso-spacerun: yes;"> </span>It allows assigning tasks to developers,
creating backlogs of tasks to keep developers busy during non-overlapping
business hours, along with the ability to clearly define implementation
details.<span style="mso-spacerun: yes;"> </span>This allows managers to keep
resources tasked throughout the project.</div>
<div class="MsoNormal" style="text-align: justify; text-justify: inter-ideograph;">
<br /></div>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-280390521402561022013-01-18T16:34:00.001-06:002013-01-18T16:48:54.871-06:00Tips to Maximize Productivity - Cygwin<div dir="ltr" style="text-align: left;" trbidi="on">
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
<w:DontFlipMirrorIndents/>
<w:OverrideTableStyleHps/>
<w:UseFELayout/>
</w:Compatibility>
<w:DoNotOptimizeForBrowser/>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><br />
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="0" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
</style>
<![endif]-->
<br />
<div class="MsoListParagraphCxSpFirst" style="margin-left: 0in; mso-add-space: auto; tab-stops: list 0in; text-align: justify; text-justify: inter-ideograph;">
<a href="http://www.cygwin.com/">Cygwin</a> is a project of a collection of tools
that provides a Linux console based environment to Windows.<span style="mso-spacerun: yes;"> </span>It is free software.</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; mso-add-space: auto; tab-stops: list 0in; text-align: justify; text-justify: inter-ideograph;">
When
internationalizing an application, matching keys in the source code with lines
in properties files is a relatively large task.<span style="mso-spacerun: yes;">
</span>Going through the entire application for each language, and ensuring all
properties referenced in the source code are also listed in the property files
is time consuming.</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; mso-add-space: auto; tab-stops: list 0in; text-align: justify; text-justify: inter-ideograph;">
An even
more quick and efficient method of finding missing keys is to write scripts to
parse the source code.<span style="mso-spacerun: yes;"> </span>Scripts that
parse the source code for keys and match the keys with keys located in the
property files can be written using Cygwin and some creativity.<span style="mso-spacerun: yes;"> </span>Cygwin provides a command prompt that gives
access to a collection of common Linux/UNIX tools.<span style="mso-spacerun: yes;"> </span>By employing tools including <i>find, xargs,
cat, grep, sed, wc, sort </i>and<i> diff</i>, mismatched keys can easily be
found.<span style="mso-spacerun: yes;"> </span>This includes keys either located
in the source code or property file and not in the other, as well as duplicate
keys.</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; mso-add-space: auto; tab-stops: list 0in; text-align: justify; text-justify: inter-ideograph;">
These tools
can be used for other tasks as well:</div>
<br />
<ul style="text-align: left;">
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Searching projects for strings</li>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span><span style="font-family: "Courier New";">C</span>ounting instances of specific strings for
estimating effort</li>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Listing files that require translation so that
they can be added to tasks/work items</li>
<ul>
<li><span style="font-family: "Courier New"; mso-fareast-font-family: "Courier New";"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Calculating
line counts of the files to estimate effort</li>
</ul>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Generating repetitive script files that apply
changes to a database</li>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Mass renaming of files</li>
</ul>
An example of one of a script that I created, full of relatively complicated commands to get keys used within properties files is the following, where getEscapedHTMLString and getEscapedJavaScriptString are methods that are called every time the properties file is accessed. It took several attempts to get correct and was built slowly piece-by-piece. The result is a sorted list of all the property keys referenced in code.java. I added echos throughout to display progress.<br />
<br />
#!/bin/bash<br /># copy Java files<br />echo Cleaning local directory...<br />rm -f *.java .properties PROPERTY_* JAVA<br />echo Copying Java source files...<br />find /cygdrive/c/s<wbr></wbr>rc/ | grep "java" | xargs -I file cp file .<br />rm Internationalizer.java<br /># copy properties files<br />echo Copying properties files...<br />cp /cygdrive/c/s<wbr></wbr>rc/XXX*.properties .<br /># get all property entries from Java source into file JAVA<br />echo Parsing Java source files...<br />cat *.java | sed "s/in\.get/\nin\.get/g;s/\")/\<wbr></wbr>")\n/g" | grep "getEscape\|getPlain" | sed "s/in.getEscapedHTMLString//g;<wbr></wbr>s/in.getEscapedJavaScriptStrin<wbr></wbr>g//g;s/in.getPlainString//g;s/<wbr></wbr>(\"//g;s/\"[ ,a-zA-Z0-9)]*)[\;]*//g" | sort > JAVA<br /># get all property entries from property files into file PROPERTY<br />echo Parsing properties files...<br />cat PIOS_en_CA.properties | sed "s/=.*//g" | sort > PROPERTY_EN<br /># Output properties missing in properties file<br />echo Missing English Properties \(PIOS_en_CA.properties\)<br />diff --ignore-blank-lines --ignore-all-space JAVA PROPERTY_EN | grep "<"<br />echo \*\* PROPERTY KEYS THAT ARE USED MULTIPLE TIMES IN JAVA SOURCE WILL BE REPORTED \*\*<br />echo Removing copied files...<br />rm -f *.java .properties PROPERTY_* JAVA <br />
<br />
I used this script frequently to match keys referenced in the source code with property file keys. This ensured I wouldn't get exceptions during execution, and quickly scanned for common typos.<br />
It's also really useful to estimate effort. In the same project, translation effort was estimated by the number of lines of code that needed internationalization. I took the complete list of files and broke them down into functional categories to make testing/verification easier. Then, to quickly determine the number of lines (which was later converted to effort in hours), a ran the following which outputs the total number of lines:<br />
<br />
<span class="DescriptionSpan readonly-text" style="display: block;" tabindex="0"><span>cat file1.java file2.java file3.java file4.java | wc -l</span></span><br />
<br />
The last, and another relatively simple example is breaking a massive log file into pieces. A client didn't have rotating logs implemented on their server, which resulted in a 2GB log file. Obviously the log file is much to large to open and analyze as is. However, by using split it's really easy to break the file into multiple manageable files.<br />
The nice thing is, all of this is command-line based, so it's resource efficient and generally won't tie up your computer. It's also extremely easy to save bash scripts for reference or repeating execution.<br />
<br />
<ul style="text-align: left;">
</ul>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-72242980098183560372012-12-21T16:44:00.000-06:002012-12-21T16:55:22.358-06:00Tips to Maximize Productivity - Sikuli<div dir="ltr" style="text-align: left;" trbidi="on">
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
<w:DontFlipMirrorIndents/>
<w:OverrideTableStyleHps/>
<w:UseFELayout/>
</w:Compatibility>
<w:DoNotOptimizeForBrowser/>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><br />
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="0" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
</style>
<![endif]-->
<br />
<div class="MsoNoSpacing" style="text-align: justify; text-justify: inter-ideograph;">
<a href="http://sikuli.org/">Sikuli</a> is an open-source research project
developed at MIT and is released under the MIT License.<span style="mso-spacerun: yes;"> </span>It can be used for countless tasks, and
scripts can be exported to an executable to simplify execution.<span style="mso-spacerun: yes;"> </span>It is also Windows, Linux and Mac OS X
compatible.</div>
<div class="MsoNoSpacing" style="text-align: justify; text-justify: inter-ideograph;">
Sikuli
is a technology that allows you to automate interacting with graphical user
interfaces (GUI) using screenshots and keystrokes. <span style="mso-spacerun: yes;"> </span>Developers can quickly write scripts, written
in Python, which interact with any GUI including applications and web
pages.<span style="mso-spacerun: yes;"> </span>Sikuli is a heavier utility than
AutoHotKey. <span style="mso-spacerun: yes;"> </span>However it is much more
powerful and serves a different purpose.<span style="mso-spacerun: yes;">
</span>The feature that distinguishes Sikuli is interacting with GUIs based on
screenshots.<span style="mso-spacerun: yes;"> </span>Partial screenshots are
added directly to your script as arguments to methods including click,
double-click, find and exists.<span style="mso-spacerun: yes;"> </span>When
executed, the desired GUI interaction is achieved using image pattern matching
with the screen.</div>
<div class="MsoListParagraphCxSpFirst" style="margin-left: 0in; mso-add-space: auto; mso-list: l1 level1 lfo1; tab-stops: list 0in; text-align: justify; text-indent: 0in; text-justify: inter-ideograph;">
Another nice thing about Sikuli is that it is an automation
tool with scripts written in a full-blown programming language, Python.<span style="mso-spacerun: yes;"> </span>This allows you to write complex scripts that
support interacting in a flexible and adaptable manner based on external and
unknown dependencies.<span style="mso-spacerun: yes;"> </span>Scripts can interact
with error messages, log results, and iterate a number of times that is unknown
during programming and based on GUI elements.</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; mso-add-space: auto; mso-list: l1 level1 lfo1; tab-stops: list 0in; text-align: justify; text-indent: 0in; text-justify: inter-ideograph;">
Here are some examples of tasks that can be automated with
Sikuli (website and/or application):</div>
<br />
<ul style="text-align: left;">
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Boundary testing</li>
<li>Exhaustively testing user options</li>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>User Acceptance Testing (UAT)</li>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Regression testing</li>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Applying a base load</li>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Automatically setting user preferences, changing
configuration, opening applications, etc… when logging into a computer</li>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Automate repetitive steps or tasks during development
or debugging</li>
<ul>
<li><span style="font-family: "Courier New"; mso-fareast-font-family: "Courier New";"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Ex.
Logging in and navigating to a specific area of a website or application</li>
</ul>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Any repetitive task</li>
</ul>
<img alt="" height="337" src="data:image/png;base64,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" width="400" /> <br />
<ul style="text-align: left;">
</ul>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-84462714482093388142012-12-18T15:30:00.001-06:002012-12-18T15:30:51.696-06:00Java Based Internationalization Made Easier<div dir="ltr" style="text-align: left;" trbidi="on">
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
<w:DontFlipMirrorIndents/>
<w:OverrideTableStyleHps/>
<w:UseFELayout/>
</w:Compatibility>
<w:DoNotOptimizeForBrowser/>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--><br />
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="0" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
</style>
<![endif]-->
<br />
<div class="MsoListParagraphCxSpFirst" style="margin-left: 0in; mso-add-space: auto; mso-list: l0 level1 lfo1; tab-stops: list 0in; text-align: justify; text-indent: 0in; text-justify: inter-ideograph;">
Internationalizing Java applications includes highly
repetitive tasks.<span style="mso-spacerun: yes;"> </span>The standard method is
to use a property file per supported language, which effectively contains a
look-up table of content that is presented in the user interface.<span style="mso-spacerun: yes;"> </span>Hard-coded content displayed in the user
interface is moved into properties files, and is replaced with unique
keys.<span style="mso-spacerun: yes;"> </span>Initially, the following syntax
was used for naming keys:</div>
<br />
<ul style="text-align: left;">
<li><source
file name>.<description></li>
</ul>
<br />
<div class="MsoListParagraphCxSpMiddle" style="mso-list: l0 level3 lfo1; tab-stops: list .5in left 71.45pt; text-align: justify; text-indent: 0in; text-justify: inter-ideograph;">
<br /></div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; mso-add-space: auto; mso-list: l0 level1 lfo1; tab-stops: list 0in; text-align: justify; text-indent: 0in; text-justify: inter-ideograph;">
The format allowed developers to quickly determine where
the key is used in the source code.<span style="mso-spacerun: yes;"> </span>It
also helped provide translators the general area of the user interface the content
is used, thus providing a bit of context.<span style="mso-spacerun: yes;">
</span>Later in the project, translators requested further information to
narrow down context even further.<span style="mso-spacerun: yes;"> </span>The
following format, which includes a look-up value used to indicate descriptor
(button, label, link, title, etc...), was used:</div>
<br />
<ul style="text-align: left;">
<li><source
file name>.<descriptor>.<description>
</li>
</ul>
<br />
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; mso-add-space: auto; mso-list: l0 level1 lfo1; tab-stops: list 0in; text-align: justify; text-indent: 0in; text-justify: inter-ideograph;">
Note that keys are only used once within each application
to maximize translation flexibility.<span style="mso-spacerun: yes;"> </span>We
wanted to avoid forcing translators to use the same content in multiple places,
which could result in incorrect contexts.<br />
In general, internationalizing applications is not a
technically difficult task.<span style="mso-spacerun: yes;"> </span>However, it
is time consuming, repetitive, monotonous work and therefore prone to
errors.<span style="mso-spacerun: yes;"> </span>Anything that can be done to
minimize errors due to this is highly recommended.<br />
Syntax highlighting source code editors are hugely
advantageous when internationalizing applications.<span style="mso-spacerun: yes;"> </span>These editors allow developers to efficiently
scan source code for literals, which is where content that requires translating
resides.<span style="mso-spacerun: yes;"> </span><br />
However, these editors can't provide syntax highlighting
for languages within languages which is sometimes the case.<span style="mso-spacerun: yes;"> </span>For example, Java source code literals can contain
HTML source, which in turn contains JavaScript.<span style="mso-spacerun: yes;">
</span>Source inside of source is important because different escape sequences
are required.<br />
<div class="MsoListParagraphCxSpFirst" style="margin-left: 0in; mso-add-space: auto; mso-list: l0 level1 lfo1; tab-stops: list 0in; text-align: justify; text-indent: 0in; text-justify: inter-ideograph;">
To simplify the effort, a class should be used to maximize
code reuse in the application.<span style="mso-spacerun: yes;"> </span>Create
methods in the class that perform common tasks such as returning text based on
a properties file key, adding escape sequences to content based on the target
language (HTML, JavaScript, JavaScript within HTML) and formatting numbers.</div>
I found that using tools like AutoHotKey to automate common
tasks was extremely beneficial.<span style="mso-spacerun: yes;"> </span>I
created a shortcut that copied the currently selected text to the clipboard and
replaced the text with a method call to the internationalization object,
including the source file name as the argument.<span style="mso-spacerun: yes;">
</span>The appropriate quotes and concatenation operators were also
included.<span style="mso-spacerun: yes;"> </span>Then I only had to type in a
description for the text, and put the corresponding entry in the appropriate
property files.<span style="mso-spacerun: yes;"> </span>With minimal ingenuity,
AutoHotKey can automate most of the task of inserting the entry in the property
files as well.<span style="mso-spacerun: yes;"> </span>Basically any task/key
sequence you are doing repeatedly can be added to AutoHotKey. <br />
After changing my development to use AutoHotKey, I found
that the number of errors was significantly reduced.<span style="mso-spacerun: yes;"> </span>Originally, I had a relatively large amount
of typos, missing and out of order letters, etc… in the source code and
property files.<span style="mso-spacerun: yes;"> </span>Afterwards, these were
almost entirely eliminated.<span style="mso-spacerun: yes;"> </span>Furthermore,
I was internationalizing the source code much faster than before.
</div>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-37440548324546702692012-12-04T12:52:00.003-06:002012-12-04T12:52:58.393-06:00Tips to Maximize Productivity - AutoHotKey and KeyText<div dir="ltr" style="text-align: left;" trbidi="on">
<div style="text-align: left;">
<!--[if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:TrackMoves/>
<w:TrackFormatting/>
<w:PunctuationKerning/>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:DoNotPromoteQF/>
<w:LidThemeOther>EN-US</w:LidThemeOther>
<w:LidThemeAsian>X-NONE</w:LidThemeAsian>
<w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript>
<w:Compatibility>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:SplitPgBreakAndParaMark/>
<w:EnableOpenTypeKerning/>
<w:DontFlipMirrorIndents/>
<w:OverrideTableStyleHps/>
<w:UseFELayout/>
</w:Compatibility>
<w:DoNotOptimizeForBrowser/>
<m:mathPr>
<m:mathFont m:val="Cambria Math"/>
<m:brkBin m:val="before"/>
<m:brkBinSub m:val="--"/>
<m:smallFrac m:val="off"/>
<m:dispDef/>
<m:lMargin m:val="0"/>
<m:rMargin m:val="0"/>
<m:defJc m:val="centerGroup"/>
<m:wrapIndent m:val="1440"/>
<m:intLim m:val="subSup"/>
<m:naryLim m:val="undOvr"/>
</m:mathPr></w:WordDocument>
</xml><![endif]--></div>
<div style="text-align: left;">
<!--[if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"
DefSemiHidden="true" DefQFormat="false" DefPriority="99"
LatentStyleCount="267">
<w:LsdException Locked="false" Priority="0" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Normal"/>
<w:LsdException Locked="false" Priority="9" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="heading 1"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8"/>
<w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9"/>
<w:LsdException Locked="false" Priority="39" Name="toc 1"/>
<w:LsdException Locked="false" Priority="39" Name="toc 2"/>
<w:LsdException Locked="false" Priority="39" Name="toc 3"/>
<w:LsdException Locked="false" Priority="39" Name="toc 4"/>
<w:LsdException Locked="false" Priority="39" Name="toc 5"/>
<w:LsdException Locked="false" Priority="39" Name="toc 6"/>
<w:LsdException Locked="false" Priority="39" Name="toc 7"/>
<w:LsdException Locked="false" Priority="39" Name="toc 8"/>
<w:LsdException Locked="false" Priority="39" Name="toc 9"/>
<w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption"/>
<w:LsdException Locked="false" Priority="10" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Title"/>
<w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font"/>
<w:LsdException Locked="false" Priority="11" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtitle"/>
<w:LsdException Locked="false" Priority="22" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Strong"/>
<w:LsdException Locked="false" Priority="20" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Emphasis"/>
<w:LsdException Locked="false" Priority="59" SemiHidden="false"
UnhideWhenUsed="false" Name="Table Grid"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text"/>
<w:LsdException Locked="false" Priority="1" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="No Spacing"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 1"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 1"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 1"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 1"/>
<w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision"/>
<w:LsdException Locked="false" Priority="34" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="List Paragraph"/>
<w:LsdException Locked="false" Priority="29" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Quote"/>
<w:LsdException Locked="false" Priority="30" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Quote"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 1"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 1"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 1"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 1"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 1"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 2"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 2"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 2"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 2"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 2"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 2"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 2"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 2"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 2"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 3"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 3"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 3"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 3"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 3"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 3"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 3"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 3"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 3"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 4"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 4"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 4"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 4"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 4"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 4"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 4"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 4"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 4"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 5"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 5"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 5"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 5"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 5"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 5"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 5"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 5"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 5"/>
<w:LsdException Locked="false" Priority="60" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Shading Accent 6"/>
<w:LsdException Locked="false" Priority="61" SemiHidden="false"
UnhideWhenUsed="false" Name="Light List Accent 6"/>
<w:LsdException Locked="false" Priority="62" SemiHidden="false"
UnhideWhenUsed="false" Name="Light Grid Accent 6"/>
<w:LsdException Locked="false" Priority="63" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6"/>
<w:LsdException Locked="false" Priority="64" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6"/>
<w:LsdException Locked="false" Priority="65" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 1 Accent 6"/>
<w:LsdException Locked="false" Priority="66" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium List 2 Accent 6"/>
<w:LsdException Locked="false" Priority="67" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6"/>
<w:LsdException Locked="false" Priority="68" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6"/>
<w:LsdException Locked="false" Priority="69" SemiHidden="false"
UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6"/>
<w:LsdException Locked="false" Priority="70" SemiHidden="false"
UnhideWhenUsed="false" Name="Dark List Accent 6"/>
<w:LsdException Locked="false" Priority="71" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Shading Accent 6"/>
<w:LsdException Locked="false" Priority="72" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful List Accent 6"/>
<w:LsdException Locked="false" Priority="73" SemiHidden="false"
UnhideWhenUsed="false" Name="Colorful Grid Accent 6"/>
<w:LsdException Locked="false" Priority="19" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis"/>
<w:LsdException Locked="false" Priority="21" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis"/>
<w:LsdException Locked="false" Priority="31" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference"/>
<w:LsdException Locked="false" Priority="32" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Intense Reference"/>
<w:LsdException Locked="false" Priority="33" SemiHidden="false"
UnhideWhenUsed="false" QFormat="true" Name="Book Title"/>
<w:LsdException Locked="false" Priority="37" Name="Bibliography"/>
<w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading"/>
</w:LatentStyles>
</xml><![endif]--><!--[if gte mso 10]>
<style>
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:"Table Normal";
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0in 5.4pt 0in 5.4pt;
mso-para-margin-top:0in;
mso-para-margin-right:0in;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0in;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}
</style>
<![endif]-->
</div>
<div class="MsoListParagraphCxSpFirst" style="margin-left: 0in; text-align: justify;">
<b style="mso-bidi-font-weight: normal;">Problem:</b></div>
<div class="MsoListParagraphCxSpMiddle" style="text-align: justify;">
There isn’t enough time in the day to get
everything done.<span style="mso-spacerun: yes;"> </span>There’s always more to
do, and the general pace of things seems to be ever increasing.<span style="mso-spacerun: yes;"> </span>Optimizing time usage is an ongoing
challenge, as well as trying to avoid or minimize mundane and repetitive tasks.</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; text-align: justify;">
<b style="mso-bidi-font-weight: normal;">Solution:</b></div>
<div class="MsoListParagraphCxSpMiddle" style="text-align: justify;">
Using tools to improve productivity and
carry out repetitive and mundane tasks frees you up for more important tasks.<span style="mso-spacerun: yes;"> </span>They reduce errors that people commonly make
when performing tasks over and over.<span style="mso-spacerun: yes;">
</span>Last, they can quite often perform tasks faster.</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; text-align: justify;">
<br /></div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; text-align: justify;">
<a href="http://www.autohotkey.com/"><span style="mso-bidi-font-style: italic;">AutoHotKey</span></a>
is an open source Windows utility provided under the GNU General Public
License.<span style="mso-spacerun: yes;"> </span><a href="http://www.keytext.com/"><span style="mso-bidi-font-style: italic;">KeyText</span></a>
is a Windows utility that is free to evaluate for 30 days.<span style="mso-spacerun: yes;"> </span></div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; text-align: justify;">
AutoHotKey
and KeyText are extremely useful to automate repetitive and/or common
day-to-day tasks such as typing class names, method names and property keys
along with the appropriate syntax for ending and restarting literals within the
source code.<span style="mso-spacerun: yes;"> </span>They can also be used to
search for content, copying it to the clipboard and replacing it, as well as
pasting clipboard contents into properties files.<span style="mso-spacerun: yes;"> </span>Using these tricks can significantly reduce
the amount of typos and errors.<span style="mso-spacerun: yes;">
</span>Furthermore, less typing is required, which reduces development time and
effort.</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; text-align: justify;">
AutoHotKey
and KeyText can also be used to automate interacting with relatively complex
user interfaces.<span style="mso-spacerun: yes;"> </span>Although the
development interface is limited, the utilities can produce mouse clicks (based
on x-y coordinates relative to the selected window) and keystrokes.<span style="mso-spacerun: yes;"> </span>When combined to form complex sequences, it
is possible to automate compiling, releasing, creating backups, logging into
applications and other repetitive time consuming tasks.<span style="mso-spacerun: yes;"> </span>These sequences are mapped to keyboard
shortcuts, allowing developers to program the utilities with multiple different
sequences, each being used to simplify a specific task.</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; text-align: justify;">
As all
developers know, just because an application compiles doesn't mean that it
works.<span style="mso-spacerun: yes;"> </span>For example, a common problem when
internationalizing applications is missing keys in the property file.<span style="mso-spacerun: yes;"> </span>To combat this, try-catch statements can be
added to the appropriate methods, returning content an easily noticeable error
statement that includes the name of the missing key.<span style="mso-spacerun: yes;"> </span>The message can also be written to a log file
or the console, further easing development and finding bugs.</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-left: 0in; text-align: justify;">
Here’s a
list of some of the tasks that I have recently used these utilities for:</div>
<div style="text-align: left;">
</div>
<ul style="text-align: left;">
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Login to application being developed</li>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Automatically navigate to part of application
being developed</li>
<li><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Internationalization of applications<span style="font-family: "Courier New"; mso-fareast-font-family: "Courier New";"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"> </span></span></span></li>
<ul>
<li><span style="font-family: "Courier New"; mso-fareast-font-family: "Courier New";"><span style="mso-list: Ignore;"><span style="font: 7.0pt "Times New Roman";"></span></span></span>Searching
for content to move to properties file</li>
<li>Copying,
replacing (with keys using a standardized format) and then pasting the conten<span style="font-family: "Times New Roman";">t</span><span style="font-family: Symbol; mso-bidi-font-family: Symbol; mso-fareast-font-family: Symbol;"><span style="mso-list: Ignore;"></span></span></li>
</ul>
<li>Generating load on a web server by triggering
numerous requests (50+)</li>
</ul>
<br /><div>
<div style="text-align: left;">
</div>
</div>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-49674693957545195332012-11-13T08:36:00.000-06:002012-11-20T18:32:36.324-06:00Coupling , Cohesion, and the Importance of Escaping Delimiters<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;">
<br />
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;">
<b style="mso-bidi-font-weight: normal;">Problem:</b> </div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .5in; margin-right: 0in; margin-top: 0in;">
A customer was unable to debug or
reproduce why a web-based application was crashing periodically.<span style="mso-spacerun: yes;"> </span>The crashes were becoming more frequent, and
increasingly affecting their business and customer satisfaction.</div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;">
<b style="mso-bidi-font-weight: normal;">Steps used to solve the problem:</b></div>
<div class="MsoListParagraphCxSpFirst" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">1.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Rule out performance issues through performance
testing</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">2.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Aggregate and Review logs for finding issue
trends</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">3.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Improve error tracking in the application</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">4.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Wait till issue reproduced</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">5.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Used additional logging and new tools to discover
underlying issue</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">6.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Develop fix</div>
<div class="MsoListParagraphCxSpLast" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l0 level1 lfo2; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">7.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Confirm resolution</div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;">
<b style="mso-bidi-font-weight: normal;">Tools used to solve the problem:</b></div>
<div class="MsoListParagraphCxSpFirst" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l1 level1 lfo1; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">1.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Rational Performance Tester</div>
<div class="MsoListParagraphCxSpLast" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l1 level1 lfo1; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">2.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Sikuli</div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;">
<b style="mso-bidi-font-weight: normal;">Cause of the problem:</b></div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in; text-indent: .5in;">
Search entry string with a tab.</div>
<div class="MsoNormal" style="margin-bottom: .0001pt; margin-bottom: 0in;">
<b style="mso-bidi-font-weight: normal;">Tips to avoid in the future:</b></div>
<div class="MsoListParagraphCxSpFirst" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l2 level1 lfo3; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">1.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Properly escape characters used to delimit
data/fields</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l2 level1 lfo3; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">2.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Never make assumptions when dealing with user
inputted content</div>
<div class="MsoListParagraphCxSpMiddle" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l2 level1 lfo3; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">3.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Use design patterns including encapsulation and
low coupling</div>
<div class="MsoListParagraphCxSpLast" style="margin-bottom: .0001pt; margin-bottom: 0in; margin-left: .75in; margin-right: 0in; margin-top: 0in; mso-add-space: auto; mso-list: l2 level1 lfo3; text-indent: -.25in;">
<span style="mso-bidi-font-family: Calibri; mso-bidi-theme-font: minor-latin; mso-fareast-font-family: Calibri; mso-fareast-theme-font: minor-latin;"><span style="mso-list: Ignore;">4.<span style="font: 7.0pt "Times New Roman";">
</span></span></span>Use debug statements in logging</div>
<h2>
Brief Background</h2>
<div class="MsoNormal">
I have been working on a project for a client on and off for
approximately a month.<span style="mso-spacerun: yes;"> </span>I was engaged to
debug and solve an intermittent problem in a Java client-server application
that is over ten years old.<span style="mso-spacerun: yes;">
</span>Periodically, the server application would get locked up, using 100% of
the CPU, until it was manually killed and restarted.<span style="mso-spacerun: yes;"> </span>During this time, the client applet was
unbearably slow or completely didn’t work.<span style="mso-spacerun: yes;">
</span>The problem had been around for a long time, but was starting to occur
more frequently, likely due to more customers using the application.</div>
<h2>
Analysis</h2>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
After doing
load testing using Rational Performance Tester (RPT) and monitoring the memory
usage of the server application, it was determined that the issue was not
caused by loading.<span style="mso-spacerun: yes;"> </span>I successfully
verified that the application ran fine with approximately 10x the maximum
number of actual users observed in production.</div>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
While
performing the load testing, I analyzed server log files.<span style="mso-spacerun: yes;"> </span>They had been looked at previously, but
nothing in particular stood out.<span style="mso-spacerun: yes;"> </span>I
looked for various patterns around the times where problems were logged by
operations personnel.<span style="mso-spacerun: yes;"> </span>Luckily, the
developers created log entries when commands were started and completed.<span style="mso-spacerun: yes;"> </span>After matching up intertwined start and
complete logs for commands using Cygwin scripts and Excel, I discovered that a
specific command was started but never completed right around the time when the
issue occurred.<span style="mso-spacerun: yes;"> </span>This was found in all of
the dozen log files analyzed.</div>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
After
narrowing the cause, I focused my testing using <a href="http://sikuli.org/">Sikuli</a>
to exhaustively test the functionality in question.<span style="mso-spacerun: yes;"> </span>I also added more logging to better
understand how to solve the problem.<span style="mso-spacerun: yes;"> </span>I
was not able to reproduce the problem, so we decided to go live with the
version of the application with added logging and wait for it to occur again.</div>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
The problem
occurred soon after and I looked at the generated log files.<span style="mso-spacerun: yes;"> </span>Immediately, I was able to determine the
cause and recreate the problem.<span style="mso-spacerun: yes;"> </span>In the
application, messages are being sent from the client applet to the server using
delimited strings.<span style="mso-spacerun: yes;"> </span>However, the
delimiters were not being escaped.<span style="mso-spacerun: yes;">
</span>Therefore, whenever a user entered a delimiter in the user interface,
the corresponding message was not formed properly, causing the server
application to improperly process it.</div>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
In the case of
this application, message contents are used as arguments in SQL procedures with
minimal error checking.<span style="mso-spacerun: yes;"> </span>Invalid and/or
missing arguments were causing infinite results.<span style="mso-spacerun: yes;"> </span>So the server application was becoming locked
up attempting to fetch and process the results.</div>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
There are
several modifications I made to the client-server application to solve the
issue and make it generally more robust.</div>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
First, I
modified and tested changes to the server application to ensure the changes
were effective.<span style="mso-spacerun: yes;"> </span>I modified the loop that
reads from the database to include a loop counter, and to exit after an overly
large number of iterations.<span style="mso-spacerun: yes;"> </span>This change
eliminates the infinite loop, eliminating the need for operations personnel to
restart the server application.<span style="mso-spacerun: yes;"> </span>The
break condition was made overly large to guarantee it would not exit
prematurely.</div>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
The algorithm
used to process the message was also improved.<span style="mso-spacerun: yes;">
</span>It was modified to handle, as best it reasonably can, extra delimiters
in the command.<span style="mso-spacerun: yes;"> </span>It also now validates
arguments passed to SQL procedures.</div>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
Second, I modified
and tested changes to the client applet.<span style="mso-spacerun: yes;">
</span>The class that packages messages was modified so that delimiters are
removed from the fields put in the message.<span style="mso-spacerun: yes;">
</span>The modifications were complicated by the fact that in some cases the
class was not used to create the message, rather the message was created
manually with string concatenations and hard-coded delimiters (poor
encapsulation).<span style="mso-spacerun: yes;"> </span>It was extremely time
consuming to go through all of the messages, verifying they are created
properly, modifying them so that they are using the class for packaging, and to
test and verify all the changes.<span style="mso-spacerun: yes;"> </span>The
lack of encapsulation and high coupling made the client-server application far
more difficult to maintain.</div>
<h2>
Conclusion/Tips for Developers</h2>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
This
engagement highlights the importance of encapsulation and low coupling.<span style="mso-spacerun: yes;"> </span>If the class designed to package messages was
consistently used, reducing coupling and making it well encapsulated,
eliminating the delimiters in the fields of the message would have been much
simpler to add.<span style="mso-spacerun: yes;"> </span>A small change to the
class would have sufficed.<span style="mso-spacerun: yes;"> </span>Instead, the
class had to be modified, code had to be changed to use the class for creating
the messages, and a bunch of code had to be traced so that it was better understood.</div>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
Last, escaping
delimiters is extremely important and no assumptions should be made when
dealing with user entered content.<span style="mso-spacerun: yes;"> </span>Escaping
delimiters is an extremely common in programming.<span style="mso-spacerun: yes;"> </span>Assuming a class will only be used for a
specific purpose, for example content without tabs, can lead to future issues headaches
when the class is reused.<span style="mso-spacerun: yes;"> </span>In this case,
the tab character was used as a delimiter.<span style="mso-spacerun: yes;">
</span>Users should never enter the tab character, and in fact it is difficult
to do so because pressing a tab changes the focus to the next element.<span style="mso-spacerun: yes;"> </span>However, it is still possible to paste tab
characters into the user interface, which is what users were doing.</div>
<div class="MsoNormal" style="tab-stops: list 0in; text-align: justify;">
<br /></div>
<div class="MsoNormal">
<br /></div>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0tag:blogger.com,1999:blog-24232301.post-71359456637097965062012-10-15T11:52:00.001-05:002012-10-15T11:52:54.726-05:00Software Project Management using Trello<div dir="ltr" style="text-align: left;" trbidi="on">
<a href="http://www.trello.com/">Trello</a> is an online tool that can help keep you organized. It's free to use, quick and easy to learn, and mimics Agile development quite well. The interface mimics a
whiteboard of items, and allows users to move them around
automatically pushing changes to other logged in board members. It's a great quick and dirty tool,
that lets you get started and productive quickly.<br />
<br />
I had researched Trello quite a while ago, when it first became available. I remember liking the interface, however thought it was missing a couple of key features I was looking for. Now, after using it for a couple of weeks, it seems they've added new functionality and made it an extremely attractive tool targeting a wide audience.<br />
<br />
At work, I've been involved with a relatively small project. Another developer and myself are adding some new features to an existing ASP.NET application. To start the project, we hadn't been using any tools to help manage the project tasks, we simply divided the major screens/sections of the new functionality up and worked on them. We recently had a major review with the project manager, which resulted in a list of several changes/fixes to get done ASAP. We had notes on the changes, but needed to efficiently manage them so that none were forgotten. We also didn't want to be working on the same item, thus wasting a bunch of time.<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSJ3Bh7eHcFyKKmofnCeh7gT2hYmzlulzzFqOVayaK37oOhYwNUEM9SOXActwqpgSiiBwYXmjFk0olRpeAUuM3elItnjsOtnuuhi1QXUx5p48nwHlfuZgyppNvBrpqlPU6aL34/s1600/TrelloMain.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSJ3Bh7eHcFyKKmofnCeh7gT2hYmzlulzzFqOVayaK37oOhYwNUEM9SOXActwqpgSiiBwYXmjFk0olRpeAUuM3elItnjsOtnuuhi1QXUx5p48nwHlfuZgyppNvBrpqlPU6aL34/s400/TrelloMain.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Board Screenshot</td></tr>
</tbody></table>
We used Trello to manage all the tasks. After creating free accounts and a board for the project, it was quick and easy to add the changes/fixes as cards. The interface is extremely intuitive and efficient. It allowed us to efficiently manage and complete all the tasks, without being cumbersome. I found it very easy to plow through the items, adding comments after completing them and moving them to the appropriate list (i.e. status). We never accidentally worked on the same card, and minimized project management by relying on Trello. Here's a censored screenshot of our board.<br />
<br />
Trello is very customizable, including renaming lists (labeled To Do, Awaiting Feedback, Doing, etc... above) and labels (refer to Custom Labels Screenshot). You have the ability to add checklists to each card to further breakdown the task. You can also assign the card to members, set a due date, attach files, subscribe, archive. You can also move the card to a different board, list and position within the list.<br />
<br />
<br />
Modifying the list and assigned members is extremely easy from the board. The interface supports drag-and-drop for both. Changes are automatically pushed to other members viewing the board so that everyone is working with an up-to-date view.<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjvWwAyYRtmPRqZU9Xoyg35yndlp6aYz5yV-OQIUIKb0aLhoBvi5UCADB2WnXE4ki5p2ZOZ1p5EPRvSEQa-VrPWHjfyS1_lqfvyyjUwla7zO3xudVthPO5aXbSaNOQ5F7IoAuC/s1600/Labels.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhjvWwAyYRtmPRqZU9Xoyg35yndlp6aYz5yV-OQIUIKb0aLhoBvi5UCADB2WnXE4ki5p2ZOZ1p5EPRvSEQa-VrPWHjfyS1_lqfvyyjUwla7zO3xudVthPO5aXbSaNOQ5F7IoAuC/s200/Labels.jpg" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Custom Labels Screenshot</td></tr>
</tbody></table>
Here is a summary of Trello features:<br />
<ul style="text-align: left;">
<li>Free, easy to setup</li>
<li>Extremely intuitive user interface</li>
<li>Drag-and-drop cards to change their status</li>
<li>Drag-and-drop users onto cards to assign them</li>
<li>Board automatically refreshes as others make changes, highlighting recent changes</li>
<li>Cards support a lot of functionality</li>
<ul>
<li>Description, checklist, comments, file attachment, due date, subscribe (to changes), archive</li>
</ul>
<li>Customizable lists and labels</li>
<li>Add/invite new users to the board</li>
<li>Vote - vote on a card, presumably to increase it's priority</li>
<li>User permissions - limit permissions of individual users</li>
<li>Search cards for specific content</li>
<li>Recent Activities - a listing of recent changes to the board</li>
</ul>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiukcmI42DjkWdzLlAUZXgHDum9StuBphHzuLsKi0VnTb_3veNNNLGl3uwk9OCQMb0xfSKUjax_TQn4iAnCqBrwzXamh6XTH6ULHJXDUlO-RBjH7Ij2OWFTjA1hh3dMc7u_kjf1/s1600/Checklist.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiukcmI42DjkWdzLlAUZXgHDum9StuBphHzuLsKi0VnTb_3veNNNLGl3uwk9OCQMb0xfSKUjax_TQn4iAnCqBrwzXamh6XTH6ULHJXDUlO-RBjH7Ij2OWFTjA1hh3dMc7u_kjf1/s320/Checklist.jpg" width="264" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Detail view of card including history and checklist</td></tr>
</tbody></table>
To support the next level of project management, there are a couple of short-comings, or at least things to be aware of before using Trello. Tracking the status of cards and getting a high level view of everything is very easy, however there are limited project management tools available. Beyond looking at the board, there isn't a way to determine the rate at which cards are being created and completed. Basically, Trello is missing reporting tools altogether. You can export the project to JSON, and it looks like the file contains all of the cards in their current state. However I'm not sure how to make use of it.<br />
<br />
Another thing to be aware of is that Trello is hosted on the web. Although we set the board to private, and they have privacy documentation, I think it's a good habit to always be a bit wary of what content you're posting. There's always the possibility that the site gets hacked, or privacy rules change. To avoid possible problems in the future, I think it's good practice not to post overly sensitive data/information.<br />
<br />
Here is a summary of features missing from Trello that I think are useful:<br />
<ul style="text-align: left;">
<li>Time tracking for individual cards</li>
<li>Ability to minimize lists</li>
<ul>
<li>As far as I can tell, lists have to be open and take up an entire column in the board</li>
<li>It would be nice to be able to minimize them because board real estate does become a limiting factor</li>
<li>It would be nice to stack multiple lists in a single column</li>
</ul>
<li>Project management and reporting functionality</li>
<li>Instant Messaging/Chat</li>
<ul>
<li>It would be great to have the ability to chat with other users</li>
<li>You can already determine if a member is logged into the board</li>
<li>IM would be a great feature, allowing you to quickly ask another member questions </li>
</ul>
</ul>
<br />
Here is some Trello terminology:<br />
<ul style="text-align: left;">
<li>Board - a sprint, project, sub-project or work iteration</li>
<li>Card - a task, issue, bug, work item</li>
<li>List - the state of the card</li>
<ul>
<li>ex. To Do, Doing, Complete, Verified, Awaiting Feedback</li>
</ul>
<li>Label - a tag, category or grouping for cards</li>
<ul>
<li>Cards can have multiple labels</li>
<li>ex. feature, bug, priority</li>
</ul>
<li>Member - users with permission to access the board </li>
</ul>
</div>
prlj13http://www.blogger.com/profile/00932888436794418736noreply@blogger.com0