Grails

Plugin resources not included in WAR

Details

  • Type: Bug Bug
  • Status: Closed Closed
  • Priority: Critical Critical
  • Resolution: Fixed
  • Affects Version/s: 1.1
  • Fix Version/s: 1.1.1
  • Component/s: None
  • Labels:
    None
  • Environment:
    Grails 1.1

Description

It seems that only the files under "grails-app/views" of a plugin will be included in a WAR file.

I created a fresh "testapp" grails 1.1 application and it contains a newly created plugin "testplugin".
"testplugin" has files in grails-app/conf and grails-app/i18n. But those won't be included in the generated WAR file, only grails-app/views.

Activity

Hide
Markus Kramer added a comment - - edited

Found the following code in _GrailsWar.groovy:

target(warPlugins:"Includes the plugins in the WAR") {
    ant.sequential {
        def pluginInfos = GrailsPluginUtils.getSupportedPluginInfos(pluginsHome)
        if(pluginInfos) {
            for(PluginInfo info in pluginInfos) {
                // Note that with in-place plugins, the name of the plugin's
                // directory may not match the "<name>-<version>" form that
                // should be used in the WAR file.
                def targetPluginDir = "${stagingDir}/WEB-INF/plugins/${info.name}-${info.version}"
                mkdir(dir:targetPluginDir)
                copy(todir:targetPluginDir, failonerror:true) {
                    def pluginBase = info.pluginDir.file
                    fileset(dir:pluginBase.absolutePath) {
                        include(name:"plugin.xml")
                        include(name:"grails-app/views/**")
                        include(name:"${pluginBase.name}/grails-app/i18n/**")
                    }
                }
            }
        }
    }
}

I changed the lines at the end to:

fileset(dir:pluginBase.absolutePath) {
    include(name:"plugin.xml")
    include(name:"grails-app/**")
}

Now all necessary files from a plugin will be included in the WAR.
I hope you include this fix in your next release.

Show
Markus Kramer added a comment - - edited Found the following code in _GrailsWar.groovy:
target(warPlugins:"Includes the plugins in the WAR") {
    ant.sequential {
        def pluginInfos = GrailsPluginUtils.getSupportedPluginInfos(pluginsHome)
        if(pluginInfos) {
            for(PluginInfo info in pluginInfos) {
                // Note that with in-place plugins, the name of the plugin's
                // directory may not match the "<name>-<version>" form that
                // should be used in the WAR file.
                def targetPluginDir = "${stagingDir}/WEB-INF/plugins/${info.name}-${info.version}"
                mkdir(dir:targetPluginDir)
                copy(todir:targetPluginDir, failonerror:true) {
                    def pluginBase = info.pluginDir.file
                    fileset(dir:pluginBase.absolutePath) {
                        include(name:"plugin.xml")
                        include(name:"grails-app/views/**")
                        include(name:"${pluginBase.name}/grails-app/i18n/**")
                    }
                }
            }
        }
    }
}
I changed the lines at the end to:
fileset(dir:pluginBase.absolutePath) {
    include(name:"plugin.xml")
    include(name:"grails-app/**")
}
Now all necessary files from a plugin will be included in the WAR. I hope you include this fix in your next release.
Hide
Graeme Rocher added a comment -

This will duplicate all of the source code into the WAR as well when these are compiled into .class files and not needed. Hence the change is not appropriate

Show
Graeme Rocher added a comment - This will duplicate all of the source code into the WAR as well when these are compiled into .class files and not needed. Hence the change is not appropriate
Hide
Markus Kramer added a comment - - edited

Okay I see. An improved version would be:

fileset(dir:pluginBase.absolutePath) {
    include(name:"plugin.xml")
    include(name:"grails-app/**")
    exclude(name:"grails-app/**/*.groovy")
}

This might result in some empty directories in the WAR file. But all necessary resources would be included.

Show
Markus Kramer added a comment - - edited Okay I see. An improved version would be:
fileset(dir:pluginBase.absolutePath) {
    include(name:"plugin.xml")
    include(name:"grails-app/**")
    exclude(name:"grails-app/**/*.groovy")
}
This might result in some empty directories in the WAR file. But all necessary resources would be included.
Hide
Will Droste added a comment -

