Tapestry Grid & Hibernate Criteria

Tapestry Grid is a very powerful tool for displaying a list of entities. It expects a GridDataSource as source parameter. A useful tool can be a TypeCoercer which converts a Criteria to GridDataSource.

Here is a simple implementation

public class Criteria2GridDataSourceCoercion implements Coercion<Criteria, GridDataSource> {

    @Override
    public GridDataSource coerce(final Criteria criteria) {
        return new GridDataSource() {
            private List<?> cache;

            private int startIndex;

            @Override
            public int getAvailableRows() {
                setupCriteria(Projections.rowCount(), 0, 1);
                long count = ((Long) criteria.uniqueResult());
                return (int) count;
            }

            @Override
            public void prepare(int startIndex, int endIndex, List<SortConstraint> sortConstraints) {
                setupCriteria(null, startIndex, endIndex - startIndex + 1);
                criteria.setResultTransformer(Criteria.ROOT_ENTITY);

                if (sortConstraints.size() != 0) {
                    for (SortConstraint sortConstraint : sortConstraints) {
                        String propertyName = sortConstraint.getPropertyModel().getPropertyName();
                        criteria.addOrder(
                                sortConstraint.getColumnSort() == ColumnSort.ASCENDING ?
                                        Order.asc(propertyName) : Order.desc(propertyName));
                    }
                }

                cache = criteria.list();
                this.startIndex = startIndex;
            }

            @Override
            public Object getRowValue (int index) {
                return cache.get(index - startIndex);
            }

            @Override
            public Class getRowType() {
                if (cache == null) {
                    setupCriteria(null, 0, 1);
                    criteria.setResultTransformer(Criteria.ROOT_ENTITY);
                    cache = criteria.list();
                }

                if (cache.size() != 0) {
                    return cache.get(0).getClass();
                }

                return null;
            }

            private void setupCriteria(Projection projection, int firstResult, int maxResults) {
                criteria.setProjection(projection).setFirstResult(firstResult).setMaxResults
                        (maxResults);
            }
        };
    }
}

and in you Module class

   @Contribute(TypeCoercer.class)
    public static void addCoercion(Configuration<CoercionTuple> types) {
        types.add(new CoercionTuple(Criteria.class, GridDataSource.class,
                new Criteria2GridDataSourceCoercion()));
    }

Usage


public class SamplePage {

    @Inject
    private Session session;

    public Criteria getCriteria() {
        Criteria criteria = session.createCriteria(MyEntity.class);
        return criteria;
    }
}


<html xmlns:t='http://tapestry.apache.org/schema/tapestry_5_3.xsd'>
   <div t:type='Grid' t:source='criteria'>
   </div>
</html>

Dragan came up with another useful Coercer to convert Criteria to Long

    public static void contributeTypeCoercer(Configuration configuration) {
        configuration.add(CoercionTuple.create(Criteria.class, Long.class,
                new Coercion() {
                    @Override
                    public Long coerce(Criteria input) {
                        input = input.setProjection(Projections.rowCount());
                        input = input.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
                        return (Long) input.uniqueResult();
                    }
                }));

        configuration.add(CoercionTuple.create(Criteria.class, List.class,
                new Coercion() {
                    @Override
                    public List coerce(Criteria input) {
                        return input.list();
                    }
                }));
    }
About these ads

Tagged: , , ,

4 thoughts on “Tapestry Grid & Hibernate Criteria

  1. dragansah May 22, 2012 at 4:29 PM Reply

    This is almost the exact implementation as I have used in my projects. Good work !
    One thing though. If the criteria has no rows in the result – than you would have to know the class of the root entity, which you don’t in the example. One hack is to cast Criteria to CriteriaImpl (which is what is used for root criterias) and use criteria.getEntityOrClassName().

    I also have coercions to Long (for row count using projection not the expensive criteria.size()) and List

    Cheers

    • tawus May 22, 2012 at 4:56 PM Reply

      Hi Dragan

      Great! Why not blog it :) and add a link or just add your code in a comment. It will help readers.

      • tawus May 22, 2012 at 6:48 PM

        Thanks Dragan, I have added your comment(code) to the bottom of the post

  2. Tapestry5 Grid component | kosmology June 25, 2012 at 5:50 PM Reply

    [...] Tapestry5 Grid component [...]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 90 other followers

%d bloggers like this: