Another week with the Droid

When I last posted, things weren’t looking so good for my use of the Droid, and I had pretty much convinced myself that I was going to have to swap it out for the Eris. Fortunately, I didn’t do that and instead decided to give it another shot. I did a factory reset to wipe everything and start fresh, and then I proceeded very slowly. Rather than installing the somewhere around 40 apps that I previously had all at once, I started to trickle them over a period of several days, and I also switched things up a bit by choosing alternatives to what I previously had when there was a feasible other option. I’m happy to report success this time, and I haven’t had a crash or reboot all week.

Now that it’s stable, my fanboi status is back in full force. I really love this phone. It’s really fast, the display is incredible, the already-good browser is much improved over the G1, and I’m even starting to accept the crappy keyboard (and I actually typed much of this post on it while standing in line to see Lars von Trier’s Antichrist). I’ve used the car mode and Google Maps Navigation a few times, and I’m very happy with it, and find it a significant improvement over the VZ Navigator app I was previously using on my Blackberry. The voice search has never misunderstood me, which is really impressive.

Last night, I finally got up the courage to try putting the UnboundID LDAP client on it to test it out and it works just as well as it did on the G1 (actually, quite a bit better because it’s faster and on a better network). I hope to give it a much-needed update and make it available in the market in the near future.

A Week with the Droid

At the beginning of the year, I got an Android Developer Phone 1 (basically an unlocked version of the T-Mobile G1) and was using it on T-Mobile’s network. For the most part, I loved the phone but hated T-Mobile’s network. If only I could have an Android phone on Verizon’s network, things would be perfect. So I waited anxiously for any news to come and eventually the rumors started to trickle in. Finally, Verizon launched the Droid last Friday and I was there early before the store opened, second in line to get one. I was in love. It’s a much faster phone than the G1, with a better display, better battery life, better camera, more memory, newer version of the operating system, better maps and navigation, better everything. Well, it didn’t have a better keyboard (the G1 keyboard has five rows of buttons with one row dedicated to numbers, while the Droid’s only has four and you have to use the alt key to hit the numbers which is kind of annoying, and also the G1 keys are more separated and feel better than those on the Droid).

My love for the Droid grew over the weekend. I saw four movies (two each on Friday and Saturday), and it kept me company while I was waiting for them to start. I downloaded and installed several apps from the Android market, most of them free but some of them purchased. However, that’s when the problems started. On Sunday evening, I purchased the Better Terminal Emulator Pro application and instantly the phone rebooted, and as soon as it came back up, it rebooted again, before I could do anything at all. And it kept rebooting. There was nothing that I could do to stop it. I found that if you hold down the “s” key or the menu key (on the keyboard, not the one below the screen), then the phone boots into safe mode, but even that wasn’t enough because it still rebooted. Trying to attach it to my computer over USB (from Linux or Windows) was unsuccessful, since it wasn’t getting far enough to allow me to see the device or attach to it.

Clearly, I couldn’t do anything at all with the phone in that state, so my only option was to take it back to the Verizon store on Monday morning, and they replaced it for me. Because it was tied to my Google account, all of my contacts and apps synced down without any problems, so it wasn’t too much of a hassle to get the second one configured like I had the first one. I did most of it in the car before leaving the Verizon store to head into work.

Surely it was just a bad phone and everything would be fine with the new one. Unfortunately, that wasn’t the case. The battery in the new phone wasn’t fully charged, and as soon as I plugged it in when I got into the office, it rebooted. Fortunately, it only rebooted once and didn’t enter an infinite reboot loop like the last one, but I was nervous. One of the applications that had automatically synced was the Better Terminal Emulator Pro application that had seemingly triggered the problem on my first one, so I thought it would be safer to get it off the phone in case it did something to make things unstable. So I uninstalled and refunded the app, and instantly the phone rebooted, and it kept rebooting nonstop. Another trip to the Verizon store (a different store this time, mainly because it was closer to the office) over lunch and I got my third Droid. The problem app wasn’t ever on this phone, and things generally seemed to be OK., although I still noticed occasional reboots, especially if I got a text message.

Earlier today, I was working and signed up for an online service that needed to activated over the phone. I entered my phone number and waited for it to call, but nothing happened. That was when I noticed that my phone was again stuck in a reboot loop. Once again to the Verizon store. This time, I was determined to not let it happen again. I made sure that it was completely new hardware (e.g., so they didn’t move the memory card from my previous one to the new one) and I even used a completely separate Google account. I proceeded with extreme caution, and things were looking positive for a while. However, again since it was a new battery it wasn’t fully charged so I plugged it in to charge it, and fortunately it didn’t reboot. I sent it a text message and it didn’t reboot then either. So things were finally fixed, right? Nope. A while later I looked at the phone and noticed that it was once again stuck in a reboot loop. Fortunately, when I unplugged it, it stopped rebooting, and it started back up when I plugged it in again. So I left it unplugged and let it come back up, and then I sent it a text message and it rebooted right away.

