Sunday, December 12, 2010

Introducing...Edufy

Like I mentioned in my last post, I have some big personal news to announce...without further ado -

My entrepreneurial tendencies have finally resulted in something that lives on the internet!


It's called Edufy (http://www.edufy.org). We have built a site for teachers to share and discover learning activities for their students. Our founder, Philip Cooke, is a teacher in Arlington, VA, and his frustration with finding ways to create personalized learning activities for his students inspired him to start this project. After six months of planning, building, testing, and fixing, we launched the site at a couple of conferences in November, and now we want to start spreading the news.
You can check out what Edufy is all about at:
http://www.edufy.org/about/index

We'd love it if you could all check out the site and let us know what you think. If you are a teacher, give it a test drive! If you know any teachers, PLEASE send this to them - we are just getting started, and any feedback/criticism/encouragement we can get is highly valued. If you have any questions or comments, please let me know, or send feedback to contact@edufy.org.

For anyone who cares, I'll be posting about some of the technologies we're using, but for now, check out Edufy, and spread the word!

To keep up with what's new on Edufy, be a fan on Facebook, or follow our blog

Thanks from the Edufy Team!

Friday, November 5, 2010

Big News...Coming Soon

For months now, I have been working with a group of awesome folks on something.  Lots of leaving my job, getting home, and going back to work.  I am pretty proud about what we've come up with.  In a few days, I'll be sharing it.  Fingers crossed.  Exciting times ahead...make or break as they say.

Stay Tuned.

Wednesday, November 3, 2010

Generating .ldif Files using Groovy

I recently needed to do a bulk update of an openLDAP directory to add a password for a really big batch of test users.  I wrote a little Groovy script to do it.  Thought it might be helpful.  First things first, generate a password for the test users using the slappasswd command.  Using the defaults will give a you password with SSHA encryption.  Now we need an .ldif file that describes the change to make.  For more information on ldapmodify commands, head here.  The script here will loop through a group of sequentially id'd users in a couple of ous and assign them our nicely hashed password:



        File newFile = new File('modify-script.ldif')
        String username = ''
        String toAdd = ""

        def stuCount = 80000
        def admCount = 2000
        def teachCount = 18000

        StringBuilder sb = new StringBuilder()

        def ous = [ 'ou1', 'ou2' ]

        for ( ouname in ous ) {

            for ( i in 1..stuCount ) {
                username = "user_${epname}_${i}"

                toAdd = """
dn: uid=${username},ou=people,ou=${ouname},dc=yourdc,dc=com
changetype: modify
add: userPassword
userPassword: {SSHA}zW7Q/yQQ8IKZiX8ANJIGugi0deNebN1o
                    
"""
                sb.append( toAdd )
            }

            sb.append( "\n\n" )

            newFile << sb.toString()
        }

This will produce a file (modify-script.ldif) with a bunch of entries like these:


dn: uid=user_ou1_1,ou=people,ou=ou1,dc=yourdc,dc=com
changetype: modify
add: userPassword
userPassword: {SSHA}zW7Q/yQQ8IKZiX8ANJIGugi0deNebN1o
                    

dn: uid=user_ou1_2,ou=people,ou=ou1,dc=yourdc,dc=com
changetype: modify
add: userPassword
userPassword: {SSHA}zW7Q/yQQ8IKZiX8ANJIGugi0deNebN1o

...

Now you can simply run the ldapmodify command to update the users:

ldapmodify -x -D "cn=admin,dc=yourdc,dc=com" -w yourpass -f modify-script.ldif

I've been able to use derivatives of this script for a few different tasks.  Hope it helps someone else.

Thursday, October 7, 2010

Grails Image Processing with the ImageTools Plugin

I recently had a requirement on my side project to add some simple image processing.  I had previously used the ImageTools plugin, but that seems to have falled into a bit of disrepair.  I had a multistep process to get this going, and I figured I'd share it.

