Archive for the ‘programming’ Category

More about motivation

Tuesday, April 15th, 2008

I find myself writing about programmer motivation a lot. I think it’s because my career is at somewhat of a crossroads. I just got done reading a wonderful post at foundread.com by Carleen Hawn about motivation, and it was great to reflect on how it related to my situation.

At my previous job, I was rockstar superman-go-to-guy for the wireless billing system that I was working on. I know that this sounds arrogant and boastful as hell. Admittedly, I was a bit of a programmer prima donna. But when it came to knowledge of the inner-workings of our particular product, it at least felt like I was the man. Part of that was not only understanding the software, but understanding the business as well.

When that gig started to dry up, it became time to find new work, and I found myself at a local financial services company. In doing so, I fell from my position of glory to “just another programmer.” I was promised that I would someday get to the more prestigious position of architect again. But that takes time – a lot of it. Grokking the system that the guys here have spent years working has been more difficult than I thought it would be. Understanding the business that we’re in is just as difficult, and it’s clear to me that understanding the business is what’s important to ascend the ranks to an architects’ role.

At my “new” job (I’ve been here for months, it’s hardly new anymore), I struggle sometimes with motivating myself. After reading the aforementioned “The Motif of Employee Motivations,” I think I understand why. The role I crave is to be the guy that understands the business, and how the entire system meets that need. I like being the guy who gets asked questions by the business analysts and the other engineers. At my current job, I haven’t yet achieved that. Being an impatient person by nature, it’s frustrating to see how far away the day will be that I attain that role. And I’m not sure how to get there from here.

The thing that I find the most insightful is that this motivates me beyond just my career – it motivates me to blog, and it motivates me to work on my “side projects.” I think it’s also what makes me dream of being an entrepreneur.

But actually knowing what motivates me now helps a lot. Perhaps now I’m on my way to getting there.

Photo credit: Paal Leveraas

Anatomy of a Project Failure: Corporate Culture and Lessons Learned

Tuesday, March 25th, 2008

When a big new project lands in a company’s lap, the instincts of upper management, while well intentioned, are usually to go with people and paradigms that have worked in the past.
The culture of my former employer was forced to change suddenly to support new business, and it ultimately resulted in failure. I’ve had several months now to think about what happened. In retrospect, a lot of it could have been avoided if the company’s leaders had ignored their instincts, and been daring enough to rely more on different people with the right expertise.

This is more long-winded than most of my posts, so those with short attention spans should probably turn back now!

Background
I started working for a small company (fewer than 20 employees) in 2000 that provided billing services to small, rural wireless carriers in the United States. That company eventually grew to about sixty employees and was acquired by another medium-sized company about three years later. The new company provided other services to wireless companies, but lacked a post-paid billing platform. It seemed like a perfect fit. The smaller billing company would become a satellite office for the corporate mothership.

A Corporate Culture Shift
In the past, the team working on the billing system had been allowed a lot of latitude to work independently from the corporate mothership. However, this was a high-profile project with a large national carrier, so the company decided to bring in a lot of its leadership’s “big guns,” who had experience with large carriers. Unfortunately, they had little or no experience in the business domain, namely post-paid wireless billing.

Unlike the small team that had managed the product in the past, the new folks had little sense of what the carrier’s priorities should be. This new team included client relations representatives, many of the project managers, and even a majority of the technical team. The people who had dutifully supported the small billing program for so many years would continue to work in “maintenance mode” on the existing platform for the existing rural clients. The implication was clear – they’d been relegated to the “less important” clients.

The User Interface
The billing system had a user interface which allowed representatives at the customer call centers to change things for the subscriber in real time – things like rate plans, billing addresses, automatic payment, allowed managers to configure their own rate plans and user privileges and roles, and it even had an integrated Point-of-Sale system.

The system was “good enough,” but barely. Unfortunately, it was written using a poorly supported, obscure 4/GL whose scalability was in doubt. Deploying it at carrier sites also created some sketchy security issues. We had been meaning to re-write it for a long time, but didn’t have the resources to do so. It wasn’t going to be good enough for our new client.

Offshoring to the Rescue
At about that time, the parent company acquired another company in India that processed payments for wireless carriers. Suddenly we had nearly limitless programming resources at our disposal. All we’d need to do is mock up some new screens, write a few specs, and send the work to our new development staff. We’d “keep a close eye” on their progress, strip the functionality down to the bare necessities, and we’d have a re-vamped UI in a matter of months. As an added bonus, the new programmers already knew Java, so we wouldn’t need to re-train any of the existing workforce to get started.

The first thing the new leadership did was to consult with a UI expert to do the mockups – one that (of course) had no experience with the product or with wireless carriers. She was mentored by a product manager who had very little experience with post-paid billing.

Fortunately for me, I got to work on a SOAP-based API for the product to integrate with the other elements of the back-end. I saw the train wreck coming with the UI project, and I managed to avoid it. I worked quite independently with another contractor based near the corporate mothership.

Reviewing the Mockup
The first thing we did was review the new UI mockups. The new leadership had the right idea, and decided that it might be a good to include some people familiar with the “legacy” system in the review. The legacy team was horrified. The new application looked completely dysfunctional. Naturally, the “new team” got defensive and insisted that the crufty old-timers were thinking too much in the past, that this was the future. Their comments fell on deaf ears. They weren’t invited to participate any more.

Developing the UI
So here’s how development worked: The company hired some brand-new Java superstar contractors to work in their corporate office to “oversee” the development effort. The contractors were great Java programmers, but they had literally zero business domain knowledge. Every morning, they would get onto a conference call with India to review the previous night’s work and discuss the next day’s priorities.

Nobody on the project knew if they were doing it right. There was no connection between the back-end and the wireframes. They started consulting me with business-related questions, and I helped out where I could, but that ended up being like the game of telephone that you play in grade school – things are lost when they are translated three times over, and communicated over a garbled conference call and IM. The rest of the legacy team was too busy supporting the existing customers to help answer questions.

So domain knowledge continued to drip very slowly from wherever it could, over to the mothership, and finally to India. Too slowly. They began to sit idly on a UI that, because it followed the mockups religiously, was fairly unusable.

Eventually, the developers on the other side of the ocean started to get fed up, and were leaving the company. I couldn’t blame them, and the fact that there are so many jobs available in that market made it easy for them to leave. What little domain knowledge had been built up was constantly fading away. They began hiring furiously, which compounded the problem further.

I heard complaints from the superstar contractors that the quality of the work was a bit sketchy. I imagine that the quality of the work must have worsened as the rate of turnover increased. We started bringing on extra contractors stateside to help out. Have you ever read Brooks’ The Mythical Man Month? Yeah, he knew what he was talking about. Adding developers to a late project makes it later.

One night I was visiting the mothership, as I had to do almost weekly to keep up with the latest news on the project (it was about an hour-long drive from our satellite office). We were weeks away from the launch date. The lead UI developer called me into his cubicle and asked if I could spare a few minutes. We started reviewing the UI, and he began asking me how to wire up the pages with the back-end. We looked at page after page and I told him “you can’t do that – it doesn’t make sense,” or “we have no feature like that, I don’t know what it is supposed to mean.”

We were supposed to use my SOAP API to do the business logic, but they had laid none of the groundwork for it. The programmers were pretty good at calling stored procedures. So, on page after page, I told him I’d write a stored procedure to do the work. Add a rate plan? I’ll throw together a procedure. View the customer detail? Yup, that too. We started eliminating unnecessary pages, buttons, and fields left and right.

The next day I started hacking frantically on a raft of stored procedures that did most of the back-end logic for the UI, and I did a pretty mediocre job. I was in a hurried marathon session, and I like to believe that I did the best that I could given the circumstances, but at that point it was definitely all about volume, not quality. Work on the API was pretty much halted, but it was nearly finished anyways. Soon it was time to start training the call center.

Was the Customer Happy?
Fortunately, the client had problems of their own with ramping up. Their operations people were initially satisfied with the product because they had very little experience in the business domain, either. But it didn’t last.