At this point, I’m stuck. I really want to love the Droid, and when it’s not rebooting it’s an extremely nice device. But if it crashes when I plug it in to charge it, or when I receive a text message or a phone call, then it’s really not of any use to me. At this point, I think that my only recourse is to take it back and swap it out for the HTC Droid Eris (which is also on Verizon’s network and also launched last Friday). It’s not as nice a phone as the Motorola Droid pretty much all the way around (smaller screen with a lower resolution, less memory, no physical keyboard, not running Android 2.0), but HTC has more experience building Android devices than Motorola so hopefully it will be stable. So I’m off to the Verizon store again tomorrow, hopefully for the last time in quite a while.

Austin Film Festival 2009 part 2

Day 4 — Sunday, October 25

Strigoi — This is a very authentic Romanian vampire movie, by which I mean it is true to the Romanian vampire legends and not the more popular version that we typically see portrayed in movies. The Romanian vampires don’t vaporize in the sunlight, and although the may not like eating garlic or going into churches, doing so won’t do any significant damage. The writer/director has spent a lot of time in Romania, and her husband (who I think was a producer) is Romanian. The movie is in English rather than Romanian with English subtitles or dubbing.
Overall, I liked the movie. It did feel a bit slow at times, but it was interesting to see how vampires are portrayed in their original culture. 7/10.

Shorts — This is a series of short films (10-20 minutes each) shown back-to-back. They were:

  • Sugar Rush — A Gremlins-type tale about a little girl who turns into an absolute monster when she is given sugar, and a babysitter and her boyfriend who ignore the advice of her parents. It was pretty fun, if not a bit cliche. 6/10.
  • A Little Mouth to Feed — A religious woman who has repeatedly failed to have a baby prays to the devil instead and gets a demon child. 6/10.
  • Unawakening — A story about a man who has a recurring nightmare of killing someone and burying the body, triggered by a past event that he has repressed. 6/10
  • Lambs — A couple of guys stage a broken-down car so they can rob whoever comes to their aid, only to find the tables turned when a 50’s style Ward Cleaver type turns hardcore. 8/10.
  • Survivors — A man and woman hole up in a bar to try to stave of a zombie attack. 7/10.
  • Slasher — A story about a rather outcast kid who stabs a fellow classmate in an altercation at a party. No obvious point, and very boring. 2/10.

Hunger — Five loners with varied pasts find themselves abducted and held hostage together in an underground bunker. They are given plenty of water, a crude toilet, a knife, and a clock to tick off the number of days they’ve been held. They aren’t given any food, but it becomes clear that their captor expects them to eventually turn against each other.
This was an excellent psychological thriller, that wasn’t really scary or particularly intense but was a well-told story and well-acted movie. My only real complaint is that the characters’ appearances didn’t seem to reflect the duration accurately (e.g., guys weren’t really amassing a lot of facial hair, and a girl’s white shirt was still a pretty brilliant white after a couple of weeks). The director did mention that they had someone looking at continuity, and scenes were shot in sequential order and within a time frame that was about the same as that portrayed in the movie, so it’s probably something that probably should have been handled a little better. Nevertheless, it was still a great movie so I’m willing to overlook the continuity. 8/10.

ZMD: Zombies of Mass Destruction — A small island town off the coast of Washington finds itself in the midst of a zombie infestation. Like every other zombie comedy, a small group of people try to survive, while family, friends, and neighbors are overcome.
There have been a lot of zomcom movies in the last few years, and this one isn’t a serious contender against the top tier movies like Shaun of the Dead or Zombieland, but it can hold its own against most others. It was quite funny and had plenty of gore, so it was never slow or boring. The director said that they had recently gotten a distribution deal, so it may be making it to theaters early next year, and I think that it’s worth seeing if you like this type of film. 7/10.

Day 5 — Monday, October 26

Little Fish, Strange Pond — Callum Blue plays a murderer named Sweet Stephen who’s a bit off his rocker. He’s accompanied by a man known only as “Mr. Jack” (Matthew Modine), who is kind of like a human embodiment of the voice in Stephen’s head encouraging him and antagonizing others (more like Tim Roth/Amanda Plummer in Pulp Fiction than Edward Norton/Brad Pitt in Fight Club). It’s a very fun dark comedy that also features Zach Galifianakis, Adam Baldwin, and Don McManus. I give it an 8/10.
I really loved Callum Blue’s performance in this, and it evoked a lot of fond memories of his role in Dead Like Me. A small grim reaper doll was prominently featured in one scene, and you could consider him playing a kind of reaper role to Matthew Modine’s graveling. He also had a great “don’t talk during the movie” scene that would be perfect for the Alamo Drafthouse to run before the trailers.

