Search code examples
jsfreflectionprimefacesjava.lang.class

How to cast a (java.lang.Class) Class to a Class obtained with reflection


I'm trying to build a module for managing my database's catalogues like: country, enterprises, users etc. The user is supposed to select the catalog from a combobox and the system is supposed to display a table with the principal columns (not null in the database and some predefined by me). From the 3 objectives I have only achieved 2: 1.- get the @NotNull fields from the Entity Classes after selecting the catalogue using reflection 2.-display the table with dynamic columns retrieving them from the above also. But number 3 is giving me trouble. The thing is, I used this folling code in the view for displaying columns dynamically (based on the @NotNull fields I stored in an object) ,(https://www.primefaces.org/showcase/ui/data/datatable/columns.xhtml):

<p:dataTable  id="conceptos" var="pojo" value="#{catalogoMB.comocombo}>
<p:columns value="#{catalogoMB.columns}" var="column" 
columnIndexVar="colIndex" sortBy="#{pojo[column.property]}" filterBy="#
{pojo[column.property]}">
        <f:facet name="header">
        <h:outputText value="#{column.header}" />
        </f:facet>
        <h:outputText value="#{pojo[column.property]}" />
</p:columns>
</p:dataTable> 

So for example, in a normal way, without reflection the code above will work like this: comocombo will have this properties: name, value, id; and my array of columns will be the same: name, value, id... The thing is, comocombo is a List<Object> object where I store field's reflection class values, which returns java.lang.class instead of the instance of the EntityClass although I managed to invoke setter and getter from an Object instance of that class (combito) -supposedly- so when I try to display pojo[column.property]-> comocombo["id"], comocombo["name"] or comocombo["value"] it sends me an exception saying that java.lang.class doesn't have this any properties....How can I reach them? I've read about Map<String, String> and of .cast() But I'm not sure this could be the way.

public void populateT(){ 
comocombo=new ArrayList<>();
Object tt ;
y = tabla.get(tabla.size()-1).getConcpetos(); //result of query type: 
FindAll from the entity Class 
try{
Class combito= Class.forName("sipe.services."+ catName); //the "path" of the 
Entity Classes
for (Integer j=0; j<y.size()-1; j++){
tt=y.get(j);
            for (Integer i=0; i< tabla.size()-1; i++){
            tucampo=minustomayus(y.get(j).getClass().getDeclaredField(tabla.get(i).getNombre_c()).getName()); //tabla.get(i).getNombre_c()-> here I've stored the @NotNull properties' names (countryid, countryname...) whic are the same in  columns = new ArrayList<ColumnModel>();  (catalogoMB.columns in the view) 
            Class cls= Class.forName("sipe.services."+ catName);
            Method method = cls.getDeclaredMethod("get"+tucampo); // for example "countryid" -> getCountryid              
            Class<?> type = null;
            for (Method methods : combito.getDeclaredMethods())
            { //Here I'm trying to invoke setter of the Entity Class in order to store its values..
              //equivalent to: if o is an instance of Entity Class Country: Country o = new Country(); o.setCountryid(2);
                if (methods.getName().contains("set"+tucampo)){
                type=method.getReturnType();
                methods.invoke(combito.newInstance(),method.invoke(tt));
             }
            }

Solution

  • I got mine to work this way, hope it helps

     private void createDynamicColumns(){
                //split column templates
                String[] columnKeys = columnTemplate.split(" ");
                //set first list to null
                //this should be a List with no type specified
                //eg List objects = new ArrayList<>();
                //since you will dynamically populate it based on what the user selects from combobox
                objects = null;
                //clear columns
                columns.clear();
                //create a class from combobox selection
                Class<?> forName = Class.forName("pathToClass." + comboboxSelection);
                //get declared fields in that class
                List<Field> asList = Arrays.asList(forName.getDeclaredFields());
                //for each columkeys
                //if method.getName() can be found in columnKeys
                //add that columnKey to the new columnList;
                for(int i =0;i< asList.size();i++)
                    for (String columnKey : columnKeys) {
                        String fieldName = asList.get(i).getName();
                        if (columnKey.equalsIgnoreCase(fieldName)) {
                            columns.add(fieldName);
                        }
                    }
    
              //fetch from the database the objects list
               objects = DAO.findAll();
            }
    

    and facelets page

    <p:dataTable var="object" value="#{backingBean.objects}">                    
            <p:columns value="#{BackingBean.columns}" var="column">
                <f:facet name="header">
                    <h:outputText value="#{column}" />
                </f:facet>
                <h:outputText value="#{object[column]}" />
            </p:columns>
    </p:dataTable>
    

    Remember to deal with exceptions