Announcement Announcement Module
Collapse
No announcement yet.
Grails script will not run - NoClassDefError Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Grails script will not run - NoClassDefError

    I have a script I have written

    Code:
    import org.codehaus.groovy.grails.commons.GrailsClassUtils as GCU
    import groovy.text.SimpleTemplateEngine
    import org.codehaus.groovy.grails.commons.spring.GrailsRuntimeConfigurator;
    import org.codehaus.groovy.grails.scaffolding.*
    import org.springframework.mock.web.MockServletContext
    import org.springframework.core.io.Resource;
    
    Ant.property(environment:"env") 
    grailsHome = Ant.project.properties."environment.GRAILS_HOME"
    
    includeTargets << grailsScript("Init")
    includeTargets << new File ( "${grailsHome}/scripts/Package.groovy" )
    
    target(main: "Generate controller/views for a single domain class") {
        depends( checkVersion, packageApp )
        typeName = "Domain Class"
        
        println "General usage : grails single-domain-generator <domainclassname> [generateviews(boolean value)] [generatecontroller(boolean value)]"
        println "For example : grails single-domain-generator Newclass true true to generate all views and controllers for domain class Newclass"
        parseArguments()
        def targetClass = argsMap?.params[0]
        def generateViews = (!argsMap?.params[1] || argsMap?.params[1]?.equals("")) ? true : argsMap?.params[1]
        def generateController = (!argsMap?.params[2] || argsMap?.params[2]?.equals("")) ? true : argsMap?.params[2]
        
        ant.echo "Your request : grails single-domain-generator ${targetClass} ${generateViews} ${generateController}"
        
        rootLoader.addURL(classesDir.toURL())
        def beans = new grails.spring.WebBeanBuilder().beans {
            resourceHolder(org.codehaus.groovy.grails.commons.spring.GrailsResourceHolder) {
                this.resources = "file:${basedir}/grails-app/domain/**/*.groovy"
            }
            grailsResourceLoader(org.codehaus.groovy.grails.commons.GrailsResourceLoaderFactoryBean) {
                grailsResourceHolder = resourceHolder
            }
            def pluginResources = [] as Resource[]
            if(new File("${basedir}/plugins/*/plugin.xml").exists()) {
                pluginResources = "file:${basedir}/plugins/*/plugin.xml"
            }
    
            pluginMetaManager(org.codehaus.groovy.grails.plugins.DefaultPluginMetaManager, pluginResources) 
            grailsApplication(org.codehaus.groovy.grails.commons.DefaultGrailsApplication.class, ref("grailsResourceLoader"))
        }
                                                        
        appCtx = beans.createApplicationContext()     
        appCtx.servletContext = new MockServletContext()
        grailsApp = appCtx.grailsApplication 
    
        grailsApp.initialise()
        def domainClasses = grailsApp.domainClasses
    
        if(!domainClasses) {
            println "Domain classes not found in grails-app/domain, trying hibernate mapped classes..."     
            try {
                def config = new GrailsRuntimeConfigurator(grailsApp, appCtx) 
                appCtx = config.configure(appCtx.servletContext)                
            } 
            catch(Exception e) {
                println e.message
                e.printStackTrace()
            }
            domainClasses = grailsApp.domainClasses
        }
        
        //change the values of domain classes : THIS IS THE CRITICAL STEP
        echo "domainclasses contains :  ${domainClasses}"
        
        def sublist = []
        sublist << domainClasses.find{it.shortName.equals(targetClass)}
        
        echo "sublist now set to :  ${sublist}"
        
        
        //generate all our strings
        //generateGeneralStrings()
        
        if(sublist) {
            def generator = new DefaultGrailsTemplateGenerator()
            sublist.each { domainClass ->
                if(generateViews) {
                    event("StatusUpdate", ["Generating views for domain class ${domainClass.fullName}"])                
                    generator.generateViews(domainClass,".")
                    
                    //generate strings
                    //generateDomainClassStrings(domainClass.fullName)
                }                                                                                     
                if(generateController) {
                    event("StatusUpdate", ["Generating controller for domain class ${domainClass.fullName}"])     
                    generator.generateController(domainClass,".")             
                }
                event("StatusUpdate", ["Finished generation for domain class ${domainClass.fullName}"])            
            }
            event("StatusFinal", ["Finished generation for domain classes"])
        }
        else {
            event("StatusFinal", ["No domain class found"])
        }
    }
    
    setDefaultTarget(main)
    This script is supposed to be very similar to the GenerateAllForDomain script that generates controllers and views. Except..i want to just generate for one class..

    Expected parameters are <domain class name> <boolean> <boolean> each of
    the bools are for generate controller and generate view respectively.

    The script gets as far as line 48 : grailsApp.initialise()

    at which point i get this dump...

    Code:
    Error executing script SingleDomainGenerator: Lcom/eventmanager/domain/Event;
    java.lang.NoClassDefFoundError: Lcom/eventmanager/domain/Event;
    	at java.lang.Class.getDeclaredFields0(Native Method)
    	at java.lang.Class.privateGetDeclaredFields(Class.java:2291)
    	at java.lang.Class.getDeclaredField(Class.java:1880)
    	at SingleDomainGenerator$_run_closure1.doCall(SingleDomainGenerator:48)
    	at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
    	at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
    	at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
    	at gant.Gant.withBuildListeners(Gant.groovy:427)
    	at gant.Gant.this$2$withBuildListeners(Gant.groovy)
    	at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
    	at gant.Gant.dispatch(Gant.groovy:415)
    	at gant.Gant.this$2$dispatch(Gant.groovy)
    	at gant.Gant.invokeMethod(Gant.groovy)
    	at gant.Gant.executeTargets(Gant.groovy:590)
    	at gant.Gant.executeTargets(Gant.groovy:589)
    The script above is the one called : SingleDomainGenerator

    Now ..the class being complained about Event.groovy is actually provided by a plugin I have written. So it is NOT in the domain folder of the project I run this script from.

    It is the only domain class that I have provided from outside my project.

    Is this the reason it is failing ?

    I have tried two things:

    Referencing the plugin in buildConfig.groovy like so ;

    Code:
    grails.plugin.location.eventmanager = "../eventmanager"
    and even commenting that line out and actually installing the plugin in the hopes that it will be available to the application more readily.
    NO dice.

    Btw.. I do NOT copy this Event.groovy domain class into my existing project domain folder when I install plugin.. ie. my InstallScript.groovy is empty.

    Any help would be appreciated...

    thanks

    Deus

  • #2
    First off, generate-controller, generate-views, and generate-all already allow you to generate scaffolding for a single class. Does your script do something the others don't? Second, you should really include the Grails script "_GrailsBootstrap" and depend on the "bootstrap" task.

    Which version of Grails are you using?

    Comment


    • #3
      Originally posted by pledbrook View Post
      First off, generate-controller, generate-views, and generate-all already allow you to generate scaffolding for a single class. Does your script do something the others don't? Second, you should really include the Grails script "_GrailsBootstrap" and depend on the "bootstrap" task.

      Which version of Grails are you using?

      Peter


      Thanks for writing. You are right.. the scripts mentioned do actually do that stuff individually and since the post I have decided to reuse those precise scripts. I even switched to using the _GrailsBootstrap script and using it within my script. The only difference so far as I can tell.. is that I want to control through the arguments, whether or not to generate views and controllers independently.


      First, my grails version is 1.3.4 and I am about to upgrade to 1.3.5 today.

      Second. I have made an additional change. My new script (called SingleDomainGenerator.groovy) is in the scripts directory of an INLINE plugin called minimalist.
      I also changed this call

      Code:
        ...templateGenerator.generateViews(domainClass, '.')
      to use a . rather than basedir

      here is the script:


      Code:
      /*
       * Copyright 2004-2005 the original author or authors.
       *
       * Licensed under the Apache License, Version 2.0 (the "License");
       * you may not use this file except in compliance with the License.
       * You may obtain a copy of the License at
       *
       *      http://www.apache.org/licenses/LICENSE-2.0
       *
       * Unless required by applicable law or agreed to in writing, software
       * distributed under the License is distributed on an "AS IS" BASIS,
       * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       * See the License for the specific language governing permissions and
       * limitations under the License.
       */
      
      import org.codehaus.groovy.grails.scaffolding.*
      import grails.util.GrailsNameUtils
      
      /**
       * Gant script that generates a CRUD controller and matching views for a given domain class
       *
       * @author Graeme Rocher
       *
       * @since 0.4
       */
      includeTargets << grailsScript("_GrailsCreateArtifacts")
      includeTargets << grailsScript("_GrailsGenerate")
      includeTargets << grailsScript("_GrailsInit")
      includeTargets << grailsScript("_GrailsBootstrap")
      
      target(generateForOne: "Generates controllers and views for only one domain class.") {
          depends(parseArguments,packageApp, loadApp)
      
          echo "basedir = ${basedir}"
          
          def name = argsMap["params"][0]
          def generateViews = new Boolean(argsMap["params"][1])
          def generateController = new Boolean(argsMap["params"][2])
          
          echo "name : ${name} | generateviews: ${generateViews} | generate controllers : ${generateController}"
          name = name.indexOf('.') > -1 ? name : GrailsNameUtils.getClassNameRepresentation(name)
          def domainClass = grailsApp.getDomainClass(name)
            
          
          if (!domainClass) {
              println "Domain class not found in grails-app/domain, trying hibernate mapped classes..."
              bootstrap()
              domainClass = grailsApp.getDomainClass(name)
          }
      
          if (domainClass) {
              generateForDomainClass(domainClass)
              event("StatusFinal", ["Finished generation for domain class ${domainClass.fullName}"])
          }
          else {
              event("StatusFinal", ["No domain class found for name ${name}. Please try again and enter a valid domain class name"])
      		exit(1)
          }
      }
      
      target(uberGenerate: "Generates controllers and views for all domain classes.") {
          depends(loadApp)
      
          def domainClasses = grailsApp.domainClasses
      
          if (!domainClasses) {
              println "No domain classes found in grails-app/domain, trying hibernate mapped classes..."
              bootstrap()
              domainClasses = grailsApp.domainClasses
          }
      
          if (domainClasses) {
              domainClasses.each { domainClass -> generateForDomainClass(domainClass) }
              event("StatusFinal", ["Finished generation for domain classes"])
          }
          else {
              event("StatusFinal", ["No domain classes found"])
          }
      }
      
      def generateForDomainClass(domainClass) {
          def templateGenerator = new DefaultGrailsTemplateGenerator()
          //use a resource loader
      
        
          if (generateViews) {
              event("StatusUpdate", ["Generating views for domain class ${domainClass.fullName}"])
              templateGenerator.generateViews(domainClass, '.')
              event("GenerateViewsEnd", [domainClass.fullName])
          }
      
          if (generateController) {
              event("StatusUpdate", ["Generating controller for domain class ${domainClass.fullName}"])
              templateGenerator.generateController(domainClass, '.')
              event("GenerateControllerEnd", [domainClass.fullName])
          }
      }
      
      setDefaultTarget(generateForOne)
      and here is the inlining of my plugins

      Code:
      grails.plugin.location.eventmanager = "../eventmanager"
       grails.plugin.location.minimalist = "../minimalist"

      and it now generates the controllers/views as expected. However the problem is that it is generating the views and controllers using the templates that are provided with Grails scaffolding by default.

      IN the plugin minimalist that I have inlined, I have a the same views and controller file, specially modified for my project.

      How can I get the script above to generate controllers and views using the minimalist controller /view templates rather than the default Grails templates ?

      I know i have to use a resource loader ..but not sure how ...



      thanks

      Comment


      • #4
        You can solve this for static scaffolding by simply changing the 'basedir' property on the template generator:
        Code:
        templateGenerator.baseDir = minimalistPluginDir
        All you then need to do is store the template's in the plugin's src/templates/scaffolding directory.

        Getting dynamic scaffolding working with the plugin's templates would take more work. You might want to consider looking at the Glossy Templates Grails plugin. I haven't investigated it myself, but it sounds like it's doing something similar.

        Comment


        • #5
          Re: SOLVED - Here is the solution

          Kudos Peter.. it worked.

          i added this line

          Code:
          templateGenerator.basedir = minimalistPluginDir
          right after the DefaultGrailsTemplateGenerator is instantiated.



          Here is my final script for those who would like to use it.

          Code:
          Usage : grails <scriptname> <fully.qualified.domain.object.name> <true> <true>
          
           e.g. :  grails single-domain-generator com.noop.Dummy true true
          will generate both controller and view for Dummy using the templates I have in my plugin dir templates folder.

          Code:
          /*
           * Copyright 2004-2005 the original author or authors.
           *
           * Licensed under the Apache License, Version 2.0 (the "License");
           * you may not use this file except in compliance with the License.
           * You may obtain a copy of the License at
           *
           *      http://www.apache.org/licenses/LICENSE-2.0
           *
           * Unless required by applicable law or agreed to in writing, software
           * distributed under the License is distributed on an "AS IS" BASIS,
           * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
           * See the License for the specific language governing permissions and
           * limitations under the License.
           */
          
          import org.codehaus.groovy.grails.scaffolding.*
          import grails.util.GrailsNameUtils
          
          /**
           * Gant script that generates a CRUD controller and matching views for a given domain class
           *
           * @author Graeme Rocher
           *
           * @since 0.4
           */
          includeTargets << grailsScript("_GrailsCreateArtifacts")
          includeTargets << grailsScript("_GrailsGenerate")
          includeTargets << grailsScript("_GrailsInit")
          includeTargets << grailsScript("_GrailsBootstrap")
          
          target(generateForOne: "Generates controllers and views for only one domain class.") {
              depends(parseArguments,packageApp, loadApp)
          
              echo "basedir = ${basedir}"
              
              def name = argsMap["params"][0]
              def generateViews = new Boolean(argsMap["params"][1])
              def generateController = new Boolean(argsMap["params"][2])
              
              echo "name : ${name} | generateviews: ${generateViews} | generate controllers : ${generateController}"
              name = name.indexOf('.') > -1 ? name : GrailsNameUtils.getClassNameRepresentation(name)
              def domainClass = grailsApp.getDomainClass(name)
                
              
              if (!domainClass) {
                  println "Domain class not found in grails-app/domain, trying hibernate mapped classes..."
                  bootstrap()
                  domainClass = grailsApp.getDomainClass(name)
              }
          
              if (domainClass) {
                  generateForDomainClass(domainClass)
                  event("StatusFinal", ["Finished generation for domain class ${domainClass.fullName}"])
              }
              else {
                  event("StatusFinal", ["No domain class found for name ${name}. Please try again and enter a valid domain class name"])
          		exit(1)
              }
          }
          
          target(uberGenerate: "Generates controllers and views for all domain classes.") {
              depends(loadApp)
          
              def domainClasses = grailsApp.domainClasses
          
              if (!domainClasses) {
                  println "No domain classes found in grails-app/domain, trying hibernate mapped classes..."
                  bootstrap()
                  domainClasses = grailsApp.domainClasses
              }
          
              if (domainClasses) {
                  domainClasses.each { domainClass -> generateForDomainClass(domainClass) }
                  event("StatusFinal", ["Finished generation for domain classes"])
              }
              else {
                  event("StatusFinal", ["No domain classes found"])
              }
          }
          
          def generateForDomainClass(domainClass) {
              def templateGenerator = new DefaultGrailsTemplateGenerator()
              templateGenerator.basedir = minimalistPluginDir
              //use a resource loader
          
            
              if (generateViews) {
                  event("StatusUpdate", ["Generating views for domain class ${domainClass.fullName}"])
                  templateGenerator.generateViews(domainClass, '.')
                  event("GenerateViewsEnd", [domainClass.fullName])
              }
          
              if (generateController) {
                  event("StatusUpdate", ["Generating controller for domain class ${domainClass.fullName}"])
                  templateGenerator.generateController(domainClass, '.')
                  event("GenerateControllerEnd", [domainClass.fullName])
              }
          }
          
          setDefaultTarget(generateForOne)
          Enjoy

          Comment

          Working...
          X