Happy Ending — This is a Japanese movie (with Engrish subtitles) about a not-very-girly lead character who is very into movies and is beginning to see her life as a movie, much like Jamie Kennedy’s character in Scream. She’s generally more into horror movies than romantic comedies, but that starts to change when she happens across a guy who she wants to notice her. She enlists the help of her friends (including one who secretly likes her, ala Duckie in Pretty in Pink).
I generally liked this movie, although it wasn’t very original. It also seemed to develop a bit slowly toward the end. Nevertheless, I liked the humor and the self-referential nature. 7/10.

Day 6 — Tuesday, October 27

Myna Se Va — This is a movie about a woman living as an illegal alien in Spain, where she was a nanny for a young boy. His parents went out of town on a ski trip, and she was left to care for him. When he got injured, she had to find help for him while avoiding being found out and deported.
The premise for this movie sounded interesting, but its execution fell flat. This was without question the worst movie I have ever seen. The subtitle translation was horrible. The camerawork was horrible, and there were minutes at a time with absolutely nothing happening on the screen (no people or objects of interest visible, and not particularly focused on anything, with only occasional sounds). The pacing was unbearably slow. It had more false endings than Return of the King. It had completely unnecessary flashbacks that didn’t provide any useful information. And there was a 30-minute sequence in the middle of the movie that was so painful to watch that I can’t even bring myself to describe it. I would say that at least half the audience walked out, and I would have if there hadn’t been two other movies following it in the same theater that I wanted to see. I can’t see any value whatsoever in this movie, and I give it a rating of zero out of ten.

Earthwork — This is a documentary that tells the true story of a man who creates incredible artwork through landscaping. From the ground, they don’t look like much, but from the air they turn into very intricate scenes depicting all kinds of things, like people and nature. He had been doing this all his life and had become a bit of a minor celebrity in his hometown of Lawrence, Kansas but he wanted a bigger audience, and jumped when he heard about an opportunity to create his artwork on land owned by Donald Trump shortly before it was to be used to erect skyscrapers. He undercut all of the other competitors by basically offering to do the work for free, and paying all of the expenses himself (effectively putting himself deep into debt by taking out a loan to cover the costs), and he enlisted several homeless men to help him out. He of course encountered a number of difficulties in the process, and it doesn’t necessarily turn out as you might expect, but it’s definitely worth a watch. 9/10.

The Vicious Kind — Alex Frost plays a college student who brings his girlfriend (Brittany Snow) home for Thanksgiving. His father (J. K. Simmons) and brother (Adam Scott) aren’t on speaking terms, nor can they even stand to be in the same place at the same time. They haven’t spoken in several years, since the mother’s death. Things got even more tense when the brother’s treatment of the girlfriend alternated between hostile and obsessive.
This was a very good movie, although at just over 90 minutes I felt that it could have been longer and a couple of story lines weren’t pursued as well as they could have been. The line producer (who was in attendance) mentioned that a lot had been cut out in editing to prevent it from dragging on too much, but I think that perhaps too much had been cut. 8/10.

Day 7 — Wednesday, October 28

Tenure — Luke Wilson plays a literature professor named Charlie who is up for tenure at a small college, after two previous unsuccessful attempts at other schools. He loves teaching, and the students love him, but he’s under pressure to focus more on other academic pursuits like getting published. Things get a little more anxious when another professor (played by Gretchen Mol) enters the picture and joins the tenure race. Even though she gets off to a rocky start as a teacher, she has more impressive credentials and has been published in a prestigious journal.
This movie had two different personalities. I think that the primary story was well executed and generally enjoyable. However, it was awkwardly intertwined with some attempts at comedy which fell a bit short. The quest by a fellow professor (David Koechner) to find Bigfoot, a student’s attempts at erotic comedy, and a fake double date (with Rosemarie DeWitt) felt out of place and in some cases were almost painful to watch. 6/10.

American Cowslip — This is a very odd movie about a heroin addict named Ethan Inglebrink (played by Ronnie Gene Blevins) who hasn’t left his house in years but is being evicted by his landlord/next-door neighbor (Rip Torn) because he’s unable to pay the rent. About the only thing that he does well is tend to his garden, and he is the primary obstacle in the way of his landlord’s victory in a home landscaping competition.
Despite his addiction and agoraphobia, and in spite of his constant neediness and lack of personal responsibility, Ethan is very well-liked by most of his neighbors (a pretty noteworthy cast, including Diane Ladd, Cloris Leachman, Priscilla Barnes, and Hanna Hall), although his well-meaning but somewhat misguided brother (Val Kilmer) appears to be the only one trying to get him to really improve himself. The film has a pretty crazy climax, but I think that it took too long to get there and I just couldn’t connect with the characters and get into the movie like I wanted to. 5/10.

Thank you, Don

This weekend, Don Bowen passed away, nearly two years after being diagnosed with brain cancer. His battle certainly had its ups and downs, but his faith in God remained strong and was truly an inspiration to me, and I’m sure to many others. He has long been one of the men I admire most, and although it was sad to see him go, we can take comfort in the knowledge that he is truly in a better place, free of pain and full of praise.

I first met Don about ten years ago when we both worked at Caterpillar. I was fresh out of college and inherited responsibility for the Corporate Web Security (CWS) system, a web-based single sign-on environment built from scratch using a collection of Perl scripts, a web server plugin, and (at the time) Netscape Directory Server 3.11. Don had previously overseen the CWS project, and someone suggested that I talk to him to learn more about how it was put together. He gave me a pretty good grilling, and actually I came out of it a little scared of him. I can’t imagine what he must have done to the guys brave enough to try to date one of his daughters. Nevertheless, I must have done well enough because within a few months he asked me to join him at a startup in Baltimore (B2B Communications, later renamed to TidePoint Corporation), which I did.

Unfortunately, TidePoint fared about as well as many of the other startups around that time, and when it came to an end we separated for a bit when he went to the Burton Group and I joined Netscape Communications. However, we were reunited after only a few months when we both came to Sun Microsystems at about the same time (he actually called me and told me he was probably going to be joining Sun while I was there for my interview). And most recently, we helped to found UnboundID Corp., where despite his diagnosis days after forming the company, he was a tremendous asset to the company in many ways and I know we certainly wouldn’t be where we are today without him. Even after he was no longer able to work, he continued to stay involved and the last time I was able to have a meaningful conversation with him (about two weeks ago), he wanted to know what I was working on so he could continue to pray for me.

Please pray for Don’s wife, their four daughters, his parents, and their myriad friends. I can’t imagine how exhausting things must have been for them, especially within the last couple of weeks, but it is a blessing to see and to experience the strong support network they have. We will miss his presence, but his memory will live on, and his eternity is secure.

Austin Film Festival 2009 part 1

The 16th annual Austin Film Festival started last Thursday, and I’m attending this year for the first time. Even though I watch a lot of movies, I’ve shied away from most film festivals in the past because I was under the impression that they would be mostly a combination of artsy and preachy. While there are some of both, most of the movies I’ve seen so far are neither, which was also my experience with Fantastic Fest last month.

The Austin Film Festival lasts eight days (Thursday through Thursday), although I won’t be able to attend anything on the last day. Nevertheless, I’m on pace for eighteen movies over the seven days I can attend, with two every evening during the week and four each on Saturday and Sunday. Below, you can find a brief summary of the films that I saw on the first three days.

Day 1 — Thursday, October 22

Serious Moonlight — Meg Ryan plays a self-assured lawyer who doesn’t take it well when her husband (Timothy Hutton) tells her he’s leaving her for a younger woman (Kristin Bell). She ties him up and threatens to hold him hostage until he sees the error of his ways. I was pleasantly surprised by the depth and humor of the movie and the not-quite-predictable manner in which it arrives at its resolution. I give it an 8/10.
This movie was written by Adrienne Shelly around the same time that she wrote Waitress. It was directed by Cheryl Hines, who was in attendance to introduce the movie and do a Q&A afterwards.

Youth in Revolt — Michael Cera plays a bright but awkward 16-year-old who falls for a girl who likes him as well. However, fate seems to have it out for them and keeps putting up roadblocks in their relationship. Michael develops a “bad boy” alter ego who wreaks quite a bit of havoc and gets into more trouble than he bargained for.
I thought that the trailer for this movie was pretty funny, but didn’t hold out a lot of hope that the movie would be able to match it. Fortunately, I was wrong and it was able to hang onto its humor for the duration. It doesn’t have the hilarity of Zombieland or Superbad, but it’s worth seeing when it comes out early next year. 7/10.

Day 2 — Friday, October 23

31 Minutes — This is a very unique movie, based on a Chilean TV show of the same name. It features a team of puppets that work together produce a parody news show. The producer is a rare type of animal that an evil millionaire needs to finish her collection in an island zoo, so she arranges to have him kidnapped and taken to the island. When the rest of the crew find out, they set off on a rescue mission.
The story itself was fine, but the real draw for this movie is the comedy. It was extremely funny. It was in Spanish with English subtitles, but they were very well done (no obvious spelling or grammatical errors, and they generally captured the meaning and not a literal word-for-word translation) and didn’t detract from the experience. On top of that, the film print of the movie didn’t arrive in time for the showing, so they had to show the DVD they provided for screening the movie, and it featured a pretty prominent watermark in the middle of the picture, but it got pretty easy to ignore that. The experience could have been a little bit better, but the movie itself was excellent. 8/10.

Calvin Marshall — Alex Frost plays Calvin Marshall, a junior college student who loves baseball and wants to go pro but he’s having a hard time making the college team. No one works harder than he does, and the coach (who used to be a minor league player himself, played by Steve Zahn) appreciates the effort and really doesn’t want to cut him. Calvin is also a sportscaster for the school’s TV station and is an announcer for sports events, like women’s volleyball. It is there that he meets and instantly falls for Tori Jensen (played by Michelle Lombardo). Over the course of the movie, Calvin tries to play the game he loves and woo the girl he likes. Andrew Wilson, Diedrich Bader, and Abraham Benrubi also played supporting roles. Like most baseball movies, there was a lot going on besides just baseball, but it came together well to create a very enjoyable movie. 8/10.
This was the movie’s world premiere, and several of the cast and crew were present. This included the director (Gary Lundgren), actors Diedrich Bader and Michelle Lombardo (among others), producers, and other crew. The director introduced the film, and several of them answered questions afterwards.

Day 3 — Saturday, October 24

Missy and the Maxinator — From the description, this sounded like it could be a fun movie. Max is a geeky high school kid who wants to upgrade his current “best friends” status with Missy, the girl next door, to something more. However, he finds that something unusual is happening, and he’s starting to acquire super powers like super strength and hearing and the ability to see through walls. That’s extremely lucky for the rest of us, because two of his teachers are working on a plot to go back in time and change the outcome of World War II so they could take over the world.
I wasn’t expecting a masterpiece, but was hoping for something fun. I was pretty disappointed all the way around. The digital video was shot at worse than DVD resolution and was very grainy, and there were several breaks in the soundtrack where the sound would end too early before a scene change. The acting was horrible (even more so from the adults than the kids), and there were lots of mistakes and continuity errors. But the biggest problem was the weak story, which was weak and not well thought out. Unfortunately, it didn’t make it into the “so bad it’s good” category (I’m not sure if it went too far or not far enough), so I’ll give it a 3/10 rating. I can see how it might have some appeal to the preteen crowd (which is fitting, since the director, who was in attendance, works for Nickelodeon), but I can usually get at least some enjoyment out of those kinds of movies, and in this case there was too much that I couldn’t overlook to get to that point.

Straight to the Bone — This is a very Austin-centric movie about a woman (Shannon) in a long relationship with a guy (Jay) who doesn’t want to get married. When she’s dealing with dealing with a particular bout of frustration from that, she has a couple of chance encounters with another guy (Blake) and they hit it off. When Jay decides that he needs to get away for a couple of days, Shannon finds herself on a date with Blake.
In general, I thought that this was a pretty good movie. It had a good basic story, and was pretty well acted. There were some video problems with a lot of digital artifacting around cuts, but I think that the film festival itself is to blame for that, since this is the first year they’re going digital and there are some bugs to be worked out in the conversion process as I saw similar problems (although not to the same extent) in a couple of other movies. I do think that it captured a bit too much of the Austin hippie culture, and it was a little too slowly-paced (which probably comes from the fact that the cast and crew wrote the movie as they went along over more than a year of filming when they could get everyone together), but I think that both of those are things that could be improved with a bit of editing. I give it a 6/10.

Hockey Night in Texas — This is a documentary that follows a few teams over a season of an amateur adult hockey league in Austin. I really don’t like hockey, and you couldn’t drag me to see a game or even watch one on TV, and the only reason that I decided to see it was that it happened to be sandwiched between two other movies that I wanted to see and I decided that it wasn’t worth going home for an hour and a half. I’m glad that I stayed because I loved this movie. It was very funny, and very fast-paced, complete with 50’s-style how-to clips interspersed ala Dodge Ball. The guys (and at least one woman) are pretty bad and at least most of them acknowledge and embrace that to have a really good time, and that translates well to the screen. I still have no desire to watch hockey, but I would watch this again. 8/10.
The director was there to introduce it and do a Q&A, and he said that there were hundreds of hours of footage that had been shot, but that didn’t show at all in the 83 minutes that actually made it in. A large percentage of the audience was comprised of players from the league, which helped to further enhance the experience.

Lo — Lo is the story of a guy who summons a demon to help him get a girl who he had fallen in love with but had herself been kidnapped by another demon. It was heavily-inspired by Faust, which is directly acknowledged in the movie. It was billed as being funny, but didn’t really succeed at that. It ultimately felt like we were watching a tape of a musical theater production, and the director said that although he wrote it as a movie they were exploring the possibility of running it as a play. The story was interesting, but the movie was a little too experimental and artistic for my taste. 5/10.

LDAP SDK persistence framework part 2: Supported data types

Another very important aspect of the persistence framework being developed for the UnboundID LDAP SDK for Java is the set of data types that it supports. In order to be able to correctly store and retrieve Java objects in a directory server, the LDAP SDK has to now how to encode Java values to LDAP attributes, and then decode the values of those attributes back to their Java representations. The LDAP SDK provides an abstract LDAPFieldEncoder class which defines the API needed to achieve this, as well as other things like generating LDAP attribute type definitions for a particular field or method. The @LDAPField, @LDAPFieldGetter, and @LDAPFieldSetter annotation types all include elements that allow you to specify the type of encoder that should be used when interacting with the associated field or method.

