-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: Hibernate Validator seems unused with inheritance
PostPosted: Tue Jul 21, 2009 12:22 pm 
Regular
Regular

Joined: Mon Aug 07, 2006 5:07 am
Posts: 56
Hi,

I'll try to discribe this situation as good as possible. It's a proof of concept I'm making for my own use based on a client's project which is implemented in old Struts, old EJB2 and a quite bad design.
I'm trying, for educational use and using a more complex project, to make a PoC for my client using new standardized technologies as JPA/Hibernate, JSF, and hopefully a more straightforward future-proof changeable design (which the current one isn't).

I use a custom constraint for Hibernate Validator to validate the format of an Belgian accountnumber.
The annotation and validator class are the following:
Code:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@ValidatorClass(RekeningNummerValidator.class)
public @interface RekeningNummer {

   public static final String DEFAULT_REGEX = "\\d{3}-\\d{7}-\\d{2}";

   // Maximum rekeningnummer
   // 000-0000000-00
   String regex() default DEFAULT_REGEX;

   String message() default "{validator.rekeningnummer.invalid}";

}

Code:
public class RekeningNummerValidator implements Validator<RekeningNummer> {

   private static final Integer EERSTE_BLOK = 0;

   private static final Integer TWEEDE_BLOK = 1;

   private static final Integer CONTROLECIJFERS = 2;

   private static final Double MODULO = new Double(97);

   private String regex;

   /**
    * @return the regex
    */
   public String getRegex() {
      return regex;
   }

   /**
    * @param regex
    *            the regex to set
    */
   public void setRegex(String regex) {
      this.regex = regex;
   }

   /**
    * @param parameters
    */
   public void initialize(RekeningNummer parameters) {
      this.regex = parameters.regex();
   }

   /**
    * @param value
    * @return
    */
   public boolean isValid(Object value) {
      if (value == null) {
         return true;
      } else if (value instanceof String) {
         String valueString = (String) value;
         if (StringUtils.isBlank(valueString)) {
            return true;
         } else {
            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(valueString);
            if (matcher.matches()) {
               String[] rekeningNummers = valueString.split("-");
               Double rest = Double.valueOf(rekeningNummers[CONTROLECIJFERS]);
               Double getal = Double.valueOf(rekeningNummers[EERSTE_BLOK] + rekeningNummers[TWEEDE_BLOK]);
               if (rest.equals(getal % MODULO)) {
                  return true;
               }
            }
         }
      }
      return false;
   }

}


I have an Entity Entiteit which is the superclass of another Entity Operator (a farmer) with is also mapped as an Entity.
The Entiteit Entity has been marked with the annotation @Inheritance(strategy = InheritanceType.SINGLE_TABLE) to be able to save all kinds of Entiteiten in the same table.

An Entiteit has an Embedded class OndernemingInformatie (CompanyInformation, like accountnumbers, firm numbers, ...). I have put the Annotation RekeningNummer to validate the format of an account number on a property of the OndernemingInformatie class.
When I create and persist an Operator object, which is a subclass of Entiteit, the Validator isn't called.
When I create and persist an Entiteit object, the Validator is fired and the isValid() method is called.

When I make the Entiteit class a @MappedSuperclass, the validator is used also when Operator is used.
Apparently there's a difference in inheriting properties and defined annotations when using an @Entity of an @MappedSuperclass.

The following code (lots) is used:
Code:
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Entiteit extends DataElement implements AlgemeenElement {
...
   private OndernemingInformatie ondernemingInformatie;
...
   /**
    * @return the ondernemingInformatie
    */
   @Embedded
   public OndernemingInformatie getOndernemingInformatie() {
      return ondernemingInformatie;
   }
...
   /**
    * @param ondernemingInformatie
    *            the ondernemingInformatie to set
    */
   public void setOndernemingInformatie(OndernemingInformatie ondernemingInformatie) {
      this.ondernemingInformatie = ondernemingInformatie;
   }
...
}

Code:
@Entity
public class Operator extends Entiteit implements AlgemeenElement {
...
}


Test code (after creating an Operator object):
Code:
...
       /**
    * Test het persisteren van een Operator object.
    */
   @Test
   public void testPersistOperator() {
      Operator operator = this.generateOperator();
      try {
         PersistenceUtils.beginTransaction();
         PersistenceUtils.getEntityManager().persist(operator);
         PersistenceUtils.commitTransaction();
         Assert.assertNotNull(operator.getId());
         operator = PersistenceUtils.getEntityManager().find(Operator.class, operator.getId());
      } catch (InvalidStateException e) {
         PersistenceUtils.rollbackTransaction();
         logger.error(e.getMessage(), e);
         ValidatorUtils.logInvalidValues(e);
         Assert.fail(e.getMessage());
      } catch (PersistenceException e) {
         PersistenceUtils.rollbackTransaction();
         logger.error(e.getMessage(), e);
         Assert.fail(e.getMessage());
      }
   }
...


Can anyone explain to me why the custom validator class for validating an Operator object is not used when I declare the Entiteit class as an Entity, and why it is called if I declare the Entiteit as a MappedSuperclass - but then I can't use Entiteit seperately.

Now i've declared it as a MappedSuperclass and as abstract. I might not need it seperately but it can occur that I need it.

Thanks in advance.


Top
 Profile  
 
 Post subject: Re: Hibernate Validator seems unused with inheritance
PostPosted: Tue Jul 21, 2009 12:40 pm 
Regular
Regular

Joined: Mon Aug 07, 2006 5:07 am
Posts: 56
Ow, by the way:

Actually I want to try to let Hibernate/Persistence Manger create an Entiteit table for me with a discriminator column, where I can place an Operator, Contact, OtherDestination, etc. object under.

Now, even with DiscriminatorColumn and DiscriminatorValue specifications it still creates an Operator table.

I want to use DBUnit to specify a bit of data to work on, but I can't do that without knowing the tables to work on. And if a specify Entiteit as an MappedSuperclass, a table won't be generated for that one so I can't specify an Entiteit table.

Now, when I declare Entiteit as a MappedSuperclass, it doesn't even generate my specified Discriminator column.

So, for a summary:
I would like to persist all kinds of Entiteit objects in one table. Operator is such an Entiteit type.
But I have custom Hibernate Validators which don't go off in my Unit tests if I declare the top level class (Inherticance.SINGLE_TABLE) as an Entity, but it is fired if I declare it as MappedSuperclass which destroys my whole plan of putting all objects in one Entiteit table.

Thx for all your information which you might give.


Top
 Profile  
 
 Post subject: Re: Hibernate Validator seems unused with inheritance
PostPosted: Wed Jul 22, 2009 9:45 am 
Regular
Regular

Joined: Mon Aug 07, 2006 5:07 am
Posts: 56
anyone?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.