6

I'm working on an Spring application with lots of input forms. I'd like to reuse the field length in the UI-form, validation and JPA annotations. Is there an elegant way to solve this. My solution at the moment is, to use constants to declare the length:

public class Person
{
   public static final int FIRSTNAME_LENGTH = 25;

   @Column(length=FIRSTNAME_LENGTH)
   private String firstName;

   ...
}

and then reuse the constant in the Validator and the Jsp

...

<form:input path="firstName" 
    maxlength="<%= Integer.toString(Person.FIRSTNAME_LENGTH) %>"/>

...

which is pretty verbose.

Is there any more elegant solution to this problem?

James McMahon
  • 48,506
  • 64
  • 207
  • 283
Dominik
  • 1,241
  • 1
  • 14
  • 31
  • Dominik, your "in-elegant" solution looks pretty clever to me. I may have to use that. Good question regardless, this is something everyone has to do but there doesn't seem to be built in solution for it. – James McMahon Dec 18 '09 at 16:09
  • I am glad you put a bounty up here, I want to see this answered as well. I wish they had a feature for community bounties, I'd throw in some of my rep. – James McMahon Dec 18 '09 at 18:43

3 Answers3

12

It's quite possible to access the information stored in annotations. In fact, this is their main purpose: storing meta information on a class/ method/ field. Here is an example of how to access the length stored in a @Column annotation:

import javax.persistence.Column;
import javax.persistence.Entity;

@Entity
public class Person {

   @Column(length=30)
   private String firstName;

   public static void main(String[] args) throws SecurityException, NoSuchFieldException {
      Object person = new Person();
      //find out length    
      System.out.println(person.getClass().getDeclaredField("firstName").getAnnotation(Column.class).length());
   }
}

You should be able to create some custom tag or bean to extract this info generically.

It's not difficult to create your own annotations. You could consider creating one that specifies which fields are to be included on the form, how they should be rendered, description, etc. Than you could create a generic form. Then again you may not like to mix domain and presentation.

EJB
  • 2,383
  • 14
  • 15
  • That's quite a line full, the famous Java terseness is alive and well. Great tip, thank you. – James McMahon Dec 22 '09 at 22:35
  • Just a follow up, java.lang.Class.getDeclaredField() throws two checked exceptions, NoSuchFieldException and SecurityException. This makes this method a little more clunky and is something to keep in mind if your are trying to implement this solution. – James McMahon Jan 07 '10 at 15:14
1

I asked a similar question when I was using Hibernate,

Getting column length from Hibernate mappings?

No idea how to pull this information under JPA however, but if you are using Hibernate as your underlying layer you could try access Hibernate directly and implement the solution above.

However the Hibernate solution is just as in-elegant as the solution that you outlined in your answer, with the added disadvantage that it ties your JPA implementation to Hibernate.

Community
  • 1
  • 1
James McMahon
  • 48,506
  • 64
  • 207
  • 283
0

The solution provided by EJB reads the annotated value for column length. James McMahon pointed out that this exposes the Hibernate implementation. That can be resolved fairly simply with getter methods. Assuming there is an interface for Person with a declared method getFirstNameLength:

import javax.persistence.Column;
import javax.persistence.Entity;

@Entity
public class PersonImplementation extends Person {

   @Column(length=30)
   private String firstName;

   public int getFirstNameLength() {
       return this.getClass().getDeclaredField("firstName").getAnnotation(Column.class).length();
   }
}