Wednesday, September 03, 2008

Observations on how we learn

So I have a 4 year old...

She's pretty smart if I do say so myself, she is right at that cusp of learning to read - she knows her alphabet very well.  She recognizes some words and can spell simple ones.  She is getting pretty good at typing her name (and it is a long one).  The interesting thing is, that as she types her name she repeats the letters in her name as she types it starting over each time.  So if her name was Elizabeth (which it isn't) she would type E and then say out loud "E-L" and type the L.  Then she would say "E-L-I" and type the I.  She would do this over and over and just about spell her name for every letter in her name.

This is interesting to me because I see myself following these same patterns when I learn new things...  Specifically learning python, I typically don't talk out loud (unless it's been a bad day) but mentally I am constantly repeating to myself what I've learned - "Watch the indention, no semi-colons, parenthesis aren't necessary in conditionals" almost every line of python code has the same chant.

Which confirms the old adage about bad habits learned early are almost impossible to break.  If you repeat to yourself the same mantra 1,000 times a day and find out it's wrong it is very difficult to correct yourself and not make the same mistakes over and over even though you know better.

I wonder if that is what makes great programmers early feedback from mentors who know what they're doing.  I think it was Suzuki Roshi who wrote a book on Beginner's Mind.  Basically once we believe that we have figured out what is going on we limit ourselves by our current knowledge base.  We see this over and over, historically a simple example is the one time wide spread believe that the world was flat.

I think continuing to cultivate a beginner's mind in our work helps us become better at whatever it is we're doing, but especially with programming.  I don't know how many times junior developers have come to me with solutions that I would never have thought of.  It is also impossible to have a big ego when you are maintaining beginner's mind.  It also doesn't fill peers and business partners with confidence all of the time but it keeps us honest and to me that is a fair trade.

 

Cheers!

-Aaron

Friday, August 29, 2008

Where is your Life?

Well it's over, sort of, anyway...

I haven't been posting a whole lot lately, on purpose.  I have been involved with a side project called LifeAware.  It is a mobile application that is designed to help people keep tabs on their busy lives.  It does a lot of very cool things.   You can read about it on the LifeAware blog and the website.

Here is a screen shot of the main screen on the phone:

 

 

 

 

 

 


I was invited to help out by some co-workers back in February; so, in the last 6 months we have been working like crazy with every free moment we had, to deliver this application.  LifeAware is one of the ADC Round 1 finalists, and the results just came out for round 2.   Unfortunately, we were not in the top 20 - you can see the list of all the finalists on Google's Code Page for Android, you can check us out as well.

We were definitely disappointed, but with the new Dream coming out soon, there is still work to be done....

Congratulations to all of the winners of  round 2.

-Aaron

Thursday, August 14, 2008

Enough! Time to get a new one!

I think to some extent I had gotten tired of my Ford Taurus.  I bought it used at CarMax and had been relatively content with it.  Even though the air conditioning has broken every summer for the last year, ongoing alignment problems (in the 5 years I had it, I had gone through at least 3 sets of tires, 4 if you count the set that it came with).

When I bought the car it already had 24,000 miles on it.  When I traded it in today it had 97,000 miles on it.  The final straw was that at soccer practice last night it wouldn't start.  I had to try 3-4 times to get the car to start and keep running.  I'll be the first to admit I don't know a lot about cars, except that when the AC stops working, it doesn't start and it has almost 100,000 miles it's time to get a new one.

So that's what I did today.  Here is a picture of my new car...

And it is new, I test drove it with 5 miles on it.  So why new you ask?  Honda Civic's are crazy cars, it is about as expensive to buy a new one as it is a used one... I got this one for around $20,000 (still a lot of money) before my trade in.  If you go out to CarMax and try to find a low mileage Honda Civic you're going to pay that much anyway.  Like I said crazy...

So, after years of people telling me I should get a Honda, I finally did.  I will say the buying experience was one of the best I've ever had.  They offered us refreshments and they had Internet available for research (or goofing off), all in all it was a very nice experience.... 

Except that now I have a new monthly payment.... But I do have a dependable car that gets 35 miles to the gallon (on the highway).

-Aaron

Tuesday, August 12, 2008

Back on windows... Sort of

Today I just dropped a couple of hundred dollars on Windows Vista and Microsoft Office 2007.  I've spent all evening messing around VMWare fusion trying to get vista installed and now that it is done all I can say is... Wow.

I know I will lose points in the Mac World but I kind of missed it.  After working over a decade on just Windows (and Linux command line) it feels like coming home.  There are definitely things that work better on the Mac but my comfort level in Windows is about 1,000 times higher.

Vista does look pretty nice too... I'm thinking that VMWare running Vista may be the best way to  run windows.  I'll let you know how it goes but so far, it's pretty dang cool.

Oh yeah, it's awfully nice to have Windows Live Writer back.  If you haven't tried it it is the best Blog Writing tool available on any platform...

-Aaron

Tuesday, July 29, 2008

What jar is that class in?

So, I'm a pretty big fan of python now.  Just about a convert, at least for some tasks...

One of the first things I did with python was to find a script that would recursively look for your jar files given a directory and then open them up and look for the class you're looking for. 

The script I found was very complicated using generator and all kinds of things that I'm just not familiar with.  I don't know if generators don't translate to Java very well or what but I just couldn't seem to wrap my head around that script.

So I wrote my own.  Here it is (I have the root directory and class file I'm looking for hard coded) but my version does just about everything the other version did with just about the same number of lines but it is way simpler.  Let me know what you think:

 

import os
import fnmatch
import re

jarExe = '/Progra~1/Java/jdk1.6.0_03/bin/jar.exe'
rootOfSearch = '/RAD7/SDP70/runtimes/base_v61/''
lookingForClass = 'com/ibm/ws/util/ImplFactory.class'

def showDirectory (directory):
  for aFile in directory[2]:
    if (fnmatch.fnmatch(aFile, '*.jar')):
      print 'searching file: %s' % aFile
      myclasses = os.popen('/Progra~1/Java/jdk1.6.0_03/bin/jar.exe -tf %s/%s' % (directory[0], aFile))
      for aClass in myclasses:
        if fnmatch.fnmatch(aClass, lookingForClass):
          print 'found: %s in %s/%s' % (aClass, rootOfSearch, aFile)
          return True

def findJars ():
  tree = os.walk(rootOfSearch)
  found = False
  subDirs = ''
  for directory in tree:
    subDirs = directory[1]
    found = showDirectory(directory)
    if(found):
      print 'found class in: %s' % directory[0]
      return True
  print 'Not found'
if __name__ == "__main__":
  findJars()

 

-Aaron

Wednesday, July 09, 2008

Snakes and Kool-Aid

So, I've been playing with Python a lot in the last couple of weeks.  And although it definitely has some oddities, I am nonetheless totally jazzed up about it.  I had forgotten how much fun and power you have when doing OS level scripting.  The last time I was seriously into scripting I was using perl and Korn shell (about 7 years ago!).

So, some of the fancy things I've done lately is to integrate python with my Maven build process and let me just say it is a thing of beauty... Not the code so much, but the power of what happens when you mix these two tools.  By simply calling the python script my application gets compiled, tested, packaged and deployed to all or just some of the environments I'm working in.  All environments are kept in sync (unless I don't want them to be of course).

I've been using python to write some testing scripts as well.  Since our services are exposed via JSON we can simply fire off a request and it just works... the code looks kind of like this:

import urllib
import demjson

class Response:
  def __init__(self, jsonDictionary):
    message = jsonDictionary['message']
    self.statusCode = jsonDictionary['statusCode']

responseObj = urllib.urlopen("http://localhost/webappName/servletName.do? /
              message={%key%22:%22value%22,%22key2%22:%22value2%22}")
responseString = responseObj.read()
responseObj.close()

response = Response(demjson.decode(responseString))

print 'successful: %s' % response.statusCode

If you are unfamiliar with JSON here is a high level read about it.

 

So by taking just a little bit of effort to create a json string and sending that to a server you can do some very powerful things...

And although Python plays a small part in these tasks it is a very effective and pleasant glue that holds everything together.

...

But why Python you ask? Why not Ruby, PHP or Perl (the list goes on and on).  There are several answers to that question but the biggest reason is *I think* I'm going to be pushing our back-end services out onto Google's infrastructure using AppEngine, and right now AppEngine uses Python. (that is a capital period by the way)

But Python is not so bad, it's fun and powerful - but do NOT mix tabs and spaces!  Using indentation to denote blocks of code is kind of an oddity to me - I kind of like curly brackets... but aside from that - I have found Python to be a lot of fun to work with...    And I'm looking forward to rewriting our back-end services that use MySql and Java to Google's App Engine and their big Object Database.

So yeah - Google Android, GWT and eventually App Engine... I have drank the Google Kool-Aid and it is oh so tasty...

Cheers!

 

-Aaron

What is JSON???

If you don't know what JSON is it stands for JavaScript Object Notation and basically looks like this:

{"key":"value", "key2":"value2"}

But you can do so much more: like nesting JSON objects in JSON objects:

{"key":"value", "key2":"value2", "key3":{"nestedKey":"nestedValue"}}

and adding arrays to the JSON Object:

{"key":"value", "key2":"value2", "key3":{"nestedKey":"nestedValue"}, "key4":[{"arrayKey1":"arrayValue1"},{"arrayKey2":"arrayValue2"},{"arrayKey3":"arrayValue3"}]}

With all of those quotes and brackets it gets ugly quick so there is a little python library called simplejson and by simply executing the following line:

print simplejson.dumps(nastyJsonString, sort_keys=True, indent=2)

you get this:

{
  "key": "value",
  "key2": "value2",
  "key3": {
    "nestedKey": "nestedValue"
  },
  "key4": [
    {
      "arrayKey1": "arrayValue1"
    },
    {
      "arrayKey2": "arrayValue2"
    },
    {
      "arrayKey3": "arrayValue3"
    }
  ]
}

 

It is simple but incredibly powerful it is way better than SOAP and shames EJB's and their complexities to no end.

 

If you are doing remoting or communicating between processes of any kind; you should take a look at JSON there are libraries for just about any language you can think of.

 

Cheers!

 

-Aaron

Thursday, June 26, 2008

How would you do that?

Wow!  When was the last time you needed to kill a bunch of rampant processes on a unix server?

I needed to do that today this is how I did it:

processes=`ps -ef | grep -i glassfish | awk '{print $2}'`

for a in $processes
do
  if [ $a -gt 5000 ]
    then
      if [ $a -lt 10000 ]
        then
          sudo kill -9 $a
      fi
  fi
done

 

How would you do it?  Notice the nested if statements - this is a much more verbose but yet clearer way to code the if (x > 5000 && x < 10000) which isn't too bad but if you need another &&or an || or two it gets nasty quick.

 

-Aaron

Wednesday, June 04, 2008

View From San Francisco

So, while in San Francisco at Google I/O we had to stop at the Cheese Cake Factory. Here is a shot from the baclony.




-Aaron


Monday, June 02, 2008

Whims of a school girl?!

So coming back from the glamour and glitz of Google I/O was far less than exciting.  I came back all fired up and excited about GWT.  If you haven't worked with GWT yet I can't encourage you enough to check it out.  It is without a doubt the best framework/methodology for web development I have used to date.

The initial version of LifeAware was done in Ice Faces (the current LifeAware link is to the PHP version of the site).  I chose IceFaces for three reasons:

  1. JSF was my framework of choice
  2. IceFaces has a nice push model
  3. IceFaces has a decent GMap component

So my experience with Ice Faces wasn't bad. In fact I would say they probably have the best implementation of JSF out there (comparing to Rich Faces and Suns RI).

There were things about all of these implementations that drive me crazy though... styling them is a pain in the butt! 

When the ADC Results were announced our web site started getting a ton of hits and even a couple of registrations.  Although it was completely functional it didn't seem to be a good idea to have people poking around out there.   So we threw up a quick re-skin and disabled the app.  This took about 4-5 hours and it should have taken all of 5 minutes.

Why so long?  Well I was trying to redo it with facelets and Ice Faces.  When I went to bed that night (about 3:00 AM) it turned out that the pages rendered fine in Safari, FireFox and Opera but not IE. 

There were lots of things going on that contributed to the problem but part of the drama was the extra help the themes and skins from Ice Faces gave us.  I'm sure I could have disabled them very easily had I known how, but given the time crunch I wasn't terribly interested in figuring it out the ice faces way.  I ended up taking a compromise on the layout and threw it out there, temporarily until the PHP site could be assembled.  How sucky is that?

So there I was reeling from being burned by the styles and somewhat irritated that the GMap component I had initially liked so much ended up limiting my ability to interact with the extremely powerful GMap API.  Google's Map API can do just about anything you can think of - but the JSF wrapper's seem to leave a developer wanting and waiting for future releases...

So (finally we get to GWT), I went out looking about for a new solution that would give me easy AJAX capabilities with full GMap support.  And GWT is what turned up.  I spent a couple of weeks prior to the conference playing with GWT, trying to understand if it would solve the problems I needed it to. 

Indeed it does.  And after the conference I am totally convinced that GWT is going to be a major player on the web.

I have learned a ton just from working with GWT they use well proven Java techniques like anonymous inner classes - I now understand why and how to use those.

I'm going to stop the tech talk about GWT for now - again if you haven't played with it go and download it now, RIGH NOW!  Here is the link!

So why the title "Whims of a school girl" for this post?

<sigh> I am an evangelist by nature I know that about myself - I try to keep it reigned in, but every once in awhile it gets out.  So, I talked to my boss about GWT and jokingly said that we would have to re-write the Reference Architecture Standards document and he just rolled his eyes and said "the only thing that comes to mind is the whims of a school girl"  basically calling me fickle (at least I think).  I suppose he may have meant I am overly dramatic and extremely talkative though...

I have been working with JSF for about a year and a half and although I'm not sure I would say I have mastered it, I am very comfortable in it and know how to make it do what I want (except use css effectively).  It kind of irritated me to hear someone say that I am fickle. 

I suppose to be fair that is part of the game of being an early adopter but every frame work I have used has solved some problems and created others.  I'm still looking for the problems that GWT creates though, I'm only about a month into it I may find them yet.

I told one of my co-workers today that JSF was 100 times better than Struts, but GWT is 1,000 times better than JSF. I think that is a pretty decent estimate.

Cheers!

-Aaron

Wednesday, May 28, 2008


Google I/O has begun!  

We had just sat down for the keynote when the Google VP of Engineering who is also giving the keynote came over and introduced himself to us - asked us about our T-shirts.  He congratulated us on the Android Competition win and then went to prepare for the keynote.

Pretty Cool!

-Aaron

Thursday, May 01, 2008

So this is my second post on my Mac.... and I’m kind of missing some of the software I had on my Window’s XP. I’m getting comfortable enough with the operating system although there are a lot of keyboard shortcuts and symbols that I have no idea where those keys are. But the software I had I think I mentioned editplus earlier but the tool I had that helped me write blog entries was Microsoft’s Window’s LiveWriter it integrated beautifully with picasa... so well I didn’t even know it was doing it (plus it was free).

I tried ecto for a bit and it was less than pleasant. Right now this post and the last one are coming from MacJournal.

So here is a little picture just before the storm hit us tonight. There were actually tornado sirens screaming and everything. My daughter was in the backseat and turned around said “Dad look at the rainbow.” So here is the picture taken with my phone...



Cheer’s,

-Aaron

Tuesday, April 29, 2008

So, I have a bit of a confession here. I have recently purchased a new Mac Book Pro. It’s about 2 weeks old now and I can’t say the transition has been painless... It’s hard to migrate from working in a almost exclusive windows environment for the last 12 years (My first computer was a mac OS 7). I have to think a lot about how things work now keyboard shortcuts are different... Applications are different I sorely miss my editplus, I love that application. It is one of the few that I actually registered - and highly recommend it to anyone who does any type of file manipulation or scripting...

Anyway, I’ve been working on a super secret project that will eventually evolve into developing an application for the iPhone and to do that type of development then you have to have an Intel PC mac. It is kind of crappy - but I was in the market for a new PC anyway my previous laptop was over 4 years old (still running very well but showing a bit of age). I will say that GlassFish has never run better, and it is truly amazing how much development software it comes with out of the box. I’ve started playing with Objective-C and Cocoa just a bit and they are very cool I can totally understand why a developer would want to use the Cocoa Framework and XCode.

Anyway, I just wanted to get that off of my chest... I’m not a zealot yet - it is just a tool after all but it definitely a powerful system - and a 17“ wide screen is a beautiful thing indeed.



-Aaron

Monday, April 14, 2008

Code Nuggets

A friend just told me about a nifty little feature in commons-lang:

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public String toString(){
    return ToStringBuilder.reflectionToString(this, ToStringStyle.SIMPLE_STYLE);
}

 

What that does is spit out all the properties of your object when you call a toString on it.

 

Another little gem I have ended up using a lot is when I write test cases with spring.  When you extend the AbstractDependencyInjectionSpringContextTests object one of the methods you need to override is the protected String[] getConfigLocations() method.

Getting your spring context to load correctly is critical to getting your spring app to run and can cause a lot of head scratching and frustration here is a little trick to get it to load correctly - it is a bit hackish but in some scenarios it works well.

import java.io.File;

import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

public class AbstractTestCase extends AbstractDependencyInjectionSpringContextTests {
    public final String RELATIVE_LOCATION = "src/test/resources";
    public final String FILE_NAME = "persistence_ioc.xml";
    @Override
    protected String[] getConfigLocations() {
        File aNewFile = new File("./");
        StringBuilder contextLocation =
            new StringBuilder(
                aNewFile.getAbsolutePath().substring(0,
                        (aNewFile.getAbsolutePath().length() -1)
                )
            );
        contextLocation.append(RELATIVE_LOCATION).append("/").append(FILE_NAME);
        File test = new File(contextLocation.toString());
        if (!test.exists()){
            System.out.println("!!! file doesn't exist at: " +
                    test.getAbsolutePath());
        }
        return new String[]{"File:" + contextLocation.toString()};
    }
}

Like I said a little bit hackish but effective nonetheless.

 

-Aaron

Tuesday, April 08, 2008

Ownership

In the enterprise Software Development Project Management thought process there is this concept that software developers are resources.  I suppose from the initial project development that is arguably true, more or less.  But what happens when the project is over; the deliverables have been delivered.  Who supports the project, who maintains the project and who enhances the project?  Basically who is the technical owner or steward?

This is an important part of the "Software Development Life Cycle" that is forgotten, at least where I work.  I recently came off of a fairly successful project where we delivered a fairly standard application - a web based front end that talked to an EJB service that depending on the request would call other "enterprise" services to perform the requested function.  Kind of like the diagram below:

standard

 

So in the development of this project some of the extended services were already in existence, others were new development efforts.  I had the opportunity to design and implement one of the services.  My intent was for this service to be reused by another application I used to work with, not thinking I would really get the opportunity to see it get reused but I wanted the option to be there.  Well that other applications is getting re-done soon - and I would really like to see that project use the service I wrote for it.

Unfortunately the service I wrote does not really have an owner.  It is out there chugging along quietly behaving by itself so it is pretty much forgotten.  That seems to be pretty typical, when applications work well they are forgotten.  Somehow the concept of project ownership (or maybe stewardship) is a foreign concept in a lot of places.  If someone has developed a service/application they need to be responsible as the steward sure they can transition it to someone lese but applications should never be delivered and forgotten. 

So what does it mean to be a project steward? If you are a steward then you should be the most knowledgeable person on how the application should be evolved and reused.  The steward should be involved when changes are requested or if someone wants to use it.  They should also be responsible for documenting and troubleshooting it.  They don't necessarily have to have the final say in some decisions but their views should be taken seriously. 

When there isn't a steward the services don't get reused and they begin to stagnate, other people start to re-solve the problem the service was written for.  Knowledge is forgotten, documentation isn't written, basically the software dies and that is not good.  Our software creations can only live if we take care of them.  In the world of SOA this part of the equation is forgotten - for services to be maintainable and reusable they have to have someone that is looking out for them.

I think that is why so many open source projects are successful, they have people working on them that care about the project's success and have the sense of responsibility - the end result is owned by them.  Without that commitment software development is not much different from working at McDonald's - you crank out as many cheeseburgers as you can, as quickly as you can.  If some cheeseburgers get undercooked and make people sick - well it's not your fault really....  Someone else is responsible for making sure you do your job right.

We have to have ownership in everything we do - otherwise there is no reason to do anything.  When managers shuffler resources around because resource constraints - all it really does is make a lot of people sick from undercooked cheeseburgers software.

 

-Aaron

Monday, March 03, 2008

"It didn't kill us, so it must have been ok"

The title of this entry are some fine words of praise I got today.  I left the safety of the Ivory Tower of IT today to grab a snack and ran into the VP of one of the business units that my team developed an application for last year.  I asked how everything was going with the new application and that is what he told me "It didn't kill us, so it must have been ok".  He wasn't talking about just the new applications they just completed the last month of the "busy season" but clearly the applications were not as much of a help as we had hoped.

He then quickly moved into how the business process is changing and how understaffed they were; typical concerns everywhere I guess.  That line of conversation about the business process, prompted a whole line of  thought on the way back.  It's funny how so many of the seasoned, high powered developers seem to scoff and complain about processes.  While on the business side of the house the process is what makes or breaks a company.  Some might even say, that the process of how things are done is what differentiates one player in an industry from another.

It seems odd sometimes that IT gets away with as much as we do.  Breaking processes when we see fit, taking short cuts, the list could go on and on I'm sure.  It makes me wonder how different the "processes" in a software development company is from a company who develops software as a by-product of their business.

Someday I hope I'll be involved with a software solution that at the end of a busy season the user says.  "Wow that worked great! I don't think we would have made it through those last 3 months without that application."  Maybe that is just a dream though...  New applications cause business processes to change and ultimately when it comes down to it everyone hates change, good or bad. 

Maybe in another year the business will say "How did we ever get along without that application?"  Still not glowing praise but at least we wouldn't be compared with death and dying...

 

Cheers,

-Aaron

Friday, February 29, 2008

Single Sign on with glassfish

Holy cow check out this little nugget taken from the GlassFish manual:

 

User Authentication for Single Sign-on

The single sign-on feature of the Application Server allows multiple web applications deployed to the same virtual server to share the user authentication state. With single sign-on enabled, users who log in to one web application become implicitly logged into other web applications on the same virtual server that require the same authentication information. Otherwise, users would have to log in separately to each web application whose protected resources they tried to access.

An example application using the single sign-on scenario could be a consolidated airline booking service that searches all airlines and provides links to different airline web sites. Once the user signs on to the consolidated booking service, the user information can be used by each individual airline site without requiring another sign-on.

Single sign-on operates according to the following rules:

  • Single sign-on applies to web applications configured for the same realm and virtual server. The realm is defined by the realm-name element in the web.xml file. For information about virtual servers, see the Sun Java System Application Server Platform Edition 9.0 Administration Guide.
  • As long as users access only unprotected resources in any of the web applications on a virtual server, they are not challenged to authenticate themselves.
  • As soon as a user accesses a protected resource in any web application associated with a virtual server, the user is challenged to authenticate himself or herself, using the login method defined for the web application currently being accessed.
  • Once authenticated, the roles associated with this user are used for access control decisions across all associated web applications, without challenging the user to authenticate to each application individually.
  • When the user logs out of one web application (for example, by invalidating the corresponding session), the user's sessions in all web applications are invalidated. Any subsequent attempt to access a protected resource in any application requires the user to authenticate again.

The single sign-on feature utilizes HTTP cookies to transmit a token that associates each request with the saved user identity, so it can only be used in client environments that support cookies.

To configure single sign-on, set the following properties in the virtual-server element of the domain.xml file:

  • sso-enabled - If false, single sign-on is disabled for this virtual server, and users must authenticate separately to every application on the virtual server. The default is true.
  • sso-max-inactive-seconds - Specifies the time after which a user's single sign-on record becomes eligible for purging if no client activity is received. Since single sign-on applies across several applications on the same virtual server, access to any of the applications keeps the single sign-on record active. The default value is 5 minutes (300 seconds). Higher values provide longer single sign-on persistence for the users at the expense of more memory use on the server.
  • sso-reap-interval-seconds - Specifies the interval between purges of expired single sign-on records. The default value is 60.

Here is an example configuration with all default values:

     
...
<property name="sso-enabled" value="true"/>
<property name="sso-max-inactive-seconds" value="450"/>
<property name="sso-reap-interval-seconds" value="80"/>
</virtual-server>

How sweet is that?


 


-Aaron

Thursday, February 28, 2008

MD5 Encryption Java style

Here is a little nugget you might enjoy how to do some MD5 Encryption with Java pretty easy really.  Mostly taken from this book:

javaSecurityHandbook

 

package test.md5.encrypt;

import java.io.ByteArrayInputStream;
import java.security.DigestInputStream;
import java.security.MessageDigest;

import junit.framework.TestCase;

public class TestMessageDigest extends TestCase {
private static String[] hexDigits = {"0", "1", "2", "3",
"4", "5", "6", "7",
"8", "9", "a", "b",
"c", "d", "e", "f"};
public void testEncrypt(){
MessageDigest md = null;
DigestInputStream dis = null;
String digestedString = null;
try{
md = MessageDigest.getInstance("MD5");
ByteArrayInputStream bis =
new ByteArrayInputStream("password".getBytes());
dis = new DigestInputStream(bis, md);

byte[] bytes = new byte[1024];
dis.read(bytes);
md = dis.getMessageDigest();
dis.close();
byte[] digest= md.digest();

digestedString =byteArrayToString(digest);
System.out.println(digestedString);
} catch (Exception e){
e.printStackTrace();
assertTrue(false);
}
}
private String byteToHexString(byte aByte){
int n = aByte;
if (n < 0) n = 256 + n;
int d1 = n/16;
int d2 = n%16;
return hexDigits[d1] + hexDigits[d2];
}
private String byteArrayToString(byte[] bytes){
String result = "";
for (int a = 0; a < bytes.length; a++){
result += byteToHexString(bytes[a]);
}
return result;
}
}


Not too bad is it?  Thanks to Jamie Jaworski and Paule Perrone for authoring that book (heh, I actually got in on clearance for $15.00) not too shabby...


 


-Aaron

Saturday, February 23, 2008

a wasted week

So, I did say I hated ldap right?  After fighting and fighting with I finally gave in and tried the JDBCRealm with Glassfish's security configuration.

So much nicer.  There is a brilliant post here that explains how to do it.  The only comment I would have is that you can sent the encryption to none instead of MD5 or something else. 

So, yeah I pretty much wasted a week trying to do things the "right" way.  I'm totally digging the JDBC Realm though.  It works just the way you think it should.

 

Cheers!

-Aaron

Thursday, February 21, 2008

Container Managed LDAP

<sigh> will these ldap posts ever end?

So now that I have authentication working, I want to be able to register users now.  So how can I save users easily to my ldap server?  Well I figured there had to be an easy way to get a container managed instance of the server, low and behold I found this post on making a container managed LDAP from a Java Evangelist.

Once you follow all of those instructions, what is the best way to get access to it?  With Spring of course!

It's as simple as injecting this into your bean

<bean id="ldapServer" 
class="org.springframework.jndi.JndiObjectFactoryBean"
lazy-init="default">
<property name="jndiName">
<value>ldap/directory</value>
</property>
<property name="resourceRef">
<value>false</value>
</property>
</bean>


Couldn't be easier. 

Putting it all together

So, now that I have my ldap server working (more or less).  I need to use it to authenticate with, this turned out to be surprisingly easy with GlassFish.  I created a new LDAP Realm like this:

ldapConfig

The "assign group" property was  a bit confusing - basically it is just a value that you map you application to in the web.xml and the sun-web.xml this is an exampl of how it could be done using the webusers as the value of the "assign group" property.

web.xml:

  <security-constraint>
<web-resource-collection>
<web-resource-name>Faces Servlet</web-resource-name>
<url-pattern>/pages/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>AUTHENTICATED</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>LdapRealm</realm-name>
<form-login-config>
<form-login-page>/login.jsp</form-login-page>
<form-error-page>/unprotected/loginError.jsf</form-error-page>
</form-login-config>
</login-config>


sun-web.xml:


	<security-role-mapping>
<role-name>AUTHENTICATED</role-name>
<group-name>webusers</group-name>
</security-role-mapping>


The last bit of magic is the login form:


<form action="j_security_check" method="post">
<table border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
<p>User ID<br/>
<input type="text" name="j_username" value="" size="10"/>
</p>
</td>
</tr>
<tr><td>
<p>Password<br/>
<input type="text" name="j_password" value="" size="10"/>
</p>
</td>
</tr>
<tr>
<td style="padding-bottom: 10px;">
<p>
<input type="submit" value="Log In"/>
</p>
</td>
</tr>
</table>
</form>


And that is how you can authenticate.  Now if you remember I'm using JSF to manage this and that is clearly not a jsf form.  So this is how I decided to make it work (and there are other options) it is not without problems mind you, JSF makes a lot of things better but in so doing messes up a lot of old conventions.


I have decided to work on the assumption that users are going to navigate to my web site by saying http://www.my great web site.com  I have the welcome page in a "protected" area so that by navigating to the welcome page you will get kicked out the the registration screen if you are successful then you get sent to the welcome page which does a jsp:forward to the welcome page through a faces context.  It is overly complicated I think but we have to make sure that the faces context is initialized correctly.

Thursday, February 14, 2008

OpenLDAP

So I'm not a big fan of LDAP of any kind.  It could entirely be out of ignorance I will admit to that.  It seems very out dated when the info you store can be done SOOOO much easier in a database.

 

Having said that it seems all "real" applications have an LDAP server back end.  So, tonight I have decided that this is the night when flyingspheres has a working LDAP server.  Not that I really need one mind you it is really just me for the most part, but to really play with security modules in Java you need to have the container working together with an ldap server.

So here we go...

I will be referencing lots of sites to get this work done.  Mostly cause me not so smart when it come to LDAP...

OpenLDAP comes down from the friendly synaptic manager.  Once you get that installed (very easily mind you) you get a new config directory at /etc/ldap which looks like this:

 

-rw-r--r-- 1 root root  333 2007-04-27 10:19 ldap.conf
drwxr-xr-x 2 root root 4096 2007-12-03 14:05 sasl2
drwxr-xr-x 2 root root 4096 2008-02-08 18:38 schema
-rw------- 1 root root 4340 2008-02-14 21:56 slapd.conf

 


Now, when I installed OpenLDAP I think my server wasn't named very well so if you were to try and connect to me (and I opened a hole in my firewall) you would see the DN of nodomain.  Heh, is that cool or what?


So first order of business how do I change that?


Sprinkled liberally throughout our slapd.conf file is a reference to nodomain.  This is no doubt a problem.  Before we go mucking around it let's back up that file first... 


... ok backup complete.


Now let's go through and change the cn="nodomain" to cn="flyingspheres",cn="com"  (make sure you get them all).


Ok, that's done.


YoLinux points out that the database our ldap server is under the directory attribute.  By default uBuntu put mine here: "/var/lib/ldap".  Common sense says that's where the nodomain database lives so I'm going to move it somewhere else.  if you look in that /var/lib/ldap directory there is a lot of stuff there.  I wonder what it all is... oh well.... so made my new directory and pointed slapd.conf to it.  I'm hoping that when I restart slapd (openLdap) all that stuff will be created in my new directory.  Once the directory is created and slapd points to the correct location it's time for a restart.  (upon restart there was no love.... my directory was empty... maybe that's ok).


So after about 20 minutes of poking around looking through the OpenLdap link things started working.... I can connect there are db files in the directory defined for the db.  I initially created an ldif file with only the admin user and that worked pretty well, although connecting went through anonymous bind only.


 


So, many minutes later (maybe an hour or so).  There is a mildly intuitive relationship between the object classes and attributes to what you are wanting to store in your LDAP.  I'm sure if someone reading this knows what they're doing they're laughing now.  You need to pull in the objectClasses that you want into your LDIF file and then add the attributes you care about (and the ones that are required, hopefully they're the same).



I ran the ldapadd probably 50 times trying to figure out the right combination.


 


Like I said I'm not a real big fan of LDAP...


 


-Aaron

Tuesday, February 12, 2008

Begin Again

So, I'm starting a new project. 

It never ceases to amaze me how difficult java web applications are to setup.  A lot of it is because of all the different frameworks we get to choose from.  This project appears to be going to use Ice Faces (a JSF implementation/extension), Facelets some level of Spring Integration, possibly JPA or Hibernate.

I played around with RichFaces and facelets a few months ago and was able to lean on the JBoss IDE for some of the configuration, but since I'm using Ice Faces this time I don't want all of the extra stuff that comes with the JBoss IDE.

So we get to start from scratch.  The documentation is pretty decent on what needs to be added to the web.xml and faces-config.xml to get facelets working correctly.  But after that where do you start?  I guess the best place is always the beginning so let's code up the index.html page (always a good place to start).

As you know for faces to work you need to be working w/in a faces context so this is a really good places to initialize the faces context let's make a silly little index.jsp page that simply forwards us inside the context:

 

		
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<html>
<head>
<title>My Title</title>
</head>
<body>
<jsp:forward page="pages/login.jsf" />
</body>
</html>

 


So, that's easy enough.  But, with Facelets we don't want to really be writing jsf or jsp pages.  Clearly we are forwarding to a jsf page though what gives?  We create a url-pattern mapped to a Faces Servlet so any request to our url pattern (*.jsf) get's routed through the faces context.  One last thing we need to make sure our faces.DefaultSuffix is linked to *.xhtml pages.  So our pages/login.jsf page will land on the pages/login.xhtml page.   Remember with JSF it is all about the faces context stay in the context and you will be ok. This is why (IMHO) if you're doing AJAX you really need to use a framework like RichFaces or IceFaces.  You're just asking for death by a million cuts to go any other route.


So I got all my xhtml files created the web.xml and faces-config.xml are all tweaked out and guess what the dang thing didn't work.  I kept getting this error:


 

[#|2008-02-12T23:32:08.192-0600|WARNING|sun-appserver9.1|javax.enterprise.system.stream.err|_ThreadID=12;_ThreadName=httpWorkerThread-4848-0;_RequestID=837d6942-3e34-4c0f-b9de-40c1419d7e40;|
java.lang.UnsupportedOperationException
at com.sun.faces.config.ConfigureListener$InitFacesContext.getViewRoot(ConfigureListener.java:1690)
at com.sun.faces.util.MessageFactory.getMessage(MessageFactory.java:113)
at com.sun.faces.util.MessageUtils.getExceptionMessageString(MessageUtils.java:277)
at com.sun.faces.util.Util.createInstance(Util.java:477)
at com.sun.faces.config.ConfigureListener.configure(ConfigureListener.java:671)
at com.sun.faces.config.ConfigureListener.configure(ConfigureListener.java:503)
at com.sun.faces.config.ConfigureListener.contextInitialized(ConfigureListener.java:402)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4493)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:5150)
at com.sun.enterprise.web.WebModule.start(WebModule.java:308)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:960)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:944)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:671)
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1575)
at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1216)
at com.sun.enterprise.server.WebModuleDeployEventListener.moduleDeployed(WebModuleDeployEventListener.java:169)
at com.sun.enterprise.server.WebModuleDeployEventListener.moduleDeployed(WebModuleDeployEventListener.java:265)
at com.sun.enterprise.admin.event.AdminEventMulticaster.invokeModuleDeployEventListener(AdminEventMulticaster.java:951)
at com.sun.enterprise.admin.event.AdminEventMulticaster.handleModuleDeployEvent(AdminEventMulticaster.java:938)
at com.sun.enterprise.admin.event.AdminEventMulticaster.processEvent(AdminEventMulticaster.java:448)
at com.sun.enterprise.admin.event.AdminEventMulticaster.multicastEvent(AdminEventMulticaster.java:160)

This seems to be a pretty nasty error, all it is really saying is "Hey I somebody is referencing a class I don't know anything about".  This is probably java's biggest criticism happening right here on my laptop.  I think there are a total of 16 jars I needed to get my very simple page to work here.  Don't get me wrong I'm most thankful to the people who wrote them.  But man it is sure a pain to be trying to figure out what you need and what you don't.


I actually opted for the shotgun approach.  I ended up taking a demo app that comes with Ice Faces and pull out all of the jars from the demo and add them to my project.  Not very accurate but it did fix the problem.


That's enough for tonight.  I'll let you know how it goes.


By the way I got the ice faces demo apps running here:



 


-Aaron

Tuesday, February 05, 2008

More Recovery

I certainly don't understand the intimate details of all the parts and pieces of the different technologies or applications that I use sometimes.  I have an intermediate level understanding of a lot of the parts such as Apache.  Through trial and error I had figured out how to configure it to do what I wanted it to do.  The old server had MOD_JK installed and would forward some requests over to my GLASSFISH server.  Due to a lack of understanding I had gone through the exercise of compiling apache and mod_jk myself to get it all working.  And I was pretty happy with that, he advantage of doing that is that you know exactly where all the binaries and configuration is and where it's located.

With this version of the server I'm (trying) to use the synaptic package manager and haven't had to compile anything yet.  I simply clicked on Apache in the Synaptic Package Manager and it installed a working version- very simple, very painless.  The configs and htdocs are a bit scattered but I found them eventually.  MOD_JK came down through the synaptic package manager as well.  So what do we need to do to get it all working?  There are several posts that are very helpful:

Amy Roh's from Sun

Jean-Francois Arcand's from Sun

 

Amy Roh's blog is laid out pretty clearly

Step 1) install MOD_JK (thanks Ubuntu)

Step 2) get the necessary jars from tomcat and put them in the glassfish lib.  I initially installed Tomcat 6.0.14 hoping that it would have the necessary jars but it didn't.  So I had to go get the recommended version (5.5.16) Jean-Francois says you only need tomcat-ajp.jar but Amy Roh's says you need 3 (tomcat-ajp, commons-logging and commons-modeler)

Step 3) enable ajp:

$GLASSFISH_HOME/bin/asadmin create-jvm-options -Dcom.sun.enterprise.web.connector.enableJK=8009

Also you need to define where the properties file is :

$GLASSFISH_HOME/bin/asadmin create-jvm-options -Dcom.sun.enterprise.web.connector.enableJK.propertyFile = <fileName>

That is it sort of... There are a couple of gotcha's on the way, but nothing that is too terribly difficult.  I have to take a lot of things on faith and they usually work but when they don't things get ugly quickly.  The mod_jk needs to be configured in your httpd.conf, also there is a worker.properties file that defines worker's and what they do, and the enabled MODS (taken care of on step one). 

Ubuntu/Apache does have a very fancy set of commands called a2enmod and a2ensite.  If you're wanting to create a virtual host you setup an virtual host file in the site-available directory and call a2ensite on it - a2enmod works about the same... read here if you're interested about it.

 

Next I think I'll talk about getting websvn and hgweb setup both are pretty cool.  WebSvn has far more features but Mercurial is pretty dang fancy too though...

Talk to ya later.

 

-A

Saturday, February 02, 2008

Subversion

One of my biggest concerns that I had lost was my source code repository.  Again, not a lot of stuff out there but several projects that were kind of interesting.  The good thing about the way my old server crashed was that the hard drive was intact.  I did a very small amount of research and ran across this article basically you issue a command to dump the old repository and issue another command to import it into a new repository.

Dump:

svnadmin dump /path/to/repo > reponame.dump
tar zcf reponame.tgz reponame.dump
scp reponame.tgz hostname:/path/to/new/repo

 

Import:

cd /path/to/new
svnadmin create reponame
tar zxf reponame.tgz
svnadmin load reponame < reponame.dump

 

That was basically the extent of recovering my source code repository.

 

Sweet!

-Aaron

Recovery In Progress

I had been hosting my own domain www.flyingspheres.com for awhile not much out there really, more of a sand box for me to work in than anything else.  Somewhere around January 5th the computer I was using as server died.  It wouldn't boot or even POST.  I'm still not sure exactly what happened to it.  I attempted to replace the mother board and CPU but do to a serious lack of inclination and knowledge I never got it working and took all the pieces back to where I purchased them. 

I was feeling all bummed about it, worried I had lost a lot of info (source code, database info, etc.). 

And Just the other day I went out to Nebraska Furniture Mart and found a really good deal on a new Desktop PC.  I went ahead and picked it up and have been going through all the recovery issues that I can.  I'm going to try and document the recovery process and setup of this new server in case it happens again....

 

-Cheers!

Aaron