java - How to use a generic editor for database access in tapestry 5? -


i have tapestry 5 project contains following:

  • an abstract entity in entities package inherited other concrete entities

    import java.io.serializable; import javax.persistence.basic; import javax.persistence.column; import javax.persistence.generatedvalue; import javax.persistence.generationtype; import javax.persistence.id; import javax.persistence.mappedsuperclass;  @mappedsuperclass public class abstractentity implements serializable, comparable<abstractentity> {  private static final long serialversionuid = 1l; @id @generatedvalue(strategy = generationtype.identity) @basic(optional = false) @column(name = "id") protected integer id;  @override public int compareto(abstractentity o) {      return this.tostring().compareto(o.tostring()); }  } 
  • several concrete entities (i omit of bodies since believe it's irrelevant question, simple entity data classes) inherit abstractentity. example of 1 such entity class:

    //imports go here  @entity @table(name = "room") @namedqueries({     @namedquery(name = "room.findall", query = "select r room r")}) public class room extends abstractentity {     private static final long serialversionuid = 1l;     @basic(optional = false)     @column(name = "room_type")     @validate("required")     @enumerated(enumtype.string)     private roomtype roomtype; //rest of attributes , annotations go here, setter/getter methods 
  • a generic dao interface

    import com.mycompany.myproject.entities.abstractentity; import java.util.list;  public interface genericdao <t extends abstractentity>{  public abstract list<t> getlistofobjects(class myclass); public abstract t getobjectbyid(integer id, class myclass); public abstract t addorupdate(t obj); public abstract t delete(integer id, class myclass);  } 
  • implementation of generic dao interface, bound in appmodule in services package using binder.bind

    import com.mycompany.myproject.entities.abstractentity; import java.util.collections; import java.util.list; import org.hibernate.criteria; import org.hibernate.session; import org.hibernate.criterion.restrictions;  public class genericdaoimpl<t extends abstractentity> implements genericdao<t> {  private session session;  @override public list getlistofobjects(class myclass) {     list<t> list = session.createcriteria(myclass).setresulttransformer(criteria.distinct_root_entity).list();     collections.sort(list);     return list; }  @override public t getobjectbyid(integer id, class myclass) {     abstractentity ae = (abstractentity) session.createcriteria(myclass)         .add(restrictions.eq("id", id)).list().get(0);     return (t) ae;  }     @override public abstractentity addorupdate(abstractentity obj) {     return (t) session.merge(obj); }  @override public t delete(integer id, class myclass) {     abstractentity ae = (abstractentity) session.createcriteria(myclass)         .add(restrictions.eq("id", id)).list().get(0);     session.delete((t) ae);     session.flush();     return (t) ae; }  } 
  • a generic editor java class in components package

    import com.mycompany.myproject.entities.abstractentity; import com.mycompany.myproject.services.genericdao; import java.util.list; import org.apache.tapestry5.componentresources; import org.apache.tapestry5.propertyconduit; import org.apache.tapestry5.annotations.persist; import org.apache.tapestry5.annotations.property; import org.apache.tapestry5.beaneditor.beanmodel; import org.apache.tapestry5.hibernate.annotations.commitafter; import org.apache.tapestry5.ioc.annotations.inject; import org.apache.tapestry5.services.beanmodelsource; import org.apache.tapestry5.services.propertyconduitsource;  public class genericeditor<t extends abstractentity> {  @inject private propertyconduitsource conduit; @inject private genericdao genericdao; @property @persist private t bean; @property private t row; @inject private beanmodelsource bms; @inject private componentresources cr;  private class myclass;  {     propertyconduit conduit1 = conduit.create(getclass(), "bean");     myclass = conduit1.getpropertytype(); }  public list<t> getgrid(){     list<t> temp = genericdao.getlistofobjects(myclass);     return temp; }  public beanmodel<t> getformmodel(){     return bms.createeditmodel(myclass, cr.getmessages()).exclude("id"); }  public beanmodel<t> getgridmodel(){     return bms.createdisplaymodel(myclass, cr.getmessages()).exclude("id"); }  @commitafter object onactionfromdelete(int id){     genericdao.delete(id, myclass);     return this; }  @commitafter object onactionfromedit(int row){     bean = (t)genericdao.getobjectbyid(row, myclass);     return this; }  @commitafter object onsuccess(){     genericdao.addorupdate(bean);     try {         bean = (t) myclass.newinstance();     } catch(exception ex){     }     return this; } 
  • an associated .tml file genericeditor java class

    <!--genericeditor.tml--> <html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd" xmlns:p="tapestry:parameter">         <t:beaneditform object="bean" t:model="formmodel" >     </t:beaneditform>     <t:grid t:source="grid" t:model="gridmodel" add="edit,delete" row="row">         <p:editcell>             <t:actionlink t:id="edit" context="row">edit</t:actionlink>         </p:editcell>         <p:deletecell>             <t:actionlink t:id="delete" context="row">delete</t:actionlink>         </p:deletecell>     </t:grid> </html>  
  • furthermore, there several java classes in pages package, associated .tml files, made without using genericdao, using concrete dao's looked (example of 1 of them):

    import com.mycompany.myproject.entities.room; import com.mycompany.myproject.services.roomdao; import java.util.arraylist; import java.util.list; import org.apache.tapestry5.annotations.persist; import org.apache.tapestry5.annotations.property; import org.apache.tapestry5.hibernate.annotations.commitafter; import org.apache.tapestry5.ioc.annotations.inject;  public class roompage {      @property     private room room;     @property     private room roomrow;     @inject     private roomdao roomdao;      @property     private list<room> rooms;       void onactivate(){         if(rooms==null){             rooms = new arraylist<room>();         }         rooms = roomdao.getlistofrooms();     }      @commitafter     object onsuccess(){         roomdao.addorupdateroom(room);         room = new room();         return this;     }      @commitafter     object onactionfromedit(room room2){         room = room2;         return this;     }      @commitafter     object onactionfromdelete(int id){         roomdao.deleteroom(id);         return this;     }  } 
  • and associated .tml file:

    <!--roompage.tml--> <html t:type="layout" title="roompage"       xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"       xmlns:p="tapestry:parameter">     <div class="row">          <div class="col-sm-4 col-md-4 col-lg-3">                     <t:beaneditform object="room" exclude="id" reorder="roomtype, floor,                     tv, internet"                     submitlabel="message:submit-label"/>         </div>         <div class="col-sm-8 col-md-8 col-lg-9">              <t:grid t:source="rooms" exclude="id"              add="edit,delete" row="roomrow"             include="roomtype, floor, tv, internet">                 <p:editcell>                     <t:actionlink t:id="edit" context="roomrow">edit</t:actionlink>                 </p:editcell>                 <p:deletecell>                     <t:actionlink t:id="delete" context="roomrow.id">delete</t:actionlink>                 </p:deletecell>             </t:grid>         </div>     </div> </html> 

the code above using concrete dao works properly, form inputting new rows in database appears on page expected, grid rows database table.

so, basic idea use genericeditor genericdao in order reduce amount of code necessary , manipulate of database tables, using beaneditform input new rows in table , grid show rows table , delete or edit them. in theory, should work entity inherits abstractentity class, there wouldn't need make separate dao interface/implementation pairing each entity.

the problem is, can't seem work intended, i'm not sure how use genericeditor shown above. have attempted following:

  • roompage.java after modifications:

    import com.mycompany.myproject.components.genericeditor; import com.mycompany.myproject.entities.room;  public class roompage{      @component     private genericeditor<room> ge;  } 
  • roompage.tml after modifications:

    <!--roompage.tml--> <html t:type="layout" title="roompage"       xmlns:t="http://tapestry.apache.org/schema/tapestry_5_3.xsd"       xmlns:p="tapestry:parameter">    <t:genericeditor t:id="ge" /> </html> 

but apparently not work, yielded null pointer exception error:

blockquote [error] pages.roompage render queue error in setuprender[roompage:ge.grid]: failure reading parameter 'source' of component roompage:ge.grid: org.apache.tapestry5.ioc.internal.util.tapestryexception org.apache.tapestry5.ioc.internal.util.tapestryexception: failure reading parameter 'source' of component roompage:ge.grid: org.apache.tapestry5.ioc.internal.util.tapestryexception [at classpath:com/mycompany/myproject/components/genericeditor.tml, line 5]

i have tried remove grid element entirely, , run genericeditor beaneditform only. has resulted in page loading, instead of showing expected form on page, fields of room entity , create/update button @ end of form, appeared create/update button, without field, if beaneditform created on object without attributes. pressing create/update button creates null pointer exception.

for debugging purposes, have changed genericeditor.java work in non-generic way, creating attribute of generic type t in it, , initializing new object of type room, casted (t), , declaring attribute class of same type room attribute, seen bellow

private t room;  {     //propertyconduit conduit1 = conduit.create(getclass(), "bean");     //class = conduit1.getpropertytype();     room = (t) new room();     class = room.getclass(); } 

running application these changes (with grid still disabled , beaneditform enabled), page renders input fields correctly. has led me conclusion problem lies within fact genericeditor not receive proper type through generic, not know if logic correct, , if is, how around issue. possible source of problem might propertyconduit, not sure how works exactly, , if i'm using correctly or not, i'm not ruling out issue originates there well. either way, main guess i'm misusing genericeditor somehow, title of question says, how supposed use genericeditor in order access database it?

i have searched stackoverflow similar problems own have been unable find similar, neither here nor elsewhere. hoping here able me identify issue , me around it, have no idea how on own. in advance.

update: have done further debugging, trying check type of class gets forwarded genericeditor's myclass. have modified following bit of genericeditor.java:

    {         propertyconduit conduit1 = conduit.create(getclass(), "bean");         myclass = conduit1.getpropertytype();     } 

to following:

    {         propertyconduit conduit1 = conduit.create(getclass(), "bean");         system.out.println("conduit1.tostring(): "+conduit1.tostring());         system.out.println("conduit1.getpropertytype().tostring(): "+conduit1.getpropertytype().tostring());         system.out.println("conduit1.getpropertytype().getname(): "+conduit1.getpropertytype().getname());         myclass = conduit1.getpropertytype();         system.out.println("myclass.getname(): "+myclass.getname());     } 

and has resulted in following output:

conduit1.tostring(): propertyconduit[com.mycompany.myproject.components.genericeditor bean]

conduit1.getpropertytype().tostring(): class com.mycompany.myproject.entities.abstractentity

conduit1.getpropertytype().getname(): com.mycompany.myproject.entities.abstractentity

myclass.getname(): com.mycompany.myproject.entities.abstractentity

which believe pretty means type t forwarded genericeditor abstractentity, not room intended. if assumption correct, i'm misusing genericeditor i'm not getting proper class forwarded via generics, how supposed forward proper class it? or assumption wrong , else amiss here?

i've managed find answer question, i'm posting here in case ever needs it:

there 2 reasons why application did not work intended: 1) in genericdaoimpl class, i've forgot add @inject annotation above "private session session" line, yielded error in first place piece of code should have looked this:

//imports public class genericdaoimpl<t extends abstractentity> implements genericdao<t> { @inject private session session; //rest of code unchanged 

2) thing unsure in first place how use genericeditor component, , trying in wrong way, trying add component class file , associated tml file. supposed done instead extend genericeditor, , delete associated tml file, genericeditor tml used instead, this:

public class roompage extends genericeditor<room>{ } 

upon making these 2 changes, application works intended


Popular posts from this blog

c# - ODP.NET Oracle.ManagedDataAccess causes ORA-12537 network session end of file -

matlab - Compression and Decompression of ECG Signal using HUFFMAN ALGORITHM -

utf 8 - split utf-8 string into bytes in python -