Wednesday, December 30, 2015

Thoughts on teaching Java at home

My son is taking his first Java programming course in high school (an Advanced Placement [AP] course).  Since I am primarily doing Java work most of the time now, I figured some father-son bonding would be fun to do while teaching him some Java stuff.  The result so far has been fun at times and I think he has learned a bit but also causes me to pause to think about the timing and process a bit along with other items. 

Some thoughts/considerations/findings are:
  1. I question how much I should try teaching him in this situation.  Part of my reasoning revolves around the fact that his class is moving pretty slow (maybe the memory of how slow my first Pascal course was has faded) and the content is somewhat limited with focus mainly around the requirements of the final AP test.  I don't want to distract him too much from his teachers plans due to the chance he may not focus enough on the exam requirements.
  2.  I've never taught anything formal before and have no training as a teacher.  This in and of itself makes things difficult but I find it even harder when combined with how long I have been programming (using Java and other languages).  All my knowledge and experience helps me in day to day work but I find it hard to identify material at an appropriate knowledge level for someone just starting out. It seems that teaching someone that already knows the language fundamentals should be easier than starting from a nearly blank slate. There are three major areas where I run into this.
    1. Language features/syntax
      1. Try explaining functional aspects of Java (lambda functions) to someone that is just finishing talking about 'for' loops in class.  If you come up with enough examples you might get past the initial glassy-eyed stare but it will take a while.  I am thinking that after his current class, many of the more interesting ideas should be easier to grasp or at least provide an easier basis to start explaining things.
    2. Data structures
      1.  I work with reasonably complex problems and utilize many of the of common collection classes constantly. In examples for my son, I am finding it hard to limit myself to simple arrays.  I keep getting drawn into explaining the fundamentals of data structures along with the various collection classes.  Unfortunately, my main goals usually are not about data structure fundamentals.  It is almost funny as I pondered how to explain Java references and I keep wanting to utilize C/assembler/machine details to contrast them [aka pointer, memory address].  This may work if someone already knows C or understands the underlying hardware (things like Von Neumann or Harvard architectures) but I found myself on a slippery (but fun/interesting) slope trying to find the appropriate wording.
    3. Examples and Design considerations
      1. Coming up with an extensible example that starts like "Hello World" and gradually includes new language features/syntax while demonstrating (reasonable) design skills is likely harder than my day job.  While I may cringe on occasion at examples my son has from class, I am starting to understand why they are needed at times.  It is more effort and time to teach design skills concurrently with language syntax and usage.  I would love to come up with a really nice example program/project idea that scales from day 1 all the way through the Java 8 changes AND demonstrates a reasonable design strategy.  Maybe something like that is possible or already exists but I don't have the time to create or find it.
Another impediment which I wouldn't have anticipated as one is the use of an IDE (Integrated Development Environment).  I use Eclipse about 99.9% of the time.  In the high school class they don't use anything more than Notepad++ (and just plain notepad at times).  The impediment in this case is not their use of Notepad++ but my reliance on Eclipse.  I find that when I work on some toy ideas with my son (not using an IDE), I do miss silly mistakes now which would be obvious as you type in Eclipse.  With code completion, I don't usually have to memorize the specific order of parameters for most things, etc.  If you take away the code completion, it does slow things down and I find myself providing parameters in the wrong order at times and making other mistakes.  The problem is obvious when parameters have incompatible types but otherwise it does take extra time debugging that type of problem.  Debugging and analyzing error messages are good learning tools but it is somewhat an annoyance when that isn't part of what you are trying to demonstrate.

If I was a real teacher then there are surely many resources to help with planning a real curriculum but doing this type of thing mainly spur of the moment is not easily done.

Now that I mentioned a number of impediments, I should mention a few resources which I think have helped teach my son (and maybe my daughter later).  I think a couple old "Java in a Nutshell" books helped a little - he can thumb through them as needed and put bookmarks anywhere he desires.  I think an even better resource is my Java 6 certification book/study guide.  I don't think he has spent a lot of time with it yet but the fact that it contains oodles of correct/incorrect small code samples with descriptions of why they work or not should be a big plus.  If he starts at the beginning, with a little effort he should be able to pick up many of the individual concepts presented.  I probably won't quiz him with the sample test questions though.  It make take him a while to mentally put it all together but I think it could be a really good start.  If he digs into it more thoroughly I will document what i find.
 
The following is more of a side note related to myself.

On that note, after giving my son my Java 6 certification book/guide, I went ahead and picked up the "OCA Java 8 programmer I" and "OCP Java 8 Programmer II" study guides.  In the past, I had considered taking the tests but just never found enough time to fully prepare (cram for realistically).  There were API's that I rarely, if ever, need/use that I would need preparation (Threading comes to mind).  And my earlier comments regarding reliance upon an IDE like Eclipse resulting in a bit of laxness in reading what I write still applies.  I'm not a real fan of reading intentionally misleading and ugly code but I understand reason for it in the context of the certifications. Even so, the study guides are still really useful though because they do tend to describe things which might be uncommon but useful or items which you may have forgotten about.  I'll admit here that I had somewhat forgotten that you can specify "default:" in a "switch" at a location other than the end of it.  I, as a standard practice, always specify it at the end of the "switch" - I don't remember the last time I specified it anywhere else.  So the study guides provide good examples of valid syntax which you may not utilize due to existing organizational code standards or similar reasons.  There are also items covering new features which you may not be (highly) familiar with. 

I'm going to put more effort into actually getting the OCA certification in the near term.  I think this will be a wise choice related to employment over the next 4-6 months.  Hopefully I can find time for the OCP certification as well.  It appears to be increasingly import to differentiate oneself from others.  I just don't want to take away too much family time in the process.  Some prayers will hopefully help in setting priorities. 

Thanks for reading,
Scott

Sunday, December 27, 2015

The Deck - Saga continues

The Deck - the saga begins

Over Thanksgiving week I made some progress on the deck - all 6 holes dug and concrete poured.  I ended up working on it spur of the moment because the weather was good.  This was more work than I had hoped.   I didn't have time to get a cement mixer and hand dug the holes (about 24-26" deep).  I purchased 3 12" x 48" long concrete tube forms and cut them in half. I took scrap 2x10 from the old deck and made 14" square (interior) by 6" deep frames.  I placed and filled the open frames with concrete first. Prior to this I made plywood tops/covers (cut in half for easier removal).  I cut round holes in the tops and tacked the tubes to them. After I filled the frames I added the cover/tube combo and filled them.  After 1-2 hours, I put the anchors (j/l-bolts) in the concrete and smoothed it again.  I ended up using 25 80lb bags of 5000psi high early strength concrete.  I could have probably gone with a lower strength concrete. At this point it was the Friday after Thanksgiving and I needed to wait around 3 days for the concrete to cure.

Here are a variety of pics from the work.  Probably leave some of these artifacts on a disk for the new owners of this house once we sell (hopefully this spring).



Below is the hardware used to meet code for the railings; either one of these is used directly with each rail post or 2 are used on either side of a post (to joist or blocking depending on location).


Below is the box of bulk aluminum balusters I purchased from Lowe's. Buying the 64 packs was cheaper by a bit ($2 each versus around $2.50 from what I remember). There were other places on the internet with cheaper prices but I figured Lowe's was fairly reliable and quality should be reasonable which left me with less worries.  The only thing I *may* have done differently though would be using a face mount baluster - I think that would be easier to install than what I will have to do.  The face mount balusters may be more expensive though - doesn't really matter to me at this point since I am pretty much committed to my plan so I didn't look into it.

 Here are the connectors for the balusters (one shown) - they come with screws.

Here are the connectors for the balusters on the stairs.

These HeadLOK conectors were used to tie the 2 2x10's together to make beams and I also used them to connect the front rim joist to the other joists (3 vertically through face of rim into the end of each joist). I am able to sink these enough that I should not have a problem mounting the rail posts.

I used some #10, #9 and #8 structural screws for the various hardware connections (post bases, post caps, inner flange joist hangers, full hurricane ties, single side hurricane ties).  My links may not be to the exact ones I used but they are close - make sure you use Triple galvanized/G185 coated items.  I had some trouble sourcing hardware (finding it in-stock) so I had to shop around or order online for a few items.

Below are the collated screws for the screw gun I bought (shown farther below).  This is for the decking mainly.

I used these LedgerLOK screws to tie the deck to the house for lateral support.  In my case, the ledger isn't transferring any load to the house foundation but simple stiffens things up for lateral support.

Here is the collated screw gun I picked up.  I have not tried it yet.  I skipped the cordless model since I don't see heavy use of this after the fact and batteries tend to be dead (either discharged or just plain unusable in one prior case) when I do need to use tools.
Here are the concrete tubes I used.

Here is my first batch of concrete.



I continued working on a model of the deck using SketchUp 2014 (free/non-commercial version).  I had tried using this before and found it somewhat painful to use.  I had wanted it to work differently than it does.  I finally broke down and watched some how-to videos on it from their site and things improved.  There are still a number of things I don't like about it but for a relatively simple project it works pretty well. It doesn't look like they offer the free version any longer (I didn't check very hard) so I don't know if the newer versions work better.

Below is where the design is at right now.  It is a basic freestanding design using drop beam construction.  I did attach it to the house for some later support (which is in the building code). It is mildly over-engineered by choice and should last a very long time.  There are still a couple of minor adjustments to make with some due to the hardware for mounting rail posts.  I'll mention that more later.  I also don't have the steps included yet; I am still working out the details for that. According to code I will require more concrete work for the steps.


I took a couple days off to work on the deck before my parents arrival for Christmas. I was able to prep a bunch of stuff but rain prevented real progress. Now it is nearly Christmas and my parents are here.  My dad has helped out a ton to get the posts, beams and most joists in place.  I am grateful for that extra help - it is just a difficult time to have friends help with all the holiday planning and such going on.  Even with the extra help, I wasn't able to get as much done as desired since a huge amount of rain moved in.  It has been raining for 2-3 days now and our clay soil is impossible to work in; you sink well over an inch and it is slippery as can be.

So far there have been various challenges that we were able to overcome for the most part.
  • One of the early challenges was getting the 16' 2x10's home - for that I used our 5x10 trailer and made 2 upside down u shape pieces that fit against the side of the trailer and go 24" high to the top of the sides.  I bolted those to the sides of the trailer.  I took the tailgate off the trailer which then allowed my to hang 3' of the 2x10's over the front and 3' off the back of the trailer.  I used tie downs wrapped around the wood (centered in 2 piles) and attached to hooks on the trailer walls to keep it from moving.  This worked really well (and safe) - no problem with the wood hitting the truck while centered.  
  • Another early challenge included unavailability of various tools or hardware locally (without ordering or driving an hour or 2). 
  • After reviewing the tension ties along with my model I realized that the final 2 joists were going to be too close to allow the tension tie to fit between them.  I ended up moving the last interior joist flush with the exterior joist to provide the room.  I'm hovering around code compliance on the 16" OC spacing but it is real real close. The good news is this should strengthen the stair stringer connections quite a bit.
  • We also had some difficulty getting things squared (quickly) - this was due to both differences board to board and a huge amount of rain which caused some warping in number of places.  A large bar clamp helped get some pieces in the desired location before screwing together. 

The only bad thing so far was tweaking a knee while doing the concrete work.  Doctor indicates it is probably the meniscus and that I have about a 50% chance of it healing on its own.  After a cortisone shot the pain is lower at least.  It is slowing me down a bit but things still need to get done so..  As long as God grants me the strength, I'll continue working through this.  My bigger concern is my father overdoing things.  My parents have now headed home and I think my dad survived ok - but pretty tired.  Praying that the back-pain won't be too bad after he gets home.

I figure one more blog entry will cover the remaining work.  Off to Lowe's to measure the stair stringers so I can add it to my SketchUp model.

Hope you had a wonderful Christmas and were able to celebrate Jesus birth wherever you may live. I know some readers live in places where it is crime to worship Jesus and punishments are atrocities against mankind - my heart and prayers are with you.


Sunday, November 22, 2015

A nail - life stages

After I finished tearing our old deck down I recovered a few of the nails.  The nails are about 20 years old; the picture shows what should be the same style nail in different stages of decay.  They appear to be some type of (lightly) galvanized spiral shank nail.  As I rebuild our deck, I hope that the newer "triple hot dipped" type connectors and fasteners hold up better - and the other "coated" screws as well.

If you are wondering about the odd looking protrusions near the head, tip, etc of the nail - I picked up the nails with a magnetic sweep and it left them mildly magnetic. The nails retained small bits of rust from the sweep which are like iron particles following the magnetic field lines.

Wednesday, November 18, 2015

The deck - the saga begins

This is part one of what will be 3 posts.
The second post is The deck - The saga continues

As we continue working on the house with the goal of cleaning it up to put on the market in 2016, I am fixing up eyesore projects.  One of those projects is the deck.  Early on I got a couple contractor quotes for replacing it and they ran from ~$2800-4800.  I wasn't real thrilled with those quotes - either too much money, too low quality components or a combination thereof.  My next thought was doing it myself - I bounced that around for a long time and slowly worked myself back (with lots of input from the wife) to only replacing the guard rail and deck boards. That was the minimum I was willing to do even if we are selling the place.  I just feel it is wrong to leave things like this to a new owner - going by the "do unto others as you wish them to do unto you" philosophy.  I get "advice" to the contrary from some folks/family but it is part of my values that I refuse to give up.  A new owner can rip it down and start over if they desire but at least no one should get hurt in the mean time.

The rail was a mess, unsafe and couldn't meet current code in any way. Here you can see the overall condition. I never really liked this deck. 

Here you can see the result of me using only a little effort to break a post off.  The post had been notched so only 1/4 of the 4"x4" post was supporting the horizontal rails.  Current code requirements could not be remotely met by this. 


The flooring was pretty bad - it is over 20 years old and hadn't been kept stained like it should have.

I tagged this project to work on near the end of everything else which turned out to be a mistake. I had dug along one of the posts a while back when I had considered doing the full rebuilt - I wanted to see if the post had concrete.  I only looked enough to see there was concrete and to note that there wasn't much concrete.  Now jump forward a month or 2 and when I looked at the post again (after a couple rain storms), I noticed that the post was nearly rotted in half at the concrete.

Sigh.  Not what I wanted to find. The dirt on the lower right side should actually be the post.


I had hoped to have all my major projects completed by the end of the year (2015) but this one is going to be close.  I am going to do it myself to save money and to still allow me to put the level of quality that I desire into it.

If possible and safe I will reuse a few pieces of the structure.  I am going to use the existing deck boards to build square base forms for the concrete footings (remove and take to dump when done). I'm not sure if the joists are salvageable. I would likely need to flip them over to avoid hitting the partial nails left in them after ripping the flooring out.  It looks like the floor nails used were non-galvanized spiral shank items.  Most had rusted to less than half their diameter.  I'll likely just buy new ones - not sure it is worth the effort to salvage.  Maybe I can find another use for them - have to think on that.

I decided early on that I wanted to at least use metal balusters. I hunted around and actually found that I could get boxes of 64 from Lowes for a price of ~ $1.71/each.  Wood balusters listed for around $0.97/each which was acceptable to me.  There are places online with cheaper prices but I figured it was worth the slight premium to work with someone I know versus a site I don't and where quality and returns might be issues.  Shipping to my local Lowes is free and my order was ready the next day.

I picked up a Senco collated screw gun (DuraSping 332AC)  and a pail of 2.5" coated screws to start with.  That should speed up laying the deck boards. I figure I can find a use for the screw gun for other projects down the road - especially with a new house.

I bought one roll of flexible flashing to go over the tops of the joists.  I will be cutting the 9" wide material down to maybe 3" strips which should cover the tops of the 2x10 joists.

I also picked up a gallon of Copper-Green wood preservative so I can coat the ends of all cuts and such.

I have a 4-5 books on deck construction with copyright dates as new as 2011 and I found it troubling that they show some non-code compliant designs in a few cases.  Lots of web sites show non-compliant items as well (like notching rail posts).  Maybe that can be done under certain circumstances in some locale but not around here.

I am using some documentation from Strongtie (pdf here) to select the hardware and remaining fasteners. A nice "Handy Man How To" article on deck rail construction (here). Some other good/interesting reference material is this Youtube video (here). My county doesn't have any really good documentation on deck requirements (just references the "code") but Fairfax County, VA has some nice information which I found helpful in interpreting the "code" better - look here.  It looks like much/most of the prescriptive residential construction guide documents as produced by Fairfax county are based upon information from the American Wood Council found here.  It appears that counties modify the information to fit their needs though so be careful how you use it.  I also found this PDF via a google search (found at NADRA) that originate from "Professional Deck Builder • March/April 2007" which is about building techniques for decks that don't rot.

I still have a lot of decisions and drawing to make.  I am hoping to get concrete work done before the outside temp drops to an unacceptable level.  If I have to complete the rest in either the cold or the spring it likely won't be the end of the world - hopefully just not working in rain or snow. In the end, I am hoping to keep the price to around $1500.

May God bless you and your projects!
Scott



Sunday, October 11, 2015

A year in my (IT) work life

So it is currently performance review time at work. I never really enjoy this time - not because of problems but because it takes time away from the multitude of other items I am always working on.  I'm also not one to really want to toot my horn.  I also tend to struggle with self-advocating - that generally doesn't do much harm unless I am looking to make a change of some sort.

I will say that the performance review distraction has been a little lower the last couple years but only because I had started an informal time/task tracking method a couple years ago.  It isn't anything super fancy - a spreadsheet which has lists of tasks with rough time and tagged with common apps and whether it was operations, project, etc type things in support of ITIL tracking. Sometimes I wish I had more detail in my task descriptions but it gives me enough info to show what I work on and roughly how much time I spent.

Anyways, just documenting the breadth/variety of stuff I ended up doing over the last year.  This turned out to be a pretty typical recent year other than the organizations location changes (both people and data center).  I'm trying to break this up into somewhat logical groupings but that isn't always easy. Some of the items are really minor stuff and others are substantial projects involving multiple teams/groups.  I've also limited the amount of detail I've provided but I hope it provide enough for someone to get a feel for what my position requires. 

A note to those that are looking to get into the IT field - I often find that titles don't accurately reflect the expected scope of duties. The smaller the organization or the less IT focused the "organization/product/service" the more I find this to be true. I'm not saying that is bad but make sure your expectations and the organizations real needs are compatible.
  • Department
    • Support the data center moves
    • Support the consolidation of employees to a new location across town
    • Proposal for a couple infrastructure/workflow/business process changes
    • Research some security issues
  • Team
    • Increase application build and deployment automation 
      • Jenkins/Artifactory/Subversion/scripting
    • Jenkins patching/updates
    • Batch job maintenance
    • batch email list rules/filters
  • Subversion
    • Setup some on-checkin email notifications for one application
    • Update service side workspaces to not ask to save/store passwords
    • Setup user/consultant access to various repos
  • Multiple systems
    • Tomcat & JDK upgrades
  • Blackboard
    • A litter research on items requested by lead/administrator
  • Sharepoint
    • Research user/account issues at admins request
  • Other teams
    • Provide some general support to team responsible for HighPoint Mobile application
    • Recompile/configure Apache server/PHP per new required modules needed by HighPoint Mobile upgrade
    • Provide some simple Subversion support/training/knowledge transfer to admin
    • Provide Java/Tomcat setup/knowledge/guidance to another team
    • Provide support to local team/administrator of integration with Dept of General Services
    • Provide support to local AD administrator by setting up data/infrastructure to replace a shared resource domain file sharing setup with something else.
    • Research data issues for another team after a large systems DB was corrupted and crashed with recovery from backup
    • Research other/regular data issues related to ERP and other apps/integration
    • Provide admissions application info to data warehouse group
  • Admissions Application
    • Server replacements
    • Operations and support activities.  Large number of direct college staff  functional question after the functional group quit/retired/transferred or otherwise let go.
    • Code changes to move large amounts of static text/prompts from property files to the database.  This reduced the need for deployments which were replaced by simple DB updates.
    • Other technology upgrades; Primefaces
    • Research and implement batch jobs which identify bad ERP setups and notify responsible groups.
    • Off-hours support during normal ERP maint which affects this application
    • Off-hours support for upgrades/maint
    • Staff authentication method changes - initial R&D
    • Changes to password generation/complexity requirements and processing
  • Legacy portal
    • Authentication method changes
    • Server replacements
    • User level security changes supporting split of HR from existing ERP.
    • Minor customizations/additions to content/branding
    •  Password handling changes 
    • gmail/CAS setup - convert from prior methodology
    • R&D for availability of new portals user security questions to help desk along with integrations to maintain that data
    • off-hours support/maint
  • Wizard
    • some support; research and help resolve various issues. 
    • Provide help answering questions from team/consultants working on rewrite.
  • New portal
    • On-going project support
    • Implement JSF based self-service user lookup and password reset tools
    • Another gmail/CAS custom code setup
    •  Research the large number of data issues
  • WES project
    • Provide admissions app logic/processes/metrics/support to development team
  • Integrations
    • Implemented/deployed dev/test/prod ServiceMix environments
    • Implemented several integrations involving DB to AD, DB to ERP type stuff
    • Implemented integrations to monitor/report issues to integration system status
    • Continue research, prototype and final implementation of ways to increase system capacity/stability/availability/performance/reliability.
    • Password expiration / grace period implementation
  • MS FIM
    • Help primary admin with normalization across the dev/test/prod environments.
    • Provide some additional operations/support help to primary admin
    • Implement custom C# DLL for use with FIM/PCNS 
    • Design/implement DB objects and process for the employee management agent
    • Rework some group handling to remove an unnecessary restriction in group membership for a specific user base
    • Support data setup for a college finance related back-office project
    • Add additional data into employee management agent for use by new issue tracking system
    • Some research into missing AD attributes on some users
Hoping Jesus blesses you and touches the hearts of those around you!
Scott

Sunday, September 20, 2015

Laundry room - vinyl floor, water filter and clothes hanger rack done

Finally done with all the vinyl flooring in the house. Yeah!

The laundry room is just a rectangle with only 2 cutouts (dryer vent and 1 AC/heat vent).  Laying the actual floor went pretty easy.  We still ended up tracing the room and cutouts onto paper and using that to cut the vinyl outside. This got us close but we still had to do a little trimming here and there once we got it down.  The contact cement like glue we used in the bathrooms worked ok here - better than in the master bath. I'm still working on the threshold - that is always a challenge I am finding.

Here is the final floor result:




The main challenge with this room was the plumbing I did first.  I'm a bit tired of plumbing now.  The problem started with the cold water valve to the washing machine - it was "broken" and could not be shut off.  Replacing the flooring required removing the washing machine and dryer but that was difficult with the broken valve.  I decided to replace the existing gate valves with 1/4 turn ball valves instead of trying to repair the seal in the existing valve (which is what I found was wrong).  To replace the valves, I had to cut a hole in the wall to cut off the existing copper tube. I initially decided to use "Shark Bite" style push-in connectors to connect the new valves (with copper stubs out that I solder on) to the existing copper. I ended up changing that but I'll explain that in a minute.  Once done though, I decided to make a small wooden panel to allow future access to the PEX/copper connections instead of just patching it back over.

My wife has been wanting a water filter on the cold water supply to the washing machine.  I figured this was a good time to install that since I was always messing with the plumbing.  I have tools to install PEX tubing so I used that along with a few appropriate copper fittings and a shark bite fitting to install the water filter on the wall next to the box containing the washing machine valves.  On my first test after installation, I turned the water on too fast and the shark bite fitting at the cold water inlet to the filter popped off and sprayed everywhere.  It was at that moment I decided to go back and remove the 3 shark bite fittings and use PEX, Apollo pinch clamps and solder-on PEX to copper fittings.  It took well over an hour to get the 3 shark bite fittings off and my hands felt like mush when done.  I had to go under the house to solder on copper to PEX fittings - I decided to install those on a horizontal section since I didn't trust my uphill soldering. It took about 3 hours or so to get it done; would have been less but I had to cut off the clamps on my initial PEX work and redo it all. I used new sections of tubing since I wasn't sure if crimping the clamp in the same spot is OK or not - better safe than sorry.  With the PEX in place and correctly tightened threaded connections, the water filter works fine.

A few details on how I mounted the water filter.  I took 2 copper coated straight pipe hangers and bent them on my vise in a stair-step shape (2 bends).  I then enlarged a middle hole in each one to an appropriate size to go over the pipe/connection on each side of the water filter.  I'll have to go back and get some pics at a later date.

Here is the water filter setup below.  I added a couple bolts to tie the 2 brackets together which helps stiffen things up and keep it from moving much. I do need to be a touch careful since the filter housing will swing a bit forward/back - maybe I will add a small attachment to the bracket to the filter top since it does have some appropriate holes on top for that.

 Another minor but unexpected need showed up after running a few loads of laundry - we now have a water hammer issue.  A quick trip to Lowes and about $10 for a water hammer arrester should fix that. 

The one you see here is: Water Hammer Arrester

 


Another detail desired by the wife was a place to hang empty clothes hangers again.  For this I bought 2 pipe hangers of the metal loop style with a straight section having some holes which are intended for fasteners.  The fastener holes include some which are 1/4" in diameter.  It just happens that I bought a 4' section of 1/4" steel rod which just fits in those holes.  So I cut the rod down to about 32" and cut off the loops from the pipe hangers - leaving just the straight sections with the small holes. I bent those into and "L" shape and screwed each using the long leg of the "L" to the underside of the shelf above the dryer about 31.5" apart with one end very close to the wall.  I then took the 1/4" rod and drilled a 3/32" through-hole in an end.  I fed the rod through the 1/4" holes in the short leg in each bracket.  The rod end with the 3/32" hole is near the wall and a small piece of wire was run through the hole and twisted to prevent the rod from slipping out of the brackets.

The original hangers early in the process.



Not a great pick but here I am drilling the 3/32" hole in the rod with the drill press.  I used a thin (just under 1/4") piece of scrap wood under the rod in the vice to both raise the rod to where the relatively short bit can reach and to provide a good place for the bit to penetrate into on the far side of the rod.

Here is what the final product looks like with a little paint on things. I could raise it about 1/2" but as is only 1 style of hanger rubs a little on the dryer.


Hope you enjoyed..

God Bless!
Scott

Thursday, September 17, 2015

Apache Camel - sql component failure query limitation

While implementing a ServiceMix 5.4.0 integration (Camel based) I ran into a problem which I really should check into/report when time permits. 

The route is defined like this:
        <route id="processWidgetCreate-route">
            <from uri="sql:{{sql.selectWidgetCreate}}?consumer.onConsume={{sql.markWidgetCreate}}&amp;consumer.onConsumeBatchComplete={{sql.selectWidgetCreate.batchcomplete}}&amp;consumer.onConsumeFailed={{sql.markWidgetCreateFail}}&amp;consumer.delay=60000&amp;maxMessagesPerPoll=100&amp;consumer.useFixedDelay=true"/>
            <to uri="bean:widgetBean?method=createWidget"/>
            <log message="${body}"/>
        </route>


On a failure condition, a SQL similar to below is pulled from a configuration file via keys as indicated in the route above.

        update WIDGET_CREATE
        set processed = 'F', INITIAL_FAIL_TS = NVL(INITIAL_FAIL_TS, SYSDATE),
                    FAIL_CNT = (FAIL_CNT + 1)
        where  processed = 'N' and ID = :#ID

