Halloween 2015

October 31, 2015 10:36 pm

Heather survived another Halloween, though just barely.  She was asleep within 3 minutes of lying down in bed.  She was not super enthused about trick-or-treating, but I'm fairly sure it was only because she was already tired.  We did make it all the way up and down our entire street, which is a little further than last year.

We carved a pumpkin, of course.  Heather made 5 concept drawings which I then adapted into pumpkin-ready designs.  She chose the final design, "Beak," and yesterday we carved it.  Then she decided it need eyelashes, so we added those.

IMG_20151001_212037asIMG_20151030_174718s

Heather wanted to be a witch this year and I shaved the bark off a stick to make her a wand:

IMGP4088as

I decided I wanted to put up some decorations, but really only came to that decision this morning.  So I spent the morning designing and making jellyfish / ghosts (depending on who you ask) to hang in the yard. I cut up water jugs for big jellies and used yogurt cups, spray-painted black with holes punched through the sides, as small jellies.

I strung thread across from the trellis to the fence so that the jellyfish could hang over the lawn and be more mysterious as to how they were floating.

IMGP4083as IMGP4087as

I had planned to use some glow sticks to light up "eyes" cut from cardboard tubes, but I ditched that idea in favor of the jellyfish.  Instead, I tried to use the glowsticks to light up the jellyfish.  It didn't work very well, or basically at all.  The glowsticks simply aren't bright enough, even with 4 inside a single jelly.  But I had some LEDs kicking around and a few button batteries so I used those instead, which worked great.  Now that I know, I'll have to get enough batteries next year so I can light them all up properly.

IMGP4098as

Heather's 4th Birthday

October 29, 2015 8:33 pm

Heather turned four this year.  But not without some Heather-style anxiety.  In the days leading up to her birthday she would occasionally have little meltdowns about not wanting to get older.  She liked being three and didn't want to get bigger or do different things.  We assured her that it was not an instantaneous event--She would still get to go to pre-school, dance class, and gymnastics.  That seemed to help her calm down.

She had a party on Saturday with friends from church.  They painted pictures, ran around the house like loons, and ate cupcakes.  It was a blast.

IMGP3963as

Over the weekend Heather started asking if we could play "miniature ball" by which she meant miniature golf.  So we did that Monday evening.  She's never played before and we're not sure where she even got the idea from.  She was really excited though.  When I got home from work she just about tackled me.

She started out enthused and interested:

IMG_20151026_165428as IMG_20151026_172255as IMG_20151026_175318as

But by the 18th hole she just wanted to be done:

IMG_20151026_175945as

I had a great game.  I averaged 2.66 strokes per hole on 18 holes and my worst hole was only 4 strokes!  On the way to the parking lot I asked Heather how it was.  I told her, "I had a great game; probably my greatest game!"  She responded, "I had a boring game; probably the boringest game."  I think she had fun overall, but she was definitely ready to be be done.  She burned through most of her energy being excited all day.

On her birthday I made a treasure hunt for her to find her presents.  Mom would do this for us every so often growing up and I thought Heather would really enjoy it.  She thought it was amazing.

IMGP4007as
The first clue in the treasure hunt.
IMGP4021as
Another clue had been eaten by the frog.

I compiled a video of the footage Jess took of the treasure hunt. It's at the end of the post if you're interested.  I was able to trim it down to 7.5 minutes, which I realize is still quite some time to watch a video, but it's still pretty great.

We did the treasure hunt and opened presents during lunch so Heather would have the afternoon to play with gifts.  Jess convinced me that this was a better plan than waiting until having cake after dinner then opening presents and immediately trying to send Heather to bed.

IMGP4042as
She is in love with this book about anatomy / physiology.
IMGP4057as
She immediately started pointing out solar flares in this book (not on this page though).
IMGP4062as
A rake to help Daddy rake the leaves!
IMG_20151028_134040as
Magnetic building shapes are a hit.

We had dinner at the Ale House (or, as Heather prefers to call it, the Ollie House).  It's Heather's favorite restaurant.  They apparently have the best mini corn dogs, fruit, and milk dinner in town.  Then it was back home for cake, colored blue per Heather's request.

IMGP4077as IMGP4081as

Overall I think she had a great day.

And now the Treasure Hunt video:

And a direct link if you want/need to download it to view it: Heather's Treasure Hunt 2015 (right-click, save link as...).

Mr. Fancy Pants Shirt

October 19, 2015 6:01 pm

I've been needing a new white dress shirt for many months now.  The collar on my old shirt was pretty beat up.  But shopping for dress shirts is lame so I kept putting it off.  As I was considering my need of a new shirt I was thinking it would be nice to have a shirt that actually fit properly, which seemed like it would entail shopping for a shirt and then getting it tailored.  That seemed even more lame than just shopping for a shirt.

shirt_1
My custom shirt from Tailor Store as it arrived from Sri Lanka (minus packaging)

So, as I am wont to do, I did my research.  And I found Tailor Store.  It is a Swedish company which allows you to order custom-designed and custom-fit shirts without leaving home!  You might be thinking that a custom made shirt is going to be expensive.  It can be, but it doesn't have to be.  Tailor Store offers a poplin, white, cotton fabric for $49.  So I figured it was worth a shot.

You can customize every single aspect of the shirt if you want to: fabric, button color, thread color, cuff style, collar style, pocket, embroidery, elbow patches, etc.  Despite the level of customization available the user interface is quite good.  I'm impressed they were able to keep it as simple as it is.  I was just going for a classic white shirt, though, so my design process was pretty straightforward.

But the real convenience is the custom fit.  If you put in your height and weight they'll set some starting values for all of the needed measurements and they provide explanations and tutorial videos for how to take each measurement.  Jess helped me take the actual measurements to make the final adjustments.

Once you place an order the information is sent off to their manufacturing facility in Sri Lanka where it's custom made and then shipped out.  Shipping does cost you though, $20.  So the total cost for the shirt was $70.  But that's still pretty great for a fully custom-designed and custom-fit shirt.

I placed the order on October 8 and received my shirt today, October 19.  Eleven days to have it custom-made and then delivered from around the world is pretty good in my opinion.

And it fits great.  I am very pleased with the result.  If I had need for more nice shirts I'd definitely order from them again.  And since the measurements are already done it would only be a matter of designing a new shirt and placing the order.

shirt_2
My new custom-fit shirt from Tailor Store (it needs to be ironed)

Converting Http Session Events into Grails 3 Events

1:16 pm

Grails 3 introduced a new Events API based on Reactor.  Unfortunately, as far as I can tell, HttpSessionEvents are not natively part of the Grails 3 Events system.  Bringing them in to the fold, however, is pretty easy.  I based this off of Oliver Wahlen's immensely helpful blog post about sending the HttpSessionEvents to a Grails service.

First, let's create our Spring HttpSessionServletListener.  Create this file somewhere in the /src/ path where Grails will find it:

File: .../grailsProject/src/main/groovy/com/example/HttpSessionServletListener.groovy
package com.example

import grails.events.*
import javax.servlet.http.HttpSession
import javax.servlet.http.HttpSessionEvent
import javax.servlet.http.HttpSessionListener

class HttpSessionServletListener implements HttpSessionListener, Events {
  
    // called by servlet container upon session creation
    void sessionCreated(HttpSessionEvent event) {
        notify("example:httpSessionCreated", event.session)
    }

    // called by servlet container upon session destruction
    void sessionDestroyed(HttpSessionEvent event) {
        notify("example:httpSessionDestroyed", event.session)
    }
}

Now register the HttpSessionServletListener as a Spring Bean.  If you don't already have a resources.groovy file, create one and add the following.

.../grailsProject/grails-app/conf/spring/resources.groovy
import org.springframework.boot.context.embedded.ServletListenerRegistrationBean
import com.example.HttpSessionServletListener

beans = {
    
    httpSessionServletListener(ServletListenerRegistrationBean) {
        listener = bean(HttpSessionServletListener)
    }
    
}
// Yes this is the entire file

Now you are all set to listen for the "example:httpSessionCreated" and "example:httpSessionDestroyed" events using the Grails 3 Events API.  "Example" is the namespace of the event, which in my real code I set to the last part of the package name, so I made it match the package name of "example".  Just use something so you don't have to worry about naming collisions.

Here's an example of listening for the events in a standard Grails Controller.  Note that the event handlers are attached after construction, and before the Controller bean is made available, by using the PostConstruct annotation.

.../grailsProject/grails-app/controllers/com/example/ExampleController.groovy
package com.example

import grails.events.*
import javax.annotation.PostConstruct

class ExampleController {
    
    @PostConstruct
    void init() {
        
        on("example:httpSessionCreated") { session ->
            println "sessionCreated: ${session.id}"
        }
        
        on("example:httpSessionDestroyed") { session ->
            println "sessionDestroyed: ${session.id}"
        }
    }
}