According to the git repository, the last checkin on version 1.0.4 was way back in January 2010.  Grabbing the plugin using the standard grails install-plugin as documented on the plugin documentation page just doesn't cut it.  When attempting to use the documentation, you get a message that tells you
unable to resolve class ImageTool @ line xxx, column xxx. def imageTool = new ImageTool();
This is troubling, as that is the only class included in the plugin.  Fortunately I found this comment on a closed (???) issue on github:
So, to solve this I had to run a git clone on this source tree and then follow the instruction at the link below to create my own version of this plugin with correct package.
So it would seem that you need to grab the source, then create a plugin.  This is not as easy as you might think.  First of all, you might not have git installed.  Follow the instructions here to 'git git'.  Next, you need to grab the code.  From the command prompt in the directory you want the code, run the following command:

git clone http://github.com/ricardojmendez/grails-imagetools.git

Now you have the code.  Even though it's a plugin, you have to tell grails it's a plugin, by running the grails create-plugin command.  Now you have a zip file that you can install in your project, using the standard grails install-plugin command.

From there you can follow the instructions.  The import statement is recognized, and we can get finally get down to actually writing the controller code:

import org.grails.plugins.imagetools.*

...

//the controller method we submit to
def myProfileSave = {

...

uploadPhoto( file, user )

...

}

def uploadPhoto( upfile, user ) {

 if(upfile.empty) {
  flash.message = 'File cannot be empty'
  redirect( action: 'myProfile' )
 }

 def imageTool = new ImageTool()

 imageTool.load( upfile.getBytes() )

 // Crops it to a square
 imageTool.square()
 
        //make the new squared image the image to operate on 
 imageTool.swapSource()
  
 // Reduces the image size
 imageTool.thumbnail( 125 )

 def fileBase = grailsApplication.config.imageLocation
 def fullPath = "${fileBase}/user/photo"
        File fullPFile = new File( fullPath )

 if ( !fullPFile.exists() ) {
  fullPFile.mkdirs()
 }
  
 def filePath = "${fullPath}/user_${user.id}_125.jpg"

 File toMake = new File( filePath )

 if ( !toMake.exists() ) {
  toMake.createNewFile()
 }
  
 // Saves the result
 imageTool.writeResult( filePath, "JPEG" )
}

Once you get the plugin working, it's a breeze, as you can see!  It's a great, simple wrapper around the nasty and complicated JAI library.

Some Tips:

1) You'll probably want to increase your heap size if you are running with a default or small heap.  This requires a bit of memory.
2) Remember to specify a multi-part form.  A good explanation of this can be found in the grails documentation.
3) Profit!

Saturday, July 31, 2010

July!

Let's talk about family.  My grandparents are 94 and 92, and still going.  They live by themselves.  They take care of themselves.  They sometimes complain about how badly they are doing, but I can name multiple couples one third of their age who aren't doing as well as they are!  My grandfather has good days and bad, and my grandmother has short-term memory issues, but really all in all, they are both really still rocking.  I talked to them today for half an hour, and afterwards, I was hit smack in the face with one of those 'wow am I blessed to have these people in my life' moments.  They have been married now for more than SEVENTY years.  They are amazing people who have been a part of so much, and who have so many amazing stories.  They are 'unconditional love machines', who just amaze me with their capacity to be proud of and kind to their family.  They are so positive, so caring, and so full of love.  It's really quite refreshing.


Thanks Grandma and Granddaddy for being an inspiration.  We all love you a ton!

Friday, July 2, 2010

UberConf, Days 2+3

After a great day one, we were looking forward to another great, long day, and we weren't disappointed.

Scala for Java Programmers - Day 2 started with a fun Scala workshop by Venkat Subramaniam that spanned two sessions.  This was extremely hands-on, and very worthwhile.  I learned enough about a language I have had interest in for a while to get started on my own, and got a nice little dose of Computer Science and compiler fun too.  My only complaint here was that we spent too much time using closures and Scala syntax craziness to write code in one, perl-ish, unreadable line.  We should have used the time writing 'terse' obfuscated code playing more with Scala parallel programming.  Actors are nifty, and it's amazing how clearly you can express complicated multi-threaded program flow.  If I had access to this goodness, I can think of one project I did at Blackboard that could have been written in half the time, in 1/5 the LOC, and in a much more readable and intuitive way.  Hindsight is 20/20, I suppose, but man that made me burn a bit.

Emergent Design - After lunch, we attended Neal Ford's talk on emergent design.  This was a good talk, mostly because Neal Ford is a good speaker, but I wouldn't say this was anything new.  No big design up front, test first, don't solve problems that don't yet exist, as this leads to heaps of code debt.

Stability Antipatterns - This was a workshop by Michael Nygard about common antipatterns you see as it relates to stability - this was more on the operations and integration level than at the code level, and had a fair amount of good tips for things to remember - mostly how to keep your application from dying because there is an external resource that you don't control that is failing.  Some of the horror stories he shared were hilarious, and some you could totally see happening to you (if they hadn't already).  Good session.  Good reminder of things to consider that often fall by the wayside.

On to Day 3, which was kind of disappointing.

Implementing Domain-Driven Design - I was excited about this one because DDD is one of those things you always hear about, but never really get.  After the session, I still didn't really get what the big deal was - drive the design of your application by the real-world domain.  Seems pretty simple to me.  What wasn't simple was the 100 slides of UML class diagrams the presenter used to demonstrate DDD.  Yikes, not that awesome.

SOLR - A Case Study - This was an interesting enough presentation, as Solr is something that we are evaluating.  I learned enough to know that we didn't really need to do this right away, but not much more.  It wasn't really a case study.  What I would have liked was either, Solr real-world example, or Migrating from Lucene to Solr, but alas we didn't really get either.  It was still a good presentation though, just not what I was looking for.

Android Mobile Development - Gah!  Fail!  This could have been a great way to close things out, but the presenter instead did the presentation completely out of order, gave nobody any opportunities to code, and was just generally all over the place.  I was at least able to use the time to make my way through some of the Android tutorials that Google provides.  Man what a bummer.

Monday, June 21, 2010

Uberconf Impressions, Day 1


Last week a group of us from eCollege attended the Uberconf presentation here in the Denver area.  I figured I'd post a few impressions:

First off - the venue - the Westin in Westminster, CO.  Nice place.  Really awesome food whether you are a vegetarian or a carnivore.  Free drinks all day.  Decent coffee, although the cups were oddly small.  One note to the Westin - people operate better at temperatures higher than 58 degrees.  It was FREAKING COLD in there.

Now on the conference organization.  This was one of the best flows of any conference I've attended.  There weren't too many people working the conference, and it still went well.  Easy registration process, good marketing materials (4GB USB stick - not bad), and two t-shirts I would be super embarrassed about wearing.  Easy to figure out what sessions were coming up and where they were going to be.  One minor nit - it's a developer conference, which means laptops - next time, get more power strips in the rooms, at least for the workshops.

And, finally the important stuff - the sessions (day 1):

Patterns of Modular Architecture - This was not quite what I had hoped.  I was looking for patterns, and instead got a fairly basic explanation of how to make your dependencies fairly one-way and isolated.  Neat I guess?  A decent refresher, but definitely nothing earth-shattering, and the most interesting part was OSGI, which the presenter covered for literally two minutes at the end of the presentation.  It did look promising, though.

Common Antipatterns and how to Avoid Them - This was well presented, but it was still a little light.  Good reminders on some common sense things NOT to do, and some reasonably interesting stuff out there - that this presentation was really hitting home with some of the attendees scared me - some of these were things that just shouldn't be happening now, and they obviously still are!

Architect for Scale - This was a good session - lots of 'things you should be doing when you get to this size/load'.  There were a fair amount of good notes about what was not enough, what was too much, and how to move up without huge disruptions

Automated Deployment with Maven - This was a huge win.  It was a discussion about how to use Maven plugins to streamline and automate the numerous steps that go into releasing a module of code.  With maven, it involves updating poms, branching, integrating, labeling, etc, and many manual steps.  With some of the tips in the presentation, I was able to make a releasable unit this morning in about 10 minutes with the help of some maven doc.  Why were we not doing this!?!?  Oh well - awesome.  Worth the price of the registration itself.

Architecture - Non-functional Requirements - This was more of a 'what goes into architecture' talk, than something specifically about non-functionals, but very interesting nonetheless.  As someone who is headed down that path, it validated much of what I think architecture is about.  There was some great back and forth in this presentation from the presenter of this session and the presenter of the earlier Antipattern session.