tags:

views:

33

answers:

1

I have a class that I am using for each row in a grid, it is the mix of multiple entities data. the question is where to put it? I tried placing the class in the component package and instantiating it within my page, tried returning the class from an injected service, and nesting the class within the page POJO. in all cases it will work once and then on refresh I get this error:

Failure writing parameter 'row' of component admin/Add:grid.rows: Failure writing parameter 'row' of component admin/Add:grid: Could not find a coercion from type com.foo.bar.pages.admin.Add$RolesRow to type com.foo.bar.pages.admin.Add$RolesRow.

its about as non helpful an error that I can think of. I get that Tapestry wants you to inject all dependencies but I haven't figured what pattern to use to inject a class that you are going to instantiate on the fly.

Edit: here is the class

   public static class RolesRow{
    @Property public Boolean ROLE_SUPER;
    @Property public Boolean ROLE_ADMIN;
    @Property public Boolean ROLE_USER;
    @Property public Boolean ROLE_VIEW;
    @Property public Boolean ROLE_EMAIL;
    private Map<String,Role> roles;
    public RolesRow(){

    }
    public RolesRow(Map<String,Role> roles){
        ROLE_SUPER = (roles.containsKey("ROLE_SUPER") ? true:false);
        ROLE_ADMIN = (roles.containsKey("ROLE_ADMIN") ? true:false);
        ROLE_USER =  (roles.containsKey("ROLE_USER") ? true:false);
        ROLE_VIEW =  (roles.containsKey("ROLE_VIEW") ? true:false);
        ROLE_EMAIL = (roles.containsKey("ROLE_EMAIL") ? true:false);
        this.roles = roles;
    }
    public List<Role> selected(){
        List<Role> r = new ArrayList<Role>();
        checked(r,"ROLE_SUPER",ROLE_SUPER);
        checked(r,"ROLE_ADMIN",ROLE_ADMIN);
        checked(r,"ROLE_USER",ROLE_USER);
        checked(r,"ROLE_VIEW",ROLE_VIEW);
        checked(r,"ROLE_EMAIL",ROLE_EMAIL);
        return r;
    }
    private void checked(List<Role> r,String field,Boolean obj){
        if (obj !=null && obj == true){
            r.add(roles.get(field));
        }

    }

I am instantiating the record in setupRender:

        void setupRender(){
         List<RolesRow> list = new ArrayList<RolesRow>();
     list.add(new RolesRow());
+1  A: 

Business classes like that should not be located inside Tapestry's "magic" folders (components, mixins, pages, orservices).

Tapestry will reload (and re-transform) the class whenever any file in its package changes. (This is part of the live class reloading mechanism.) When you store objects of that class in the session, that results in weird class cast exceptions, such as "A cannot be cast to A."

As a general rule, only put classes in the components folder that are Tapestry components, and put everything else elsewhere. This can be a pain when you have a class that really should be an inner class of a component class, such as yours, as you will have to move it outside the component where it is used.

You will also not be able to use Tapestry's metaprogramming magic, such as @Property.

Henning