As time went on, and more experienced management was hired by the carrier, they became incredulous that the UI couldn’t perform the simplest of tasks that competitor’s systems could. They were frustrated that it was so buggy. However, the crappy Customer Care UI ended up being the least of the carrier’s problems – that story is for another day. Eventually, both companies more-or-less crashed and burned, which is why I hope it’s safe to share this story with you now.

Takeaways and Lessons that I Learned
So, here are the things that I can impart based on what happened to this project:

  • Domain Knowledge is king. Programmers are a tenacious bunch, and we can learn technology fairly well. Years of insight from business relationships can’t be learned overnight. The mothership had the roles reversed – the big guns with experience with big carriers should have been mentoring the employees with the domain knowledge, instead of the other way around.
  • Working with people half a world away is hard. I don’t think that it had anything to do with the fact that the offshore programmers were in India. I think it would have been just as difficult if they had been Canadian or Australian or any other English-speaking country. India has plenty of talented programmers. But sharing domain knowledge becomes even harder over conference calls, Skype, and IM. When developing an application in a short timespan, you need to be able to holler questions over the cubicle wall, or grab a whiteboard on a moment’s notice, which isn’t an option when offshoring. I’m sure the Indian team was just as frustrated as we were. I know that there are companies out there who have been successful at this, but it’s difficult to pull off, and our company didn’t manage to do it. There are probably tools out there to make this easier – do you know of any that you can recommend?
  • The User Interface is the Face of the Application. Your UI probably needs the most attention, and probably gets the least. Your client’s perception of the quality of your product and engineering is largely based on what they see. Our billing back-end was quite sophisticated and managed to scale well enough, but the client didn’t see that. They saw the crummy exception messages and the things that they couldn’t do from the interface. You can often fake the back-end for a while by throwing more people and process at fixing problems – you can’t easily fake quality in your UI. To the client, our whole product was crap because the quality of the UI was poor, and this should be obvious to everyone. Have you ever worked with a pathetic UI, and concluded that the company did a shoddy job of engineering?

Phew! What a long post. Thanks for sticking it out and reading the whole thing. I’d be interested in hearing if anyone else has gone through a similar situation, and their company found ways to overcome the knowledge gap. Have you been in an acquisition where your formerly tightknit team had to integrate and ramp up within a new corporate culture? How’d you get through it?

Five Keys to Corporate Programmer Happiness

Wednesday, March 19th, 2008

I’ve worked as a programmer and as a manager of programmers for about twelve years now. Many people believe that the key to productivity is content employees, and I tend to agree with that too. Here are some low-cost ideas for things which either make me happier, or make the programmers on my team happier.

1.) Allow time for side-projects related to the business. I think this item is critically important! Any programmer worth his or her salt will look at the way that things are done, and think of ways that it could be done better. The problem is that we’re usually so immersed in core business needs that we don’t have an opportunity to improve the systems that are already in place. These improvements might be a new development tool, refactoring an existing code base, evaluating a new library or language, or adding a nifty feature to an existing product. I’ve seen lots of great things come out of this “play time,” and as a manager I tried (with limited success) to set aside specific time on Friday afternoons for these pursuits. In the end, the product gets better in unexpected ways, and the programmers have fun, so everybody wins!

2.) Start a Peer Recognition Program. This one will seem a little silly to people at first, and it will undoubtedly be a source of endless office jokes. But a lot of people do respond to peer recognition; setup an internal website where employees can recognize their colleagues for a job well done. And it’s even better to sweeten the pot by giving out small prizes, like gift certificates, to participants chosen at random. Programmers don’t get (or give) a lot of kudos from (or to) each other, and this helps grease the wheels.

3.) Send Programmers to Training or Trade Shows.
It’s especially nice if you can afford to send programmers on a junket somewhere for their training. It doesn’t need to be glamorous! Take someone who lives in New England; A week in Pittsburgh, away from the grind of the daily work cycle, in a new place, going out to eat on the company dime and meeting other similarly-minded folks, can be a blast, and (best of all) can re-energize the creative drive. If you can’t afford to send the developers on trips, then a day or two off at a local course is great, too. Make sure the training is for something that a developer might be interested in – new and interesting stuff is good, COBOL optimization techniques maybe not so much.

