Converting Http Session Events into Grails 3 Events

October 19, 2015 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}"
        }
    }
}

NASA Apollo Pictures

October 5, 2015 5:40 pm

Last week NASA released a bunch (over 10,000) of original images from the Apollo missions on their Flickr account.  They’re all Public Domain images so anyone can download the originals and use them for anything they like.  I flipped through and picked out my favorites and cleaned them up.  I’ll probably get some nice canvas prints made of some of them when Canvas Press has sales.

Here are my top 10 after cleaning them up.  I’ve uploaded my full versions so you can download them yourself if you want to make a poster or canvas print or something.  Clicking an image will open the full-size version, which you can then save to your computer using right-click -> Save image…21060968314_bcca0b9191_o_kbd 21065336993_765fba69b6_o_kbd 21082003763_9471526a7e_o_kbd 21472205930_d42afbe79a_o_kbd 21492224000_7f7d5991a8_o_kbd 21496319710_4d7bd28063_o_kbd 21653924176_26f5a10ce1_o_kbd 21667234912_ac412e1fb9_o_kbd 21693186921_68e0b6d72f_o_kbd 21912171516_ea0ef12faf_o_kbd

 

A Light in the Dark

September 28, 2015 7:34 pm

I wrapped an LED around a button battery with a little material to keep it separated so you push on it to turn the LED on.  Then we took turns waving it around while camera took a picture with a long exposure.

Heather’s work was usually very…nuclear:

IMGP3861as

We encouraged her to move around more:

IMGP3863as

I tried to write my name, but my spatial awareness is apparently not great:

IMGP3865as

Jess did better with her contribution:

IMGP3867as

Heather’s World

September 5, 2015 4:22 pm

Heather has been using her Nabi Jr. tablet for awhile now.  It has a camera on it that can spin from front-facing to back-facing.  I configured it to automatically sync the pictures to the computer.

With the pictures all in place I created a time-lapse of Heather’s past year.  If you don’t care about the nerdy details of how I made it, jump to the bottom to watch the video.

It started with the 925 pictures she took over the last year.  I ran them through ImageMagick to pad them to a consistent size:

$ cd /home/heather/Pictures
$ mkdir ~/Desktop/tmp
$ find "./2014/12 December 2014" "./2015" -name "*.jpg" -exec mogrify -gravity center -background black -extent 1600x1600 -path ~/Desktop/tmp {} \;

Then I, again, used ImageMagick to interpolate 3 transition frames between each picture so it’s less jumpy (still pretty jumpy though):

$ cd ~/Desktop/tmp
$ mkdir morphs
$ convert *.jpg -morph 3 ./morphs/out-%04d.jpg

Okay, that’s a little bit of a lie.  ImageMagick’s convert tool currently (version 6.x) reads in all input before doing anything.  When it tries to load in the 925 images it uses up all the memory in my computer and then dies.  So I had to break it up into batches (IM 7 supposedly fixes this problem).  I used batches of 100 which still used about 7 GB of RAM:

$ ls *.jpg | head -n 100 | tail -n 100 | convert @- -morph 3 morphs/a-%04d.jpg
$ ls *.jpg | head -n 200 | tail -n 101 | convert @- -morph 3 morphs/b-%04d.jpg
$ ls *.jpg | head -n 300 | tail -n 101 | convert @- -morph 3 morphs/c-%04d.jpg
# .... all the way through head -n 900 .....
$ ls *.jpg | tail -n 26 | convert @- -morph 3 morphs/j-%04d.jpg

Doing it in batches results in a duplicate frame between each batch, so at this point we have to delete b-0000.jpg, c-0000.jpg, d-0000.jpg, etc. (but keep a-0000.jpg).

Now we’re ready to run them through mencoder to produce our video:

$ cd morphs
$ mencoder mf://\*.jpg -mf w=1600:h=1600:fps=16:type=jpg -ovc lavc -lavcopts vcodec=mpeg4 -of lavf -lavfopts format=mp4 -oac copy -o ~/Desktop/output.mp4

I tried doing this with ffmpeg/avconv, but it kept cropping my images and I couldn’t make it work.  I also spent hours trying to get all this to work without using intermediate files, but ultimately failed.  This process is a little more arduous (I might get around to writing it all into a script at some point) but it does work.

Here’s is the view from Heather’s world from December 2014 through September 2015 (there’s no audio):

Or right-click and “save as…” to download it here: Heather’s View – Dec 2014 – Sep 2015 (small)

If you watch closely you’ll see Christmas, Jess being very pregnant, Corinne appears, Grandma visits, Kyle’s birthday, and a lot of wandering around the house.

It’s not super exciting, but I think it’s kind of an interesting insight into Heather’s world.

Carputer!

August 15, 2015 1:22 pm

IMG_20150815_123630as

One of the features in the Honda Odyssey that I’ve been looking forward to making use of is the auxiliary audio/video inputs located in the third row on the driver’s side.  There’s also a standard AC power outlet back there next to them.  This combination allows me to wire up a Raspberry Pi as an in-car entertainment system which is infinitely more useful than trying to swap DVDs up at the front console. This is especially true if one parent is sitting in the back with the kids because they won’t be able to reach the DVD slot to switch discs and having the driver do so is not a great plan.

Also, it allows us to avoid the awfulness of DVDs: menus, previews, ads, FBI warnings–blurgh what a terrible experience.  Boot this up, select a show, and you’re watching it instantly.

We’ve got some road trips coming up so I wanted to get this set up beforehand.  First I imaged an SD card with OSMC, an OS built around Kodi with the goal of making setup trivial.  And it really was trivial: Install the OSMC installer on your computer, run it, insert your SD card, click some options and you’re good to go.  Pop out the SD card and plug it into the RPi.

Then I copied a bunch of movies and TV shows to a 64GB USB flash drive and plugged it into the Raspberry Pi (version 1 model B).  To get things started I hooked the RPi up to the network and the TV in the house so it could download updates and the appropriate metadata for the videos.  After initial setup I took it out to the van for a trial run.

IMG_20150815_123543as
The Raspberry Pi and associated cords fit nicely in the cup-holder.

I plugged everything in and turned on the car electronics.  The RPi booted up and was ready to roll in just a couple of minutes.  To control it I’m using this wireless keyboard/mouse combo by Lenovo which works great in this application.

IMG_20150815_125218as

Heather helped me out by watching a few minutes of Finding Nemo.  She declared it the best thing ever.

IMG_20150815_123557asThe 4 purplish lights you can see above the screen are the infrared LEDs that transmit the audio to the wireless headphones.  This allows the rear passengers to listen to the movie through the headphones while other passengers do something else–a sanity-saving feature for the adults in the vehicle.