0 Replies Latest reply on May 22, 2009 11:54 PM by cjalmeida

    Validating queries against model

    cjalmeida

      Since there's no Criteria API for JPA, I've created a simple helper class that scans my sources for queries created using EntityManager.createQuery and prepares them against my entityManager instance. I use that for unit testing - it assures me that no refactoring breakes them.


      The entityManager instance is acquired through the documented integration testing way.


      Below is the code for the validator:


      package com.pf;


      import java.io.BufferedReader;
      import java.io.File;
      import java.io.FileReader;
      import java.io.StreamTokenizer;
      import java.util.HashMap;
      import java.util.LinkedList;
      import java.util.List;
      import java.util.Map;
      
      import javax.persistence.EntityManager;
      
      
      public class QueryValidator {
      
      
           private EntityManager entityManager;
           private List<File> files = new LinkedList<File>();
           
           public static void main(String[] args) throws Exception {
                QueryValidator qv = new QueryValidator(new String[] {"src/action", "src/model"});
                qv.run();
           }
           
           public QueryValidator() {
                
           }
           
           public QueryValidator(String[] srcs) {
                for (String src : srcs) {
                     File srcdir = new File(src);
                     findRecursive(srcdir,files);
                }
           }
           
           private void findRecursive(File dir, List<File> col) {
                for (File child : dir.listFiles()) {
                     if (!child.isDirectory() && child.getName().endsWith(".java")){
                          col.add(child);
                          System.out.println(child.getAbsolutePath());
                     }else if (child.isDirectory())
                          findRecursive(child, col);
                }
                
           }
      
           public void run() throws Exception {
                Map<String, File> queries = new HashMap<String, File>();
                
                for (File file : files){
                     for(String q : findQueries(file))
                          queries.put(q, file);
                }
                
                for(String query : queries.keySet()) {
                     try {
                          entityManager.createQuery(query);
                     } catch (Exception e) {
                          throw new Exception("Error on file '" + queries.get(query) + "' for query: " + query,e);
                     }
                }
                
           }
           
           private List<String> findQueries(File file) throws Exception {
                StreamTokenizer tokenizer = new StreamTokenizer(new FileReader(file));
                tokenizer.slashSlashComments(true);
                tokenizer.slashStarComments(true);
                
                int ttype;
                
                String queryMethod="createQuery";
                
                boolean queryFound = false;
                StringBuffer queryBuf = null;
                
                List<String> queries = new LinkedList<String>();
                
                while((ttype = tokenizer.nextToken()) != StreamTokenizer.TT_EOF) {
                     // We found a method
                     if(tokenizer.ttype == -3 && tokenizer.sval.contains(queryMethod)) {
                          queryFound = true;
                          queryBuf = new StringBuffer();
                          
                     // Query part     
                     } else if (queryFound && tokenizer.ttype == 34) {
                          queryBuf.append(tokenizer.sval);
      
                     // Method closed - we found a ")"
                     } else if (queryFound && tokenizer.ttype == 41) {
                          String q = queryBuf.toString();
                          if (!q.trim().equals(""))
                               queries.add(q);
                          queryFound=false;
                     }
                     
                }
                
                return queries;
                
           }
           private String read(File f) throws Exception {
                BufferedReader reader = new BufferedReader(new FileReader(f));
                String line;
                StringBuffer buff = new StringBuffer();
                while ((line = reader.readLine()) != null) 
                     buff.append(line);
                
                return buff.toString();
           }
      
           public EntityManager getEntityManager() {
                return entityManager;
           }
      
           public void setEntityManager(EntityManager entityManager) {
                this.entityManager = entityManager;
           }
      
           public List<File> getFiles() {
                return files;
           }
      
           public void setFiles(List<File> files) {
                this.files = files;
           }
      
      }
      



      and that's the a sample usage in a SeamTest class:



      import javax.persistence.EntityManager;
      
      import org.jboss.seam.mock.SeamTest;
      import org.testng.annotations.Test;
      
      public class QueryValidationTest extends SeamTest{
      
           @Test
           public void testQueries() throws Exception {
                new ComponentTest() {
                     @Override
                     protected void testComponents() throws Exception {
                          QueryValidator qv = new QueryValidator(new String[] {"src/action", "src/model"});
                          qv.setEntityManager((EntityManager) getValue("#{entityManager}"));
                          qv.run();
                     }
                }.run();
           }
      }