If the encoderClass element isn’t provided in the annotation, then the LDAP SDK will use an instance of the DefaultLDAPFieldEncoder class. This class supports a pretty broad range of data types, including:

  • boolean primitives
  • double primitives
  • float primitives
  • int primitives
  • long primitives
  • short primitives
  • byte[] objects
  • char[] objects
  • java.lang.Boolean objects
  • java.lang.Double objects
  • java.lang.Float objects
  • java.lang.Integer objects
  • java.lang.Long objects
  • java.lang.Short objects
  • java.lang.String objects
  • java.lang.StringBuffer objects
  • java.lang.StringBuilder objects
  • java.math.BigDecimal objects
  • java.math.BigInteger objects
  • java.util.Date objects
  • java.util.UUID objects
  • java.util.concurrent.atomic.AtomicInteger objects
  • java.util.concurrent.atomic.AtomicLong objects
  • com.unboundid.ldap.sdk.DN objects
  • com.unboundid.ldap.sdk.Filter objects
  • com.unboundid.ldap.sdk.LDAPURL objects
  • com.unboundid.ldap.sdk.RDN objects

In addition, it also supports arrays of all of the above types for dealing with multi-valued attributes. In the future, I intend to add add support for using java.util.Lists and java.util.Sets for all of the above types as well, but that’s not in the current implementation, and generics make that a bit tricky.

For most of the above data types, the value stored in the directory server is simply the string representation of the associated primitive or object. However, there are a few special cases:

  • boolean primitives and java.lang.Boolean objects are always stored using values of “TRUE” or “FALSE” (in all uppercase), as per the LDAP Boolean syntax.
  • byte[] objects are used to represent the raw bytes that comprise the attribute value
  • char[] objects are used to represent the raw characters that comprise the attribute value
  • java.util.Date objects are encoded using the LDAP generalized time syntax

Even though the default field encoder supports a number of primitive types (although it doesn’t support either byte or char in order to avoid confusion), I would generally recommend that you use the corresponding objects in the java.lang package instead. The reason for this is that primitives can’t have a null value, so it’s not possible to distinguish between cases in which there is no value and cases where there is a value that happens to be the same as the default value for that primitive (zero for numeric types and false for boolean). If you use the corresponding object types instead, then they can have null values, and you can use that to determine if a value has been assigned.

If you need to store some other kind of object in the directory that isn’t in this list, then you’ll need to create your own subclass of LDAPFieldEncoder with the appropriate logic for encoding and decoding values. If this is necessary, then I’d strongly recommend using DefaultLDAPFieldEncoder as a starting point.

LDAP SDK persistence framework part 1: Annotations

As I mentioned in my LDAPCon presentation, I’ve been working recently on updating the UnboundID LDAP SDK for Java to provide a framework that makes it easy to store and retrieve Java objects in an LDAP directory server. The majority of this framework is complete and has been committed into the SourceForge repository (although it’s currently in the branches/persist directory rather than in the trunk), so you can check it out and build it for yourself if you’d like to give it a shot. It provides support for add, delete, modify, get, and search operations, as well as for encoding and decoding LDAP entries to and from Java objects, and for validating the set of annotations contained in an object. The primary components that have not yet been implemented are the tools for generating LDAP schema from a properly-annotated Java object, or for generating a Java source file from LDAP schema, but that will hopefully be added in the near future.

At the heart of the persistence framework is a set of annotations that can be used to mark your source code with information about how the object should be represented in an LDAP directory server. In this post, I’ll describe those annotations and how they can be used.

The LDAPObject Annotation

The @LDAPObject annotation is used to mark the class for an object that is to be stored in an LDAP directory server. The class must include a constructor that takes zero arguments, although it may have any or no access modifier. This annotation may include the following elements:

  • structuralClass — The name of the LDAP structural object class to use for entries created from objects of this type. If this is not provided, then it will be assumed that the name of the LDAP structural object class is the same as the unqualified Java class name.
  • auxiliaryClass — The name(s) of any LDAP auxiliary object classes to use for entries created from objects of this type. If this is not provided, then no auxiliary object classes will be included in generated entries.
  • defaultParentDN — The DN of the entry below which objects of this type are typically located in the directory. This is optional, and even if it is provided, you can override this value on a per-operation basis.
  • postDecodeMethod — The name of a method in the associated Java class that should be invoked after all other processing has been performed when decoding an LDAP entry to a Java object. If this is provided, then the specified method must exist in the entry and must not take any arguments. That method can be used to perform any additional processing not directly provided by the LDAP SDK persistence framework, or to perform custom validation of the resulting object (optionally throwing an exception if a problem is found).
  • postEncodeMethod — The name of a method in the associated Java class that should be invoked after all other processing has been performed to encode the object to an LDAP entry. If this is provided, then the specified method must exist in the entry and must take exactly one argument with a type of com.unboundid.ldap.sdk.Entry. This method can be used to alter the resulting entry, or to perform further validation of that entry (optionally throwing an exception if a problem is found).