4.) Socialize.
Believe it or not, not every programmer is a daylight-hating, mumbling, uncomfortable Asperger’s poster-child. Go out some night after work for a few beers. It’s also good to bring some non-programmers from the business along. Day in and day out, we tend to become e-mail addresses or IM nicks to each other. We forget that we’re all human beings suffering in the same cubicle hell until we can get home and get on with our real lives. Getting together outside the office, for fun, reminds us who we actually are. If you and Alice-from-Accounting talk about the aging Tim Wakefield’s potential (or lack thereof) as a Red Sox pitcher for another season over a beer, then dealing with her I.T. problem the next day will seem like less of a chore, and more like helping out a friend.

5.) Cut down on the paperwork
. In a SAS70/ISO/SarBox world, a certain amount of due process is unavoidable. The larger a company (and its coffers) get, the more signatures and sign-offs are needed to do anything. Try to set up your organization so that programmers can focus on programming. Programmers are excited by problem solving, and making things more efficient. We like faster, smaller, better; that’s what we do, it’s what we’re good at. Paperwork and process are the antithesis of those things. I’m not saying that you shouldn’t design software carefully and deliberately, but if you’re spending more time in conference calls reviewing documentation than writing code, you’re probably not a happy programmer.

I’m sure there are things that I’ve missed, and I’m sure this list doesn’t apply to everyone, but these are the things that have worked for me and a lot of the people I’ve worked with. Hope it helps!

Enumerated Types with JPA, and your Sock Drawer

Monday, February 18th, 2008

One feature of JPA that didn’t exist in plain-vanilla Hibernate is support for Enumerated types. I haven’t seen a lot of examples of this in practice or on the internet, so in this post I’ll show one example of how to use JDK 5 enumerations with JPA.

For our example, we are going to create an inventory system for our sock drawer. It is comprised of only two tables. The first table, called SOCK, contains one row per sock in our drawer. The columns of the table are:

  • sock_id – an auto-incrementing identity column.
  • sock_description – a varchar column for a free-form text description of the sock.
  • sock_pattern_id – a reference to a row in the SOCK_PATTERN table.

As you may have guessed, the SOCK_PATTERN table looks like this:

  • sock_pattern_id – an integer primary key. It’s not auto-incrementing, because we will want to have control over the contents of the field.
  • sock_pattern_description – a varchar column for a free-form text description of the pattern.

We need to “prime” our SOCK_PATTERN table with the valid patterns and create a foreign key relationship between the two tables:

INSERT INTO SOCK_PATTERN (sock_pattern_id,sock_pattern_description) VALUES (0,'SOLID');
INSERT INTO SOCK_PATTERN (sock_pattern_id,sock_pattern_description) VALUES (1,'STRIPES');
INSERT INTO SOCK_PATTERN (sock_pattern_id,sock_pattern_description) VALUES (2,'POLKA_DOT');
INSERT INTO SOCK_PATTERN (sock_pattern_id,sock_pattern_description) VALUES (3,'ARGYLE');

Note that we populated sock_pattern_id starting with zero; this is important because the Enumeration below is zero-indexed.

Next, let’s create the classes:

public enum SockPattern {
 SOLID, STRIPES, POLKA_DOT, ARGYLE
}
 
@Entity @Table(name="SOCK")
public class Sock {
 @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
 @Column(name="sock_id")
 private Integer id;
 
 @Column(name="sock_description")
 private String description;
 
 @Enumerated @Column(name="sock_pattern_id")
 private SockPattern pattern;
 
 public Integer getId() { return id; }
 public void setId(Integer id) { this.id = id; }
 
 public String getDescription() { return description; }
 public void setDescription(String description) { this.description = description; }
 
 public SockPattern getPattern() { return pattern; }
 public void setPattern(SockPattern pattern) { this.pattern = pattern; }
}

Now, to use our wonderful contraption, you’d do something like the following:

public class Demo {
 private static EntityManagerFactory emf;
 static {
     Demo.emf = Persistence.createEntityManagerFactory("sockdrawer");
 }
 
 @Test
 public void socksOne() {
     Sock sock = new Sock();
     sock.setDescription("My favorite sock.");
     sock.setPattern(SockPattern.ARGYLE);
     EntityManager em = Demo.emf.createEntityManager();
     em.getTransaction().begin();
     em.persist(sock);
     em.getTransaction().commit();
     em.close();
 }
}

There are some obvious pitfalls to this approach. The object/relational mapping is very brittle; for this code to work, the IDs in the database always need to match the values that the ORM tool gets from the enumeration. Changing these values at a later date could cause some surprising results, and you can’t insert new rows without updating the Enumeration and recompiling. It does obviate the need to map the SOCK_PATTERN table, and you won’t need to worry about the details of cascading the persistent state of related Sock and SockPattern objects.

It’s just a new tool in the JPA toolbox.

(The code in this blog post was tested w/ Postgres and Toplink)

A Delicious and Simple JPA Mapping tutorial: The Pizza Shop

Thursday, January 31st, 2008

So, another JPA tutorial. What makes this one different? Well, for one thing, this one comes with a working, downloadable project that works with Eclipse, NetBeans, and IntelliJ IDEA 7. It’s packaged with Hibernate, Toplink, and OpenJPA. And it’s been tested with MySQL, PostgreSQL, MS SQL Server, and Sybase. In other words, it works with 36 different IDE/JPA Provider/Database combinations!

Another thing that makes this tutorial different is the subject matter: Pizza! Who doesn’t love pizza? Except lactose intolerant people. And people who can’t eat gluten. But other than them, who doesn’t love pizza? So we’re going to create a simple database model for a pizza shop’s point-of-sale system.

The Schema
Unsurprisingly, the starting point for any ORM task is usually the database schema (there are people who start with the Objects and work “backward” to the schema, but I haven’t worked with any of them yet). In our example, we have a pristine, consistent, completely normalized schema. In other words, it’s probably nothing like you’ll ever be lucky enough to see in the real world! Here’s our simple little ERD:From this ERD, we can infer the following: 1.) An order is comprised of zero or more pizzas. 2.) A pizza is associated with one size. 3.) A pizza may be associated with a string of text containing “special instructions.” 4.) A pizza may have zero or more toppings. You probably also notice that each table has a column called version. This will be used for an optimistic locking strategy.

The first question is, “Where should we start?” There’s no right answer for this, but I find that it’s easiest to start working with the entities with the fewest dependencies. For example, you can’t have an order without a pizza, and you can’t have a pizza without a size, so maybe it makes sense to start with the size. But before that, we’ll want an ID interface.

An ID Interface
First things first. You’ll notice that, in our schema, every table has an integer ID. It’s often a good idea to have all of your objects implement the same interface for accessing the ID, because it makes it easier to create Generic DAOs (more about that in a future post). For now, let’s make a really simple interface like this:

public interface IdObject {
  public void setId(Integer id);
  public Integer getId();
}

Many-to-One Unidirectional Relationships
Now that we’ve gotten that out of the way, let’s create the Size class. It’s a simple POJO littered with annotations, like this:

@Entity
@Table(name="PIZZA_SIZE")
public class Size implements IdObject {
  @Id
  @Column(name="pizza_size_id")
  private Integer id;
 
  @Column(name="pizza_size_description")
  private String description;
 
  @Column(name="pizza_size_base_price")
  private BigDecimal basePrice;
 
  @Version @Column(name="version")
  private Integer version;
 
  public Integer getId() { return id; }
  public void setId(Integer id) { this.id = id; }
 
  public String getDescription() { return description; }
  public void setDescription(String description) { this.description = description; }
 
  public BigDecimal getBasePrice() { return basePrice; }
  public void setBasePrice(BigDecimal basePrice) { this.basePrice = basePrice; }
 
  public Integer getVersion() { return version; }
  public void setVersion(Integer version) { this.version = version; }
}

Here are some notes on the annotations that were used in the above class:
@Entity
tells the JPA provider that this is a managed object.
@Table specifies the table name. The JPA provider will attempt to default the table name to a sane value based on the class name, but I like to be explicit. I’m funny that way. Perhaps it’s OCD. Or a power-trip.
@Column indicates the name of the column, and can include other attributes about the column (you’ll see a few additional attributes later on). Again, JPA can try to default this to sane values for you, but I like to be explicit.
@Version indicates that a particular column is used for indicating when a row is updated. This column can then be used in an optimistic locking scheme.

