skip to main | skip to sidebar

Java Programs and Examples with Output

Pages

▼
 
  • RSS
  • Twitter
Thursday, October 4, 2012

Demonstrating use/power of Java Reflection API

Posted by Admin at 11:38 AM – 0 comments
 
The main target for us was to come up with a solution, where we can perform two task

1) Dynamically getting database relationship structure using Hibernate classes [ i.e. POJO ]
2) Dynamically perform recursive insertion/updation on database till end of relationship hierarchy without using single hardcode value

After much, discussions we explored Reflection APIs of JAVA using which we can use any field of any class, invoke any method of any class without even knowing class name,method name,field names. We built our entire solution around these features only.

As, we are using Hibernate POJOs to represent our database entity we used those Hibernate POJOs to use reflection API. Hibernate POJOs represents MANY side of a relationship using SET. i.e. POJO representing ONE side of relation will have a method, which is returning SET of MANY side. in example shown in problem statment above, Java class [ POJO ] representing DEPARTMENT will have a SET which provides information about all EMPLOYEE working under that department.

In our solution, we got an Object of master table using Hibernate methods [ call it OLD_OBJ ]. We made second copy of that object. [ call it NEW_OBJ]. we updated status of OLD_OBJ as INACTIVE record. all updations required was made to NEW_OBJ . Using reflection API, we got all childs of OLD_OBJ [i.e. SET of child ]. For all child we set the parent as NEW_OBJ by calling their respective methods using reflection. [ again, the updation will be taken place by same formule, i.e. DISABLE old record, create new copy and update new record] . We recursively did this operation till the end of database relation heirarchy.

This is merely 150 lines of code but it updates all tables in hierarchy whenever required [ in our case there are 17 tables which take part in 1-M relationship ]. We are contributing the solution just to show the power of Java reflection API so that this might be used whenever required.
       


/**
*  ===============================================================
*  SNIPLET FOR RECURSIVE INSERTION/UPDATION AND METHOD INVOCATION
*  ===============================================================
**/


        //FINDING OUT CLASS TYPE OF POJO
        Class classType = oldObject.getClass();
        
        //FINDING OUT ALL METHODS OF THE POJO i.e. OLD_OBJ
        Method allMethods[] = classType.getDeclaredMethods();

        try {
            logger.info("Start of method txGetChildObjects in InsertarGenericoServiceImpl");
            
            //LOOPING THROUGH ALL THE METHODS
            for (int aMethod = 0; aMethod < classType.getDeclaredMethods().length; aMethod++) {

                //GETTING CURRENT METHOD
                Method currentMethodObj = allMethods[aMethod];

                //FINDING OUT NAME OF CHILD CLASS
                String nameOfChildClass = currentMethodObj.getName().substring(3, currentMethodObj.getName().length() - 1);

                //IF THE METHOD IS RETURNING SET i.e. IT IS A METHOD WHICH IS GIVING US CHILD OF CURRENT PARENT
                //AND WE ARE IN OUR RELATIONSHIP HIERARCHY. 
                if (currentMethodObj.getReturnType().getName().equalsIgnoreCase(ConstantesMITSeguros.CLASS_SET) &&  nameOfChildClass.startsWith(ConstantesMITSeguros.TRVTSG)) {

                    //GETTING CLASS NAME
                    String className = currentMethodObj.getName().substring(3, currentMethodObj.getName().length() - 1);

                    //COPYING THE NAME TO USE IT FURTHUR
                    String parentClass = parentName;
                    
                    //GETTING ALL CHILDREN BY INVOKING METHOD RETURNING SET
                    Set child = (Set) currentMethodObj.invoke(oldObject, null);
                    
                    //ITERATING THROUGH CHILDRENT
                    Iterator childIterator = child.iterator();
                    int iteratorCounter = 0;
                    while (childIterator.hasNext() && iteratorCounter < child.size()) {

                        iteratorCounter++;

                        //GETTING CURRENT CHILD AND A CREATING COPY OF THAT CHILD
                        Object currentChild = childIterator.next();
                        Object copyOfChild = currentChild.getClass().newInstance();
                        Class childClassType = currentChild.getClass();

                        //GETTING STATUS OF CURRENT OBJECT THROGH METHOD RETURNING STATUS OF THE RECORD
                        //TO SET THE RECORD ACTIVE FLAG AS TRUE OR FALSE
                        BigDecimal inactivo = (BigDecimal) (childClassType.getMethod(ConstantesMITSeguros.GET_INACTIVO, new Class[] {}).invoke(currentChild, new Object[] {}));
                        BigDecimal inactivoCode = new BigDecimal(0);

                        //IF THE RECORD IS AVTIVE
                        if (inactivo.equals(inactivoCode)) {
                            
                            //COPY OBJECT
                            this.copyObject(currentChild, copyOfChild);

                            //INVOKE INACTIVO METHOD FOR CURRENT CHILD
                            childClassType.getMethod(ConstantesMITSeguros.SET_INACTIVO, new Class[] { BigDecimal.class }).invoke(currentChild, new Object[] { new BigDecimal(1) });

                            //UPDATE OLD OBJECT
                            insertarGenericoDAO.txUpdateGenerico(currentChild);

                            //NOW SET PARENT FOR CURRENT CHILD AS NEW_OBJ
                            String methodToCall = ConstantesMITSeguros.SET + parentClass;
                            childClassType.getMethod(methodToCall, new Class[] { Class.forName(packagePath + ConstantesMITSeguros.DOT + parentClass) }).invoke(copyOfChild, new Object[] { newObject });

                            //NOW INSERT NEW OBJECT
                            insertarGenericoDAO.txInsertarGenerico(copyOfChild);

                            //DO THE PROCEDURE IN RECURSIVE MANNER
                            this.txRecursiveInsertUpdateChildObjects(copyOfChild, copyOfChild, packagePath, className);
                        }

                    }

                }

            }
            logger.info("End of txGetChildObjects in InsertarGenericoServiceImpl");
        } catch (Exception e) {

            logger.error("Error in txGetChildObjects in InsertarGenericoServiceImpl " + e.getMessage());

            throw new BusinessException("Exception thrown from txGetChildObjects in InsertarGenericoServiceImpl " + e.getMessage());
        }





/**
*  ===============================================================
*  SNIPLET FOR COPYING HIBERNATE OBJECTS USING REFLECTION API
*  ===============================================================
**/



       //GETTING ALL METHODS OF OLD_OBJ REPRESNTING DATABASE TABLE ROW
        Method[] allMethods = oldObject.getClass().getDeclaredMethods();
        logger.info("start of copyObject method in InsertarGenericoServiceImpl ");
        
        //LOOP THROUGH THE METHODS
        for (int methodCntr = 0; (methodCntr < allMethods.length); methodCntr++) {
            
            //FIND OUT IF THEY ARE GETTER METHODS
            if (allMethods[methodCntr].getName().substring(0, 3).equalsIgnoreCase("get")) {
                try {

                    //TAKE CURRENT METHOD
                    Method currentMethod = allMethods[methodCntr];
                    
                    //GETTING SETTER METHOD RELAVANT TO CURRENT GETTER METHOD
                    String methodToCall = ConstantesMITSeguros.SET+ currentMethod.getName().substring(3, currentMethod.getName().length());

                    //FINDING OUT CLASS FOR NEW_OBJ
                    Class newObjectClass = newObject.getClass();

                    //INVOKING GETTER METHOD ON OLD_OBJ
                    Object returnResult = currentMethod.invoke(oldObject, new Object[] {});
                    
                    //INVOKING SETTER METHOD ON NEW_OBJ AND SET THE VALUES WHICH WE RECEIVED USING GETTER OF OLD_OBJ
                    newObjectClass.getMethod(methodToCall, new Class[] { currentMethod.getReturnType() }).invoke(newObject, new Object[] { returnResult });

                    //IF THE RETURN TYPE IS SET i.e MANY SIDE OF A RELATION
                    if (currentMethod.getReturnType().getName().equalsIgnoreCase(ConstantesMITSeguros.CLASS_SET)) {

                        Class oldObjectClass = oldObject.getClass();

                        oldObjectClass.getMethod(methodToCall, new Class[] { currentMethod.getReturnType() }).invoke(oldObject, new Object[] { null });
                    }

                } catch (Exception e) {

                    logger.error("Error in copyObject in InsertarGenericoServiceImpl " + e.getMessage());

                    throw new BusinessException("Exception thrown from copyObject in InsertarGenericoServiceImpl " + e.getMessage());

                }
            }
        }
     

Leave a Reply

Newer Post Older Post
Subscribe to: Post Comments ( Atom )
  • Popular
  • Recent
  • Archives
Powered by Blogger.
 
 
 
© 2011 Java Programs and Examples with Output | Designs by Web2feel & Fab Themes

Bloggerized by DheTemplate.com - Main Blogger