The LDAPField Annotation

The @LDAPField annotation is used to mark fields in a class containing the @LDAPObject annotation. Each field marked with this annotation will be associated with a different attribute in an LDAP entry. The field may be marked with any or no access modifier (i.e., it can be public, private, protected, or have package-level access), and must not be declared either static or final. Any fields included in the class which are not marked with the @LDAPField annotation will not be used when encoding or decoding objects.

This annotation may include the following elements:

  • attribute — The name of the LDAP attribute used to hold the value(s) for this field. If this is not provided, then it will be assumed that the name of the LDAP attribute is the same as the name of the Java field.
  • objectClass — The name(s) of the object class(es) in which this attribute is referenced. This will primarily be used in the process of generating LDAP schema that may be used to store the associated type of object. If this is not provided, then it will be assumed that the attribute is included in the structural object class for the object. Only object classes named as structural or auxiliary classes in the @LDAPObject annotation may be specified.
  • inRDN — Indicates whether this field should be included in the RDN for entries created from the object. If this is not provided, then it will be assigned a default value of false. At least one field or getter method in the class must be marked for inclusion in the entry RDN.
  • inAdd — Indicates whether this field should be included in the entry created from the object as part of an LDAP add operation. If this is not provided, then it will be assigned a default value of true. Note that if inRDN is true, then the field will always be included in add operations regardless of the value of the inAdd element.
  • inModify — Indicates whether this field should be included in the set of modifications when performing an LDAP modify operation for the object. If this is not provided, then it will be assigned a default value of true. Note that if inRDN is true, then the field will never be included in the modify operations regardless of the value of the inModify element.
  • inFilter — Indicates whether this field may be included in the filter that is generated when trying to search for objects matching the provided object. If this is not provided, then it will be assigned a default value of false.
  • encoderClass — The fully-qualified name of the Java class that provides the logic for encoding and decoding the value(s) of the field to and from an LDAP attribute. If this is not provided, then a default of com.unboundid.ldap.sdk.persist.DefaultLDAPFieldEncoder will be used (more information about this class and the field encoder API will be provided in an upcoming post).
  • defaultDecodeValue — A default value (or set of values) that will be assigned to the field when decoding an LDAP entry to a Java object if the entry does not contain the associated attribute. If this is not provided, then the field will be assigned a value of null (or a default value for primitives) if the attribute is missing from the entry being decoded.
  • defaultEncodeValue — A default value (or set of values) that will be used for the attribute generated from the associated field if it has a null value. If this is not provided, then no attribute will be included in the generated entry if the field has a null value.
  • requiredForDecode — Indicates whether the process of decoding an LDAP entry to a Java object should fail if the associated attribute is not included in the entry and no default decode values are defined. If this is not provided, then it will be assigned a default value of false.
  • requiredForEncode — Indicates whether the process of encoding the field to an LDAP attribute should fail if the field has a null value and no default encode values are defined. If this is not provided, then it will be assigned a default value of false.
  • failOnInvalidValue — Indicates whether the process of decoding an LDAP entry to a Java object should fail if the associated attribute contains a value that cannot be assigned to the field (e.g., because the value cannot be parsed in a way compatible with the type of the Java field). If this is not provided, then it will be assigned a default value of true.
  • failOnTooManyValues — Indicates whether the process of decoding an LDAP entry to a Java object should fail if the associated attribute has multiple values when only a single value can be assigned to the Java field. If this is not provided, then it will be assigned a default value of true.

The LDAPFieldGetter Annotation

The @LDAPFieldGetter annotation may be used to mark a method which may be used to generate an attribute to include in entries or modifications generated from the object. It can be used for cases in which a value should only be used when encoding and not decoding, or if custom processing is needed to prepare the value for storing in the directory. Any methods marked with this annotation must not take any arguments, and must not be declared static. They can have any or no access modifier, including public, private, or protected.

This annotation may include the following elements:

  • attribute — The name of the LDAP attribute in which the value(s) returned from the method should be stored. This is a required element.
  • objectClass — The name(s) of the LDAP object class(es) in which this attribute is referenced. It has the same use as the objectClass element of the @LDAPField annotation.
  • inRDN — Indicates whether the value returned from this method should be included in the RDN for entries created from the object. If this is not provided, then it will be assigned a default value of false. At least one field or getter method in the class must be marked for inclusion in the entry RDN.
  • inAdd — Indicates whether the value(s) of this method should be included in the entry created from the object as part of an LDAP add operation. It has the same behavior as the inAdd element of the @LDAPField annotation.
  • inModify — Indicates whether the value(s) of this method should be included in the set of modifications when performing an LDAP modify operation for the object. It has the same behavior as the inModify element of the @LDAPField annotation.
  • inFilter — Indicates whether this field may be included in the filter that is generated when trying to search for objects matching the provided object. It has the same behavior as the inFilter element of the @LDAPField annotation.
  • encoderClass — The fully-qualified name of the Java class that provides the logic for encoding the method value(s) to an LDAP attribute. It has the same behavior as the encoderClass element of the @LDAPField annotation.

The LDAPFieldSetter Annotation

The @LDAPFieldSetter annotation may be used to mark a method that can be used to update a Java object based with information from an attribute in an LDAP entry. It can be used for cases in which an attribute should be read from but not written to an entry, or for cases in which custom processing is required to update the object from an attribute. Any methods marked with this annotation must take exactly one argument and must not be declared static. The methods can have any or no access modifier.

This annotation may include the following elements:

  • attribute — The name of the LDAP attribute that should be used to provide the argument used when invoking the method. This is a required element.
  • encoderClass — The fully-qualified name of the Java class that provides the logic for decoding the attribute value(s) to the argument used to invoke the method. It has the same behavior as the encoderClass element of the @LDAPField annotation.
  • failOnInvalidValue — Indicates whether the process of decoding an LDAP entry to a Java object should fail if the associated attribute contains a value that cannot be converted to the argument used to invoke the method. It has the same behavior as the failOnInvalidValue element of the @LDAPField annotation.
  • failOnTooManyValues — Indicates whether the process of decoding an LDAP entry to a Java object should fail if the associated attribute has multiple values when only a single value can be held in the argument used to invoke the method. It has the same behavior as the failOnTooManyValues element of the @LDAPField annotation.

The LDAPDNField Annotation

The @LDAPDNField annotation may be used to mark at most one field in the class which will be assigned the DN of the entry with which the object is associated. If a field with this annotation is included in the object, then it must have a type of java.lang.String, and it must not be declared static or final. It may have any or no access modifier. This annotation must not be used to mark a field that is also marked with the @LDAPField annotation.

If a field with this annotation is present in the object, then it will be assigned in the course of initializing the object with information from an LDAP entry, or in the course of generating an LDAP entry from the object contents. If set, the value of this field may be used to obtain the appropriate entry DN for add, delete, or modify operations.

Neither the @LDAPDNField nor the @LDAPEntryField annotations are required to be used in an object marked with the @LDAPObject annotation, but it is strongly recommended that at least one of them be included so that the correct entry DN will be available for LDAP operations involving the object.

The LDAPEntryField Annotation

The @LDAPEntryField annotation may be used to mark at most one field in the class which will be assigned a read-only copy of the entry with which the object is associated. If a field with this annotation is included in the object, then it must have a type of com.unboundid.ldap.sdk.ReadOnlyEntry, and it must not be declared static or final. It may have any or no access modifier. This annotation must not be used to mark a field that is also marked with the @LDAPField annotation.

If a field with this annotation is present in the object, then it will be assigned in the course of initializing the object with information from an LDAP entry, or in the course of generating an LDAP entry from the object contents. If set, the value of this field may be used to obtain the appropriate entry DN for add, delete, or modify operations. It may also be used to refine the set of modifications generated from an object for inclusion in a modify operation, so that modifications do not include changes to attributes that have not changed since the object was retrieved.

As mentioned above, although neither is required, it is strongly recommended that either or both the @LDAPDNField or @LDAPEntryField annotations should be included in objects to be persisted in the directory.

LDAPCon recorded presentation posted

I have now updated the UnboundID website to include a recorded version of the presentation that I gave at LDAPCon. The total presentation is right at 45 minutes, but I’ve broken it up into a few pieces so that you don’t have to try to digest it all at once.

You can find the recorded presentation, as well as a copy of the slides, at http://www.unboundid.com/products/ldapsdk/LDAPCon-2009-presentation/index.php.

LDAPCon slides posted

The LDAP SDK presentation that I gave Monday at LDAPCon went pretty smoothly and seemed to be pretty well-received. When I got home yesterday afternoon, I recorded a version of the presentation and we’ll hopefully be making that available online in the near future. However, a version of the slides that I used for the presentation is now available online at http://www.symas.com/ldapcon2009/papers/ely1.shtml.

Slides and/or papers for some of the other presentations are also available online. You can see them at http://www.symas.com/ldapcon2009/papers.shtml.

LDAP SDK now in Maven Central Repository

Just in time for my talk at LDAPCon on Monday, it looks like the UnboundID LDAP SDK for Java is now available in the Maven Central Repository.

You can get it with the following information

  • groupId — com.unboundid
  • artifactId — unboundid-ldapsdk
  • version — 1.1.0

The link to the POM file for this release is at http://repo1.maven.org/maven2/com/unboundid/unboundid-ldapsdk/1.1.0/unboundid-ldapsdk-1.1.0.pom.