Next, let’s do the Pizza object to show how we map a Pizza to a Size.
One thing I that always tripped me up when I started out with ORM
tools was the difference between “One-to-Many” and “Many-to-One.” I never knew, if I call a relationship many-to-one in my metadata, is this object the one that there are many of, or is it the other way around? The answer is that “this” object always comes first. ManyToOne means that “there are many of this object to one of those objects.” The “Many” side is often the side that has the foreign key.

In our case, there will be many Pizzas that are the same size. So when we make our Pizza object, we will want to use the @ManyToOne annotation. Here’s what the Pizza object looks like so far. I’ve omitted the getters and setters to save space:

@Entity
@Table(name="PIZZA")
public class Pizza implements IdObject {
  @Id
  @Column(name="pizza_id")
  private Integer id;
 
  @ManyToOne(cascade={CascadeType.ALL})
  @JoinColumn(name="pizza_size_id",nullable=false)
  private Size size;
 
  @Version @Column(name="version")
  private Integer version;
 
  // (Accessor methods omitted)
}

Note that, when we made our Size object, we did not include a reference to the Pizza. That was an intentional design decision. In this application, it’s unlikely that we will want to instantiate a Size object, and get a collection containing all of the Pizzas of that size, so we don’t bother with mapping it. This is called unidirectional association.

The @ManyToOne annotation specifies a cascade attribute. There are several different settings for this attribute, which you can read more about here. I tend to cascade the persistent state to all related objects because it reduces the amount of redundant API calls. By default, JPA does not cascade pers istence to related objects. I’ll cover the cascade attribute in future posts, but for now, we’ll go with my personal preference, because I’m writing the article!

The @JoinColumn annotation indicates the column name that defines the linkage between the Pizza and the Size. You’ll also note that we’ve included some additional attributes on our @Column and @JoinColumn annotations. The unique and nullable attributes are particularly useful if you use tools to generate schema DDL from your mappings.

One-to-Many bidirectional relationships
Both the SpecialInstruction and the Order objects are examples of One-to-Many bidirectional relationships. In the case of SpecialInstruction, it is likely that we will care about which Pizza an instruction is associated with, and likewise for the Order. A bidirectional one-to-many relationship implies that one object has a collection of other o bjects. For example, an Order has a collection of Pizzas. First, lets add an order attribute to our Pizza object:

@Entity
@Table(name="PIZZA")
public class Pizza implements IdObject {
.
.
  @ManyToOne(cascade={CascadeType.ALL})
  @JoinColumn(name="pizza_order_id",nullable=false)
  private Order order;
 
  public Order getOrder() { return order; }
  public void setOrder(Order order) { this.order = order; }
.
.
}

Next, let’s create an Order object to contain our collection of Pizzas, like this:

@Entity
@Table(name="PIZZA_ORDER")
public class Order implements IdObject {
  @Id
  @Column(name="pizza_order_id")
  private Integer id;
 
  @OneToMany(cascade={CascadeType.ALL},mappedBy="order")
  private Set pizzas = new HashSet();
 
  @Version @Column(name="version")
  private Integer version;
 
  // (version and id accessors omitted)
 
  public Set getPizzas() {  return pizzas; }
  public void setPizzas(Set pizzas) { this.pizzas = pizzas; }
  public void addPizza(Pizza pizza) {  pizza.setOrder(this);  this.pizzas.add(pizza); }
}

There are a couple of things you worth noting about this mapping:
1.) The @OneToMany annotation uses the mappedBy attribute to indicate which member of the related object defines the linkage between the two tables. In this case, we are saying that the Pizza object contains a member named order, which defines the linkage between the two objects.
2.) I’ve created a utility method called addPizza. This simplifies setting both sides of the bidirectional relationship by setting the Order object on the Pizza and adding the Pizza to the Order’s collection. Users of this class will only need to make one method call to do both.

Many-to-Many relationships via a Join Table
The last thing we’ll cover is how to map Join Tables. In our ERD, you can see that Toppings are modeled in the database with a TOPPING table that contains all of the valid toppings, a PIZZA table that contains all of the valid Pizzas, and a PIZZA_TOPPING table in the middle that maps all of the valid Pizzas to all of the valid Toppings. You could create an object called PizzaTopping that corresponds to the PIZZA_TOPPING table. Then you could have a One-to-Many relationship from the Pizza to the PizzaTopping, and a One-to-One from each PizzaTopping to a Topping. That would be very cumbersome to work with! Fortunately, there’s a better way.

Logically, a Pizza has a collection of Toppings. In our Java code, we really shouldn’t care about the fact that there is a PIZZA_TOPPING join table in the middle. First, let’s create a simple Topping class:

@Entity
@Table(name="TOPPING")
public class Topping implements IdObject {
  @Id
  @Column(name="topping_id")
  private Integer id;
 
  @Column(name="topping_description")
  private String description;
 
  @Column(name="topping_price")
  private BigDecimal price;
 
  @Version @Column(name="version")
  private Integer version;
 
  // (Accessors omitted)
}

This is how the association would be mapped in the Pizza class:

@Entity
@Table(name="PIZZA")
public class Pizza implements IdObject {
.
.
  @ManyToMany(cascade={CascadeType.ALL})
  @JoinTable(name="PIZZA_TOPPING",
             joinColumns=@JoinColumn(name="pizza_id"),
             inverseJoinColumns=@JoinColumn(name="topping_id"))
  private Set toppings = new HashSet();
 
  public Set getToppings() { return toppings; }
  public void setToppings(Set toppings) { this.toppings = toppings; }
  public void addTopping(Topping topping) { this.toppings.add(topping); }
.
.
}

The @JoinTable annotation defines three key attributes:
name: Identifies the name of the join table.
joinColumns: This attribute identifies the column name in the join table that points to this object.
inverseJoinColumns: This attribute defines the column name in the join table that points to the other objects.

From your Java code, the semantics for dealing with toppings on a pizza are just like any other set, much like you’d work with a One-to-many object.

Conclusion
Since the introduction of annotations, object/relational mapping is one of the easiest aspects of working with JPA over other frameworks. You can see this whole project in action on your IDE of choice by downloading it here (or from here if that doesn’t work for some reason). It should be a pretty reasonable starting point if you want a reference project to start playing with JPA. I hope to revisit the Pizza Shop project to cover other JPA topics in future posts.

The Myth of Requirements Gathering

Wednesday, January 30th, 2008

This post comes courtesy of the bureau of patently obvious.

Lots of software projects I’ve worked on didn’t live up to the end-user’s expectations. Sadly, it’s all part of the job. Perhaps it a bigger part than it should be.

The most successful projects I’ve worked on were those where I actually visited an end-user, and said “hey, I can make that easier for you!” There have been cases where this involved flying across the country to actually watch someone using the software with my own two eyes. I wasn’t privy to the financial expense of these trips, but from a customer satisfaction perspective, it seemed well worth it.

The alternative is to have some sort of analyst sit down with a programmer, and that person creates a pile of documents that are dumped on a programmer’s desk.

Abstraction is a wonderful tool for coding. You’ve probably heard the old programming adage “there’s no problem that can’t be solved with another layer of abstraction!” But it doesn’t work when you introduce people into the equation.

Lots of fancy new software development processes have been invented to try to revolutionize software engineering, attempting to marginalize the venerable waterfall model. But in the end, it doesn’t take a cool, aggressively marketed name. You don’t need a cadre of consultants hocking books and services to convert you to the latest methodology. All you need is to get the programmers out of their cubicles, and sit them down with their own users once in a while.

What I learned from contributing to an Open Source project

Wednesday, January 23rd, 2008

A while ago, I had the opportunity to contribute to the Avant Window Navigator open source project. My participation in the project has waned lately, but I’ve had a little time to reflect on the time that I spent working on it. In no particular order, here were some of the things I took away from the project. Note that this is just based on a single project, and that my experience might have been quite different had I participated in other projects:

Learn to detach yourself from from your code. Once your stuff is checked into a public repository, anything can happen. Generally, most people will respect what they see as “your turf,” but that isn’t always the case. People will suggest improvements, implement them, and share them with the world before you even get a chance to review them. Overall, it’s a good thing and part of the ecology of an open-source project. At your typical office-programmer job, people usually end up becoming specialists in specific areas and the demarkation of responsibilities are quite clear, sometimes at the expense of progress. The boundaries are a lot looser in the open source community.

Interpersonal Relationships are Weird. When you’re in an office, you know that Fred is a little odd, and gets touchy when people criticize his font selection, because your co-worker warns you when you’re at the coffee machine. Anyone who lives and dies by their e-mail knows that emotions don’t get conveyed adequately in text, and the same is true with online forums and IRC channels. Some people lose their inhibitions when they don’t understand that they’re communicating with other people, and turn into jerks. Fortunately, there aren’t very many of these people.

There’s a wide range in quality. There’s no entrance requirement, so there’s a pretty wide variety in code quality. There are some incredible, amazing, talented people out there who are coding for their love of the craft. There are also people who make some sub-par stuff.

Apprehension about bugs. When I started, I was really worried about what would happen when I released software that was buggy. In a commercial environment, there are often layers of people between the programmer and the end-user, so bug reports come to you filtered and sanitized. In the open source world, people will report bugs openly, directly to you, on forums, for all the world to see. That made me nervous as hell. It turned out to be not so bad. The users knew that they were using bleeding edge stuff, and they expected a degree of instability and seemed to accept it quite well. They were helpful and sympathetic when reporting problems. I think it cuts both ways; when users report their software defects to someone far removed from the programmer, they’re less sympathetic and more irate than if they’re communicating directly with a person who can help them. Users are people, just like programmers, and they usually realize that the programmers are doing this for free and are quite polite.

Uptake on Localization was less enthusiastic than I thought it’d be. My weather applet was among the first to support multiple languages. Because there were so many contributers from outside the U.S. working on AWN, I thought people would jump at the opportunity to translate my applet to their native language. In the end, there were only three people who volunteered.

I felt old. Most of the people contributing to the project were in college or in their mid-twenties. I’m in my mid-thirties, and after working for 10 hours, coming home, feeding the kids and getting them ready for the next day, it’s 8:00 and I don’t feel much like getting out the laptop and coding. I managed to sneak in a few cycles at work, but I always felt a little guilty about it. While the other contributers were complaining about their upcoming finals, I had to deal with the upcoming PTA meeting.

You can learn a lot. I got into this project to “scratch an itch.” I was using Linux at work, I needed a dock, because I’m a Mac guy and I like docks. AWN was a Dock for Linux, but it was missing a clock. So I learned Python to create one. Now I know some Python, and I have a clock on my dock. I’m a happy man.

Glassfish to Tomcat w/ JDBC Connection Pooling

Monday, January 21st, 2008

Here’s your don’t-waste-hours-on-something-silly-that-I-did tip for the day.

I recently had the opportunity to change an existing in-house web application from running under Tomcat 5.5, to Glassfish v2. The application uses JDBC connection pooling in the application server, and uses JNDI to find the pool. The only stumbling block I encountered was that, immediately after deploying the application, Hibernate would always complain that it couldn’t find the connection:

org.hibernate.HibernateException: Could not find datasource
at org.hibernate.connection.DatasourceConnectionProvider.configure(DatasourceConnectionProvider.java:56)
at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:124)
at
.
.
(yadda yadda)
.
Caused by: javax.naming.NameNotFoundException: No object bound to name java:/comp/env/jdbc/MyDB
.
.

As it turns out, the datasource that I was using in hibernate.cfg.xml was perfectly fine for Tomcat, but not for Glassfish. I had put the fully qualified JNDI file in my config file:

<property name="connection.datasource">java:/comp/env/jdbc/ApptrackDB</property>

Glassfish doesn’t like that. Once I changed it to:

<property name="connection.datasource">jdbc/ApptrackDB</property>

Everything worked swimmingly.


© 2010 Mike Desjardins. All Rights Reserved.