I'd like to re-open this bug. When resources are copied from the 'conf' directory they are no longer at the 'default' package level rather they are at the 'plugin' level. From the plugin developer side I need to go through a search path.. The files at the 'conf' directory should be at the default package much like the classes that are in the directory (Filters,Mappings etc..)..

Show
Will Droste added a comment - I'd like to re-open this bug. When resources are copied from the 'conf' directory they are no longer at the 'default' package level rather they are at the 'plugin' level. From the plugin developer side I need to go through a search path.. The files at the 'conf' directory should be at the default package much like the classes that are in the directory (Filters,Mappings etc..)..
Hide
Graeme Rocher added a comment -

Hmm I'm not sure I follow, can you be more specific about where you want the files to go?

Show
Graeme Rocher added a comment - Hmm I'm not sure I follow, can you be more specific about where you want the files to go?
Hide
Will Droste added a comment -

Currently most plugin developers copy the resources that are in 'conf' into the application 'conf' during install time. Take the jbpm plugin copies the hibernate.cfg.xml to the app's conf/hibernate directory (granted it probably should just so the app can verify/modify it).. My company has created a sort of uber plugin that has default/required resources (workflow definitions, report definitions etc..).. Its interesting to note that all of the files are available during development of the plugin. Whether direct usage (test-app or run-app) or if the test application has a BuildConfig.groovy entry pointing at the plugin. So this actually different once a WAR is created. In order to workaround this difference we copy an '_Events.groovy' to the app and use the 'eventCreateWarStart' to copy the resources in.. The reason being we don't want people to modify the resources and therefore we're not going to make it that easy, plus we want them to get upgrades more seamlessly. There is also an issue w/ 3rd party libraries that can not take a search path during initialization.. Otherwise we would have fixed it there..

Summary:
In development of a plugin the resources in 'conf' are available at the default package level in a WAR they are not. We'd like for this to be consistent such that the resources are available in the WAR at the default package.

Show
Will Droste added a comment - Currently most plugin developers copy the resources that are in 'conf' into the application 'conf' during install time. Take the jbpm plugin copies the hibernate.cfg.xml to the app's conf/hibernate directory (granted it probably should just so the app can verify/modify it).. My company has created a sort of uber plugin that has default/required resources (workflow definitions, report definitions etc..).. Its interesting to note that all of the files are available during development of the plugin. Whether direct usage (test-app or run-app) or if the test application has a BuildConfig.groovy entry pointing at the plugin. So this actually different once a WAR is created. In order to workaround this difference we copy an '_Events.groovy' to the app and use the 'eventCreateWarStart' to copy the resources in.. The reason being we don't want people to modify the resources and therefore we're not going to make it that easy, plus we want them to get upgrades more seamlessly. There is also an issue w/ 3rd party libraries that can not take a search path during initialization.. Otherwise we would have fixed it there.. Summary: In development of a plugin the resources in 'conf' are available at the default package level in a WAR they are not. We'd like for this to be consistent such that the resources are available in the WAR at the default package.
Hide
Will Droste added a comment -

Sorry didn't really answer the question directly we'd like the files to go into the 'classes' directory. Granted there is a danger of duplicates from other plugin. However that is already the case w/ duplicate class names in the 'conf' directory so I hope most are aware and make sufficiently unique names..

Show
Will Droste added a comment - Sorry didn't really answer the question directly we'd like the files to go into the 'classes' directory. Granted there is a danger of duplicates from other plugin. However that is already the case w/ duplicate class names in the 'conf' directory so I hope most are aware and make sufficiently unique names..
Hide
Graeme Rocher added a comment -

I'm concerned doing this would break a lot of existing applications that expect the plugin to resources to be where they are now.

Show
Graeme Rocher added a comment - I'm concerned doing this would break a lot of existing applications that expect the plugin to resources to be where they are now.
Hide
Will Droste added a comment -

That's a reasonable argument. We'll find some way through build events..

Show
Will Droste added a comment - That's a reasonable argument. We'll find some way through build events..

People

Vote (1)
Watch (5)

Dates

  • Created:
    Updated:
    Resolved: