Tuesday, November 22, 2011

CDI Query Module First Alpha Released!


It's been some months now since we started exploring CDI extensions as a small exercise. As it turned out, the exercise forged into something usable which we're pushing now in the open as a first Alpha shot.

So I'm happy to announce the availability of the CDI Query Module on Maven Central! The module helps you creating JPA queries with much less boilerplate, and is of course leveraging the CDI extension API as well as Seam Solder. Some of the feature highlights are:

Query By Name

Assuming you have a Person entity which looks probably similar to this:

@Entity
public class Person { 

    ... // primary key etc. skipped

    @Getter @Setter
    private String firstName;
    
    @Getter @Setter
    private String lastName;

}

You can simply create a DAO interface to query for Persons:

@Dao
public interface PersonDao extends EntityDao<Person, Long> {

    Person findByFirstNameAndLastName(String firstName, String lastName);

}

This interface does not need to be implemented. A client can just inject it, call the interface method and in the background, the JPA query is automatically created and executed. To create the query, the method name is analyzed and matching the name to entity properties.

public class PersonAction {

    @Inject
    private PersonDao personDao;
    
    public void lookup() {
        person = personDao.findByFirstNameAndLastName(firstName, lastName);
    }

}

Note that the base interface contains also a couple of other methods which you might also expect from an entity DAO. Ideally, you should not need to inject an EntityManager anymore.

Query by Query Strings and Named Queries

Of course matching property names is not extremely safe to refactorings (some more validation support here is on the roadmap) - if you like to have more control over your JPA queries, you can also annotate the method with the query to execute:

@Dao
public interface PersonDao extends EntityDao<Person, Long> {

    @Query("select p from Person p where p.ssn = ?1")
    Person findBySSN(String ssn);

    @Query(named=Person.BY_FULL_NAME)
    Person findByFullName(String firstName, String lastName);

}

Criteria API Simplifications

If you're not a big fan of query strings but rather prefer using the JPA 2 criteria API, we also allow to simplify this with a small utility API:

public abstract class PersonDao extends AbstractEntityDao<Person, Long> {

    public List<Person> findAdultFamilyMembers(String name, Integer minAge) {
        return criteria()
                    .like(Person_.name, "%" + name + "%")
                    .gtOrEq(Person_.age, minAge)
                    .eq(Person_.validated, Boolean.TRUE)
                    .orderDesc(Person_.age)
                    .createQuery()
                    .getResultList();
    }

}

All the code is hosted and documented on GitHub. Please:

  • Give feedback! If you find this useful or actually not so, we're happy to hear what is still missing.
  • Participate! Forking and creating pull requests are really a breeze on GitHub :-)


Credits:

  • Bartek Majsak for improving the initial code, taking care about quality reports and soon finalizing the stuff on the validation branch ;-) (just kidding, check out Bartek's cool work on the Arquillian Persistence Module!)
  • Grails GORM for inspiring me for this Java implementation
  • The CDI folks for a really great specification
  • Last but not least the Arquillian guys, developing and testing this stuff is pure fun with Arquillian!

Friday, November 11, 2011

JBoss Forge JRebel Plugin - Video Tutorial

It's actually out for quite a while now (and therefore already slighly out of date) but I have hardly found some time to blog about it: If you're using JRebel and JBoss Forge, have a look at this Video tutorial how to use both of them together.



Make sure to watch it in HD and full screen mode. Thanks to Chris "Kubrik" Reimann for putting the tutorial together!

As an addition, Forge now also supports checking out specific versions of a plugin, which is in our case version 1.0.0.Beta1 of the JRebel plugin. We've also added the plugin to the Forge plugin repository index so you can search for it.

By the way, if you're only using one of the tools or (even worse) none of them, this is the perfect opportunity to get a quick hands-on.