Instead of being executed, an error parsing the SQL was reported. On review of what was passed to the database I noted that the "+" above in the query was missing. What appears to happen is that during replacement of parameters or other Camel preprocessing the "+" is simply removed for an unknown reason.  

The work-around for this problem was simply to replace the "+" with a subtraction of a negative as shown below.

        update WIDGET_CREATE
        set processed = 'F', INITIAL_FAIL_TS = NVL(INITIAL_FAIL_TS, SYSDATE),
                    FAIL_CNT = (FAIL_CNT - -1)
        where  processed = 'N' and ID = :#ID

Hope this helps someone else. 

Wednesday, September 16, 2015

Oracle - bitmap index, function based index and use of sign with decode

Just had a quick random thought on a use case I have in an integration.  What I describe here is overkill and inappropriate in my case but it seems interesting enough to describe since it could be useful someday.

The general problem is one where I need to classify data into one of two buckets where the primary processing operates on one bucket.  The classification is over a field tracking the number of times a particular condition occurs.  The mapping of that count to the buckets, right now, is a simple comparison ( x <= y).  Instead of simply embedding the comparison in the selection query and using a standard b-tree style index I decided to consider what else could be done. 

First I found a method of mapping the count that I thought was interesting:

               DECODE(SIGN(10-"CONDITION_CNT"),1,1,0)

In this example, I am mapping condition counts of 9 or less to the "1" bucket and everything else to the "0" bucket. The condition count is always >= 0 therefore the subtraction guaranteed a positive result for counts 0 to 9.  The sign func returns 1 for anything >0 and 0 for an argument of 0 and -1 for anything less than 0. The decode maps the 1 to 1 and condenses everything else to 0.  And there is the data determining the correct bucket..

After that, I was able to generate a bitmap index over that set of function calls.  A bitmap index was chosen solely due to the cardinality.

CREATE BITMAP INDEX CONDITION_CNT_IDX ON SOME_TABLE (DECODE(SIGN(10-"CONDITION_CNT"),1,1,0));

No, this doesn't really help me but I still found it interesting. If I had some spare time I would try to do some sort of performance comparison just "to know".  Unfortunately, spare time pretty much doesn't exist.  A big reason this doesn't help me right now is my dataset is not very big.  And even if it was, my integration system would be a performance holdup before query access was ever a problem. 

Hope you found this of some interest.

Scott 



Monday, September 14, 2015

Java enum usages

A major reason to use statically typed languages is the type safety; the ability to catch certain errors at compile/development time.  One of the great Java features which promotes that is enums.  These are a great replacement for things such as static final ints/strings/etc and it supports functionality well beyond straight replacement of those simple types.

You normally think of enums in context like the following;


public class EnumExample1 
{
  enum Color {RED,  YELLOW, GREEN};
 
  public static void main(String[] args) 
  {
    Color c = Color.RED;
    EnumExample1 example1 = new EnumExample1();
    example1.process(c);
  }
 
  void process(Color color)
  {
    switch(color)
    {
      case RED:  
        System.out.println("Stop");
        break;
      case YELLOW: 
        System.out.print("Caution - slow down");
        break;
      case GREEN:   
        System.out.println("Go");
        break;
    }
  }
}

That is well and good but you can do more; you can extend the enum with interfaces or even add methods to individual enum values.

/**
 * Note: Part of an example program for my kids to help them learn programming..
  
 * Interface for gaining access to the value or values assigned to a 
 * playing card.
 *
 */
public interface CardValIntfc 
{
 public abstract int[] getNumericVals();
}


/**
 * Simple representation of a playing cards "value".  
 *
 */
public enum Value implements CardValIntfc 
{
 Ace(1,11),
 Two(2),
 Three(3),
 Four(4),
 Five(5),
 Six(6),
 Seven(7),
 Eight(8),
 Nine(9),
 Ten(10),
 Jack(10),
 Queen(10),
 King(10);
 
 Value(int tmpVal)
 {
  this.val = new int[]{ tmpVal};
 }
 
 Value(int tmpVal1, int tmpVal2)
 {
  this.val = new int[]{ tmpVal1, tmpVal2};
 }
 
 @Override
 public int[] getNumericVals()
 {
  return val;
 }
 int val []; 
}

Enums are immutable but you can either put in static values as shown above or with care you can load data from properties files or even a database.

I find increased usefulness when I work with multiple application code bases and have shared code needing to process enums but the set of values differs (slightly) between the code bases. Below is description of the progressive changes from a simple enum to something more flexible.

A real example I have is where I represent various databases as distinct enum values and have a bunch of non-database specific code which simple needs an enum value to determine what database to use.  Initially just creating a single enum in the shared code worked within a single application.  A trade-off occurs when you move to multiple applications though.  The enum contains values for all  possible databases whether the application needs them all or not; as in a manufacturing app may not need to know about HR. Also, if you need to add a new database, you have to worry about mixing utility jars which may break if not consistent with the enum configuration they were originally compiled against. 

So initially, an enum representing databases might be made up of values like these:

enum Database 
{
  Finance,
  Service,
  HR,
  Manufacturing
}

To get around this; instead of using an explicit enum in the various application specific and shared API's you instead use an interface and combine that with enums defined in each application.


/**
 * A very basic interface; nearly just a "marker interface"
 *  but could provide more functionality if needed.
 */
public interface DatabaseIntfc  
{
 String getEnumName();
}

So the above might reside in a jar like, db-common-utils.jar. If you have, for example, three department type web applications then you would include that jar in each WAR file. If the source for all three web applications were in separate source trees then you likely would define a Database enum in each source tree in the same package but only include the particular items for the databases you need to reference.


enum Database implements DatabaseIntfc
{
  // Only 2 DB systems in use in this application.
  Service,  
  Manufacturing;

  @Override
  public String getEnumName() 
  {
    return this.name();
  } 
   ....
   // utility stuff
 }

Then in each applications code, you can call the shared utility code but pass the enum constant you are interested in. This might look something like:

        OurDBUtil.hasGrant(Database.HR, "all_users", "admin");

With some creativity, it is pretty easy to come up with ways to put these ideas to work in beneficial ways.

I have been focusing mainly on the benefits of using enums but there is also a sort of downside - not really with enums but care must be taken with their usage.  An example which has bitten me is:  With a big ERP system, the end-users said "here are the ONLY values (5) we will ever use for field XYZ."  What about the other 4 values which are valid for the field, I asked?  "We don't ever need to use those"  was the reply.  And in this case, it appeared that an enum was a great way to go - read field text values and directly convert into enums  or specify directly where needed and pass them around without worry of some type of textual typo occurring. This is great until someone puts unsupported values into the database which then results in things going south quickly when the code can't convert the text to a known enum value.  A simple text field may have been more resilient to errors in this case.  Another option would have been to create enums for all *possible* values and then do some semi-intelligent but certainly more graceful error handling if the unexpected values were found during runtime.

Certainly, the enum usages here could be replaced by some simple ideas such as some regular classes and maybe Spring bean (or CDI) type singletons.  What is better?  It depends.. on too many things to make a blanket statement.  Personally, I like to use enums when it makes sense but there are times when it turns out better using an alternative.  So plan on looking at application needs and other criteria to determine what is the best way for the current and possible future circumstances.


Hope you found this interesting and maybe helpful.

God Bless!
Scott




Saturday, September 12, 2015

Active Directory / Oracle - time stamp handling dilema

I recently received another last minute development request.  I'm going to be a little bit vague on some details on purpose - some things can't be shared.

The general problem to solve is:  On a particular administrative action, a user must complete a specific activity within a particular time frame.  If that activity isn't completed then some data is manipulated to force the user to complete the activity in a timely fashion.  If the activity was completed then flags are cleared regarding the condition.

On first pass through prototyping a possible solution, I recognized it isn't quite as straight forward as hoped.

In this case, we handle several pieces of information from different sources (Oracle and Active Directory). One item is an Oracle date/time (sysdate) generated by the administrative transaction.  We save that "transaction timestamp" in Oracle along with a "to be done by" date which is also stored in Oracle. At that same time, an Active Directory field is indirectly updated to the equivalent of "now". This part of the process works ok and there are no real alternatives available at this time.

At this point in the process, an integration runs which looks for administrative transactions that passed or are at the "to be done by" date and therefore should be checked against the user activity to verify they completed their activity.  This involved comparing an Oracle date/time stored in Oracle against Oracle sysdate - which works well enough and has no issue.

Next we get the user specific last transaction timestamp from Active directory which is represented in Active Directory as a "100ns increment from midnight Jan. 1, 1601".  We then normalize the Oracle transaction timestamp to the same representation as the Active Directory timestamp.  Now in a perfect world, if the Active Directory timestamp is newer than the Oracle transactions timestamp - then the user completed what was required and we clear flags and complete the transaction.Otherwise, we flag the user to complete their task.

The are 2 basic problems though; (1) there is an inherent difference between the Oracle date/time and the Active Directory timestamp - possibly due to one or more causes [activities are only semi-coordinated across servers, possible differences in available precision between Oracle date/time and AD timestamp].  (2) There can be minor differences between system times even when using NTP.

The result of these issues is that in some common circumstances, a user is determined to have completed the transaction just because of the time differences occurring because activities are serialized across different systems but using each systems time.  This I can easily see in the test data I generated.  I have not knowingly run into an issue with differences in the actual clocks in this current situation but we have had previous problems with clocks being out-of-sync.

The "cost" in this situation is significantly higher than desirable if users are determined to be "incomplete" when they actually are "complete".  On that same note, for other reasons it is in the organizations best interest to be as accurate as reasonable. 

[edit 2015/10/03]
Sourcing the time stamps only from AD isn't possible - initially I thought maybe it could be. The final solution isn't too hard to implement.  First I had to determine how close my times had to be to meet business needs.  In this case, I determined that the one use case affected would be fine with 10 seconds of accuracy.  The way I implemented that was to take the transaction time and activity time and subtract them.  If you take the absolute value of that and compare it against 10 seconds, I know whether the user met the timing requirement.  Problem solved.  If the 10 second value is externally configurable, I can easily update the behavior as business requirements change.





Thursday, August 27, 2015

Active Directory Account Expiration - Java

I'm having to do some work with Active Directory accounts.  Here are some tidbits I hope are helpful.

In my situation, I am working with pwLastSet and accountExpires data which are both date/time based.

Active Directory(AD) dates in some (all?) cases are not based on the normal "C" based time functions which calculate seconds from midnight, Jan. 1st 1970.  Instead, AD uses the number of 100ns intervals from midnight, Jan. 1st 1601. 

Here is some code which calculates the number of 100ns increments between Jan 1st, 1601 and 24 hours in the future from "now".  This uses the new Java 8 date/time classes.  The initial date uses the UTC timezone and the end date is using the local timezone.  The negative 24 (-24) is because of the "minusHours()" method causing me to need to subtract a negative to get the positive(future) offset.  The duration is straight forward and by getting the seconds and multiplying by 10^7 I get the 100ns increments.  I used Math.round() just to go from double to long.  The resulting value is then usable in a context such as setting an AD account expiration.

     ZonedDateTime start = ZonedDateTime.of(1601, 1,1,0,0,0, 0, ZoneId.of("Z")); // UTC 
     LocalDateTime now = LocalDateTime.now().minusHours(-24);  
     ZonedDateTime end = ZonedDateTime.of(now, ZoneId.of("America/New_York")); // Eastern 
     Duration dur = Duration.between(start,end);  
     // result in # of 100ns increments  
     long expirationIncrements = Math.round(dur.abs().getSeconds() * Math.pow(10,7));   
     return expirationIncrements;  

Using SpringLDAP, the call to set accountExpires looks like this.  Note "expiration" here was a Long which is converted to a String for use with the LDAP API.

     final ModificationItem [] mods = new ModificationItem[]  
         {  
           new ModificationItem(DirContext.REPLACE_ATTRIBUTE, 
               new BasicAttribute("accountExpires", 
                    expiration.toString()))  
         };  
   
     ldapTemplate.modifyAttributes(userDN, mods);  

Hoping Jesus blesses your day today!
Scott

Tuesday, August 18, 2015

Jenkins - groovy and programmatic job dependency

I really like Jenkins but it certainly isn't a full fledged general job scheduler.  One aspect of various commercial / general schedulers that I miss is the ability to chain jobs together based upon job status.  A scheduler like CA Autosys handles this pretty well.

I can't really justify the cost of a commercial scheduler and we use Jenkins so what can be done?

We'll I ran into a need and decided to find out.  I need to verify the status of an Apache ServiceMix system.  On occasion (still trying to determine root cause), the connectivity with an ERP drops and isn't reacquired.  When that happens, the only solution that worked so far was to restart the ServiceMix process.

What I did is define a Jenkins job which watches the queue of input data for failures.  When a failure occurs I wanted to restart ServiceMix. It took a bit of searching but I found a way to run a second job on identifying our failure condition.  This second job is responsible for performing the restart and the job is initiated programmatically from the first job.  Below is a chunk of code to get, execute and wait for a job to complete.  Not a lot of error handling here but it hopefully provides enough of an example to successfully copy and reuse. 


   def restartWsiServer()  
   {  
    def job = Hudson.instance.getJob('SM RESTART')  
    def anotherBuild  
    try{  
     def future = job.scheduleBuild2(0, new Cause.UpstreamCause(build))  
     out.println "Waiting for the completion of " + HyperlinkNote.encodeTo('/' + job.url, job.fullDisplayName)  
     anotherBuild = future.get()  
    } catch(CancellationException e)  
    {throw new AbortException("${job.fullDisplayName} aborted.")}  
    out.println HyperlinkNote.encodeTo('/' + anotherBuild.url, anotherBuild.fullDisplayName) + " completed."  
   }  


Hope someone finds this useful.

Thursday, August 6, 2015

Gerbil info for parents

It has been about 8 months since we purchased our 2 gerbils.  This post is just a bit of a parents perspective to go along with the pretty large amount of information on the internet by kids and young adults.  These comments are based on our 2 gerbils alone.

This post isn't really for or against gerbils - it is just things we learned about gerbils or in having a child taking care of gerbils.

Each gerbil can definitely have a different personality.  If compared to cartoon characters from Scooby Doo, one of ours is like Fred while our other gerbil is more like Scooby Doo.  One isn't as easily startled and tends to be more active (runs on the wheel) while the other is a little more skittish but quite quick and agile. 

This is pretty much a brain dump of thoughts.
  • They are pretty easy to care for.  Given food, water, regular cage cleaning and some attention - they seem pretty content.  There are a few other things noted below too though.
  • Pet stores carry food which works well for them.  We use Oxbox Essentials Hamster & Gerbil food as the primary food.  As a treat/supplement we give them All living Things hamster & gerbil daily diet.  Over time, we started looking for more things to treat them with (yes, you start to spoil them) - they seem to like eCotrition Yogies which are a cheese flavor like thing.   
  • They do like some hay to eat and nest with.  
  • They can have distinct likes and dislikes regarding other treats (given in small quantities) like raisins, grapes, strawberries, blue berries, hard cheeses, and even bits of egg.
  • They like to chew is an understatement of epic proportions.  They NEED to chew and you must keep them in constant supply of things to chew. The small wood huts from the pet store will quickly grow new entrances, exits and enlargement of the initial openings.  Plan on adding a new hut every ~6 months or so based on what we saw so far.  Plan on providing new wooden play things on a regular basis. I was building little wooden play things out of craft sticks and it is amazing how fast they will turn something into wood chips.  They are also fond of chewing on clothes - be aware, my sweat pants are a bit aerated now.  A good supply of dried blackberry cane works but they seem to prefer the willow from the pet store so far.  Of course, save all your toilet paper rolls and paper towel rolls for them.  A toilet paper roll is about a 5 minute time to a pile of remnants.  We ended up with some empty Christmas and birthday paper rolls - they acted like they hit the jackpot!  They can also be pretty loud when they chew - depending a bit on what it is too.  This can be loud enough to be distracting if you are in the same room.
  • They are FAST and agile.  Only get them out in an area where they can't slip under a door or out any other holes.  If you have "stuff" piled up - they will use it to hide in/under.  
  • Can can jump 10-12 inches pretty easily.  This was more noticeable when younger and in "home made" play areas using books, cardboard box pieces, etc.  
  • They like to crawl under you.  BE CAREFUL sitting or trying to stand in an area with them - it would be REAL easy to sit or step on one.  If you move a cage/tank to a play area for them - be careful if moving it while they are out since they tend to RUN under things as you try to set the object on the floor.  We have had a couple of close calls because they ran under a tank as we moved it to the area they were playing in.
  • They are most active late in the evening (after ~7pm) and are usually moving around in the morning.  Our wonderful little Thumper will run on his wheel into the night - I have woken to him running at 3am. 
  • They don't tend to bite/nip (much).  They can nip on occasion; when young it was more of a "hm, is this finger edible" test.  Once older it has been more of a "please don't chase me, I don't want to be handled now" or maybe a "you haven't paid attention to me recently".  A few times it was an accident in that they were trying to sample something like my sock while on my foot and got a hold of more than desired (by both of us). They have never broken skin and at this point I don't tend to worry about being bitten.
  • If you have an exercise wheel and the gerbil likes it; the metal ones tend to be quite noisy.  The gerbils can run fast enough that you can hardly see their feet.  Our Thumper has done multiple flips in the thing and flung himself out on a number of times when we were watching. Ours actually seems to like attention when on the wheel - he has us trained to clap after a fast run and he will do sprints and then stop and look your direction as if expecting some clapping.  You may be thinking "yeah, right.." but I think you will find that they do indicate they like attention and find various was of showing that.
  • Ok, lets get this over with;  the gerbils poop a lot.  Of course, the more you feed them..  If you give them "out time" - meaning time outside of their cage/tank - plan on some cleanup.  We have wood floors which is likely better than carpet but still not all that pleasant.  Also note that they tend to kick it up in the air when they take off running - so it will likely find its way into areas outside where they stay/play.  The good news is that it tends to be pretty dry and is easily cleaned up with a tissue or piece of toilet paper.  If some low ceramic bowls are laying around the play area, they do seem to "potty" there more that average but they will go pretty much anywhere though.  If you let the gerbils use a "gerbil ball", you will want to check behind them for any presents they leave behind.
  • Our daughter doesn't like to clean up after then and it shows.  Plan on being involved in the cleanup or at least making sure it is done well enough.
  • There is still interest in them after 8 months but it isn't like having something like a dog.  I think if given the opportunity, our daughter would want the dog and would be "ok with keeping the gerbils too".  
  • They do enjoy crawling on people.  There seems to be enough of a difference in their claws to where one has an easier time climbing up shirts than the other depending on the material.  If you sit cross legged they will stand on your knees and look around. 
  • At around 9 months in age, they still don't tend to sit still for very long when out of their cage - they only sit still to chew on whatever is nearby.  Holding them is possible with one for a short period but the other one is always in motion so it is like holding one of those kids "water snake" toys where it is always in a state of sliding out of your hand (crawling in this case).
  • Our gerbils can be "petted" but only very little.  Mainly if they are eating something they really like.  Otherwise they tend to move away after a few seconds.
  • We have taken the camping in a travel trailer 3 times so far.  Make sure your AC works since they spend their time indoors.  I would not take them outside unless it was an emergency.  They are not too bad to travel with but remember to remove the wheel at night if you are a light sleeper.
  • We have also taken then on a week long vacation down south.  If you don't have other pets, remember that you have them and that hotels may charge you extra for having them or deny your stay if they don't allow pets.  We didn't plan ahead for our trip home and this was a little bit of an issue.

The setup of the 10g plastic fish tank plus 2 story tank topper is a decent amount of living space for our 2 gerbils.  I think that combo was about $200.  You can probably find cheaper, I simply found places that had what I wanted.   Then there are other items - some needed upfront and others just acquired over time.  If you get a cage topper (for an aquarium) then I suggest finding a thin rod (brass works well) at either a craft store or home center.  Bend the end to a small J shape and you can use that to snake though the top of the topper to lift the ramp that rests in the aquarium.  This greatly simplified the removal of the topper without a gerbil getting smacked by the ramp or trying to climb it while removing the topper.
  •  hut(s)
  • chew sticks 
  • food
  • hay
  • treats
  • water bottle (best get one that is a anti-chew style)
  • wheel (7-8 inch version seems the right size)
  • bowl and chinchilla dust (they do seem to like their dust baths) - they do tend to make messes in this as well.  Either sift, carefully extract "stuff" or replace once it starts to get excessively dirty.  You don't have to let them play with it daily but they will use it if you do.  Watching them "flop" in the dust is pretty funny to watch.
  • maybe some ceramic dishes 
    • used under water bottle to catch drips
    • food dish if desired
    • "potty" - just a spot they tend to go in.  This gets used a lot but otherwise the tank itself fills quicker; generally clean the dishes daily.
  • ceramic tiles 
    • I put 4-6 of these in the tank & topper.  They seem to prefer standing on these than the cage wires. I bury some in the bedding in the hopes their digging against them helps  wear their claws/nails down.  The tiles in the topper tend to need daily cleaning also.
  • "pet fences" 
    • We purchased 4 of them.  If you hook 2 together you get a nice ~4-5 ft diameter play area.  The ones we have are only about 9 inches tall so we took 2 more and hooked them on top with twist ties to prevent the gerbils from jumping out easily.
  • Smaller tank for in the car while traveling is nice.  Can let them play in it at other times too.
 Here is a pick of the general setup.  Note; don't leave the gerbils unattended with the towels - it isn't great for them to chew but we do let them "burrow" while they play with us in the play area.


[2015/11/08 - updates]
  1. Both gerbils are still very healthy.
  2. One gerbil has a strong desire to not be caged and has learned over the last 3-4 weeks how to "climb" out of the fenced enclosure. By basically performing a quick hop as high as possible and then quickly grasping the bars with a climbing motion he uses a bit of momentum to reach the top of the fence. It took many attempts to get it right but he now repeats it at will.  It is entertaining to watch - until he is free. Our initial mitigation was to put a ~4-5" strip of cardboard around the top edge of the fence so he couldn't find anything to grip to climb over.  A minor gap one evening though allowed him a short lived freedom.  He enjoyed taunting us as we tried variations of chasing, enticing with food and general corralling.  After about 20 minutes my daughter finally caught him.  It probably could have been sooner but I couldn't stop laughing at the sight of my wife *flat* on the floor with arms outstretched in what I can only describe as a mild form of pinball using her hands to try and keep the gerbil within reach. Trust me, the gerbil was not hurt in this (wish I had video, might have been a winner on "America's Funniest Home Videos") - I think my wife was more traumatized than the gerbil (not real found of gerbils that close up to her face).  A few other escape attempts were close - we had to move the tank/topper to nearer the center of the fenced area since it appears he was able to jump onto the outside of the topper in the back and then climb/jump to the flat cardboard area.  So far, our changes are working but we'll likely have to continue coming up with new ways to keep him in.  It seems a bit like "Escape from Alcatraz".
  3. The same escape artist gerbil is a bit nippy at times recently.  I am starting to equate the timing with having handled foods he likes (almonds being the common one).  He starts with sniffing the fingers and then attempts to gnaw.  He follows fingers when you move and keeps trying - it is a bit annoying but now I try not to handle food before handling him.  Washing hands *really well* before handling him helps a bit but I think he can still tell.  I don't think he is trying to purposely hurt me (or others).  He just doesn't seem to differentiate between the smell of food and the real thing as well as his brother.  His brother doesn't exhibit this behavior. 
  4. We are now putting down builders paper (at Lowes) under the overall play area.  This gets replaced weekly during cage cleaning.  It helps to contain their various "outputs" a bit and reduces the amount of damp mopping needed on the hardwood floor. 
  5. If you sit with them and they hang out behind you a lot - best to keep an eye on what they are doing - I now have a pair of sweat pants which I can't wear in public because of them.. You may think they are only bumping/pushing on you but that is likely not what they are up to. :)  You've been warned..