Trapo. what do you think about ...

my journey developing trapo 

Fast post: trapo maven site

How cool is dropbox? I just created an account and now the site generated by maven is available at:

https://dl.getdropbox.com/u/2812119/trapo/index.html

I promisse that I will try to maintain it updated with the code in github.

cya

Loading mentions Retweet
Filed under  //   dropbox   maven   site  

Comments [0]

Unique Constraint with Hibernate Validator and Spring

Sometime ago I was fighting with Hibernate Validator, trying to implement an unique constraint and I could not figure out how to create one that requires database access:

The problem is that your validators can't access sessionFactory or any other interface to the database. I know that I can break some rules and instantiate a sessionFactory/session/connection directly inside the Validator, but I dislike to do wrong things consciously. So, I looking for alternatives.

Then, while studying the new validation support offered by Spring, I just discovery that using Spring I can inject any bean inside my ConstraintValidators. From Spring documentation:

By default, the LocalValidatorFactoryBean configures a SpringConstraintValidatorFactory that uses Spring to create ConstraintValidator instances. This allows your custom ConstraintValidators to benefit from dependency injection like any other Spring bean.

And here is how you can use that Spring feature to implement unique constraint.

THE UNIQUE ANNOTATION

It is very simple and direct. You can see details about implementing your custom annotations in Hibernate Validator docs.

@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy=UniqueConstraintValidator.class)
@Documented
public @interface Unique {
    String message() default "{constraints.unique}";
    Class<?> entity();
    String field();
    Class<?>[] groups() default {};   
    Class<? extends Payload>[] payload() default {};
}

You can also see the code at GitHub, where trapo is hosted. If I decide to change something, you can get an updated version there. Once you have the @Unique annotation, you must implement the ConstraintValidator referenced by "validationBy" property in @Constraint annotation above. Here is the code using a bean injected by Spring:

public class UniqueConstraintValidator implements ConstraintValidator<Unique, String> {

    @Autowired private SessionFactory sessionFactory;
   
    private Class<?> entity;
    private String field;
   
    public void initialize(Unique annotation) {
        this.entity = annotation.entity();
        this.field = annotation.field();
    }

    public boolean isValid(String value, ConstraintValidatorContext context) {
        if(StringUtils.isEmpty(value)) {
            return false;
        }
        return query(value).intValue() == 0;
    }

    private Number query(String value) {
        HibernateTemplate template = new HibernateTemplate(sessionFactory);
        DetachedCriteria criteria = forClass(entity)
                                   .add(eq(field, value))
                                   .setProjection(count(field));
        return (Number)template.findByCriteria(criteria).iterator().next();
    }

}

Just like the @Unique annotation, you can find the code in GitHub. Now you just need a Validator bean that can be injected in the classes that need it.

<bean id="validator"
      class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />

Voilá!

THE UGLY PART

Right now, Hibernate Validor don't offer any way to know from where your annotations are coming. If you take some time to think about the ConstraintValidator above, you will notice that I manually configure the entity class and field information that were annotated. I need that information to know what query I must execute in order to validate the uniqueness of the field. Bad to me. Really bad. Now I have to provide this information by myself annotating the field like the code highlighted below:

    @NotEmpty @Unique(entity = Forum.class, field = "name")
    private String name;

I can even hear the DRY concept crying! I can't also find a way to reflect this to my schema. Maybe Hibernate Validator can offer some interfaces that we can use to implement all this stuff.

Loading mentions Retweet
Filed under  //   code   hibernate   spring   unique   validation  

Comments [0]

Maven + Hibernate + Spring + HSQLDB = your tests running fast and out-of-the-box

I want to keep Trapo environment as simple as possible. I want that people just fire a command and all tests can run immediately: no setups, no database creation, no sql to run. Just one single command and trapo should do everything for you. Because of that, I start to isolate the test environment from the production one in order to use a different database instance (or even a different database vendor). To integrate the combo, I just call HSQLDB to the party. To avoid describe exactly what is HSQLDB, here is a quote from its homepage:

HSQLDB (HyperSQL DataBase) is the leading SQL relational database engine written in Java. It has a JDBC driver and supports a rich subset of ANSI-92 SQL (BNF tree format) plus many SQL:2008 enhancements. It offers a small, fast database engine which offers both in-memory and disk-based tables and supports embedded and server modes. Additionally, it includes tools such as a minimal web server, in-memory query and management tools (can be run as applets) and a number of demonstration examples.


FIRST, CONFIGURE MAVEN...

The simplest part: just add hsqldb as a maven dependency:

<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <version>1.8.0.10</version>
    <scope>test</scope>
</dependency>

I decide to scope it as test because I'm not intent to use it in production, but you can use a different scope.

SECOND, ADD TEST RESOURCES...

Then, I just create two files inside src/test/resources directory. You can create files here to replace src/main/resources while running tests. But I want to reduce the amount of work to maintain both test and production enviroment, so, I'm replacing just what need to be replace: the database configuration. The two files are:

src/test/resources/hibernate.tests.properties

hibernate.connection.driver_class = org.hsqldb.jdbcDriver
hibernate.connection.url = jdbc:hsqldb:mem:trapo
hibernate.connection.username = sa
hibernate.connection.password =
hibernate.c3p0.min_size=5
hibernate.c3p0.max_size=20
hibernate.c3p0.timeout=1800
hibernate.c3p0.max_statements=50
hibernate.dialect = org.hibernate.dialect.HSQLDialect

hibernate.show_sql=true
hibernate.format_sql=true
hibernate.default_batch_fetch_size=5
hibernate.generate_statistics=true
hibernate.use_sql_comments=true
hibernate.jdbc.batch_size=10

hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true
hibernate.cache.provider_class=net.sf.ehcache.hibernate.EhCacheProvider
hibernate.cache.use_structured_entries=true

hibernate.hbm2ddl.auto=create-drop

Note the url property, it is pointing to an in memory database. Moreover, this files contains cache and some other optional configurations to mimic the production configurations. The other file is the Spring context to configure the SessionFactory for tests:

src/test/resources/applicationContextTest.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/util
           http://www.springframework.org/schema/util/spring-util-2.5.xsd">
  <bean id="testSessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
        p:annotatedClasses-ref="annotatedClasses"
        p:annotatedPackages="com.google.code.trapo.domain"
        p:hibernateProperties-ref="hibernateProperties" />
  <util:list id="annotatedClasses">
    <value>com.google.code.trapo.domain.Forum</value>
    <value>com.google.code.trapo.domain.Topic</value>
  </util:list>
  <util:properties id="hibernateProperties" location="classpath:hibernate.test.properties" />
</beans>

I'm not fully confortable with that because I need to copy and past mapped classes here. But, this is a start, so I prefer to have sub-optimal solution over don't have any solution at all.

THIRD, REFACTOR YOUR TESTS...

Your tests should use SpringJUnit4Runner instead of the default one. So you have to put the following annotation in the test class:

@RunWith(SpringJUnit4ClassRunner.class)
public class MyRepositoryTests {
    ...
}

You also need to say to Spring where it should find the configuration files using @ContextConfiguration annotation:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
    "classpath:/trapo-servlet.xml",
    "classpath:/applicationContextTest.xml"
})
public class MyRepositoryTests {
    ...
}

And, because your tests are using the database, is a good call configure them to be transactional. In order to do that, you need both @Transactional and @TransactionConfiguration annotations:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
    "classpath:/trapo-servlet.xml",
    "classpath:/applicationContextTest.xml"
})
@Transactional
@TransactionConfiguration(transactionManager = "txManager")
public class MyRepositoryTests {
    ...
}

And then inject the testSessionFactory configure in applicationContextTests.xml in your tests:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
    "classpath:/trapo-servlet.xml",
    "classpath:/applicationContextTest.xml"
})
@Transactional
@TransactionConfiguration(transactionManager = "txManager")
public class MyRepositoryTests {

    @Autowired private SessionFactory testSessionFactory;

}

FINALLY, JUST RUN YOUR TESTS...

And now the grand finale, just open a command prompt, go to trapo directory and type:

mvn clean test

If you want to see cobertura report, type:

mvn clean cobertura:cobertura

Hope that helps.

Loading mentions Retweet
Filed under  //   hibernate   hsqldb   maven   running   spring   tests  

Comments [2]

Trapo: almost 0% code not covered by tests.

I'm glad to tell you that trapo, right now, has almost 100% code coverage. More precisely, Clover is telling me trapo has 99,5% of code coverage. Wow!

BUT LET ME EXPLAIN SOME POINTS

First, I don't care about have 100% code coverage, what I really care about is have a strong test suite, a good foundation to write code and help trapo to evolute in a sustainable pace. The number is just a metric to alert me when I get away of good practices, the code coverage number is just to make me think about my decisions: "Is it ok to left this class with poor code coverage?"; "Is it ok to not test these boundaries?". Questions like that arise when you are measuring useful stuff like how much of your code your test DON'T touch.

Yes, I turning my attention to code without tests because I'm trying to be a quite dysfunctional here. To me, have code touched by tests must be the default situation, and so, I'm carring about the exceptions, those situations where I consciously decide not to have tests. Happy to see that are too few situations like that in trapo's code.

Loading mentions Retweet
Filed under  //   clover   code   coverage   quality   tests  

Comments [0]

Running using Tomcat Plugin

Fast tip: you can use tomcat maven plugin to run Trapo in development mode. Just open a prompt, go to trapo directory and run the following command:
 
>> mvn clean tomcat:run 
Voilá! Besides the fact that Trapo runs ok in Tomcat, I'm just trying compatibilities issues here. Tomcat is more heavy than Jetty for restarts, something that I need to change-save-and-see developement.

Loading mentions Retweet
Filed under  //   maven   running   tomcat  

Comments [0]

How to Run Trapo?

So, do you want to run Trapo and see how it looks like?

CURRENT STATE

For now, you can just run it in development mode. You will need:
  1. You need Java, because Trapo is developed using Java. You need version 1.5 or newer
  2. PostgreSQL (8.2 or newer) with a database named trapo and with an user "trapo" with password "trapo"
  3. And you need maven.
Once you have all this stuff installed and configured in your box, you can run Trapo using one of the these two ways:

RUN TRAPO THROUGH MAVEN

Piece of cake, just travel to Trapo directory and type:

> mvn clean jetty:run

Probably, maven will try to download the whole internet and so the command may take a while to run. But this will occur just first time you run the command. Open your browser and go to http://localhost:8080/trapo/index.html

CREATING AND DEPLOYING A WAR

If you choose this option, you will need a servlet container (Tomcat, Jetty, Glassfish, etc). Just follow the steps below:
  1. Travel to Trapo directory and run: > mvn war
  2. Maven will generate a war file, rename it to trapo.war
  3. Deploy the trapo.war (usually you just need to copy the file to a directory inside your container)
Open your browser and go to http://localhost:8080/trapo/index.html

Loading mentions Retweet
Filed under  //   building   jetty   maven   running   tomcat  

Comments [0]

Trapo Screenshots for the version 0.0.1

Long time without posting here, but I have a good excuse. Last month I was moving to a new apartment! Nice move. Well, I'm trying to keep a pace while developing Trapo, but keep a pace is a quite difficult. Anyway, here are some screenshots for the current code on github.

Next week I will post more about the good, the bad and the ugly.

     
Click here to download:
Trapo_Screenshots_for_the_vers.zip (35 KB)

Loading mentions Retweet
Filed under  //   firefox   running   screenshots  

Comments [0]

Trapo on Git

I start Trapo as a google code project, but, because I'm trying to learn as much as I can, I move the code to github. That is the first time I use git and I have some minor problems (specially because I'm using Windows). Well, git is native to linux, but you can install on windows with msysGit. First I thought that git would be available in path, but it have its own bash. Then I follow github's instructions to create Trapo repository and some problems arise.

GIT CAN'T AUTHENTICATE

0,21 seconds later google says me that I need to add the rsa key using ssh-add:

   >> ssh ~/.ssh/id_rsa

BUT...

... the command outputs a error message: "could not open a connection to your authentication agent.". 0,09 seconds later google says me that I need to execute ssh-agent using the following command:

   >> exec ssh-agent bash

where you can replace bash with the shell of your choice. Once you do this, you should be able to run ssh-add to load your key for that shell and so push code to github.

Nice! Now you can clone Trapo from github or follow me there.

Loading mentions Retweet

Comments [0]

Unique Constraint with Hibernate Validator: Harder Than You Think

I'm annotating my domain with Hibernate Validator's annotations then I notice that there is not an unique constraint. My first thought was: "not a big deal, for sure is a piece of cake implement it". I can't be more wrong. Actually, create a custom constraint that does not require database access is very simple. Just create the annotation, the validator class and you are done. But, for constraints that requires database access, such as unique that must execute a query against database to validate its uniqueness, it is a pain in the ass.

The problem is that your validators can't access sessionFactory or any other interface to the database. I know that I can break some rules and instantiate a sessionFactory/session/connection directly inside the Validator, but I dislike to do wrong things consciously. So, I looking for alternatives.

HIBERNATE VALIDATOR 4.0

The new version is already in beta state and it implements JSR 303 (Bean Validation). I have no problems using beta stuff, but, according to JSR 303 "@Unique cannot be tested at the Java level reliably but could generate a database unique constraint generation. @Unique is not part of the BV spec today."

Ouch. Next alternative.

HACK THE HIBERNATE VALIDATOR CODE

Not a real hack, but just replace ValidateEventListener class which requires create a new ClassValidator and a way to made validator know sessionFactory.

OTHER VALIDATION FRAMEWORKS

Maybe Spring Validation, maybe OVal or... I still looking.

Loading mentions Retweet

Comments [0]

The Best Way to try your application: Maven Jetty Plugin

I was looking for a way to run Trapo with a single command, maybe deploy it to Tomcat or another Servlet Container. But, I used to turn on the server, write some code and see the changes instantly on the browser. Re-deploy the whole application every time that I change something is a complete overkill. So, I found some blog posts saying that Jetty is a more lightweight container, and that can be started/embedded easily. Hum, for sure someone already have create a wheel that I can use.

HELLO, MAVEN JETTY PLUGIN

Maven Jetty Plugin is that wheel. You just need to configure it in your pom.xml and it could even scan periodically the file system to automatically restart the context. Because Jetty is fast (and also because Trapo still a tiny application), the restart is fast as hell.

      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>maven-jetty-plugin</artifactId>
        <version>6.1.19</version>
        <configuration>
          <scanIntervalSeconds>5</scanIntervalSeconds>
          <stopKey>foo</stopKey>
          <stopPort>9999</stopPort>
        </configuration>
        <executions>
          <execution>
            <id>start-jetty</id>
            <phase>pre-integration-test</phase>
            <goals>
              <goal>run</goal>
            </goals>
            <configuration>
              <scanIntervalSeconds>0</scanIntervalSeconds>
              <daemon>true</daemon>
            </configuration>
          </execution>
          <execution>
            <id>stop-jetty</id>
            <phase>post-integration-test</phase>
            <goals>
              <goal>stop</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

As you can see, the scan interval is just 5 seconds, what is almost unnoticeable. Anyway, after some restarts I'm getting some permgen errors. That is the next fight.

Loading mentions Retweet
Filed under  //   jetty   maven   plugins   running  

Comments [0]