How to nest plugin URLs? - grails

I would like to create a "Shell" of a Grails project that hosts functionality in plugins, with the URLs segregated by plugin name.
So the URLs for a Blog plugin used in the Shell project might look like: /shell/blog/viewBlogPost
But what I'm actually seeing is all of the plugins' controllers behave as if they are part of the shell project itself: /shell/viewBlogPost
Is there any way to declare that the Blog plugin's controllers be accessible only under a /blog path in the URL?

It seems like Grails plugins are not able to do this. The problem is that they lack encapsulation and composability, leading to artifact conflicts:
URL routing from plugins is simply merged together and cannot be nested
Controllers are not namespaced
Services are not namespaced
I opened an issue: GRAILS-9300
The Grails team has tentative plans to address this in 2.2, by using the plugin name as a namespace for artifacts.

Yes, your plugins can register URL mappings just like the rest of your "shell" application can.

You can declare UrlMappings in a plugin by creating a file with a name ending in UrlMappings in your plugin (e.g. BlogPluginUrlMappings.groovy) and these will get merged into the main application's UrlMappings. You can setup mappings starting with /blog/ to route to your plugin's controllers.

Related

recover grails url mappings

I have been handed a deployed grails app as a .war, after installing it, I later unpacked it to view sources and configs.
Is there anyway to find out the UrlMappings that were originally in the source? They don't seem to be anywhere in the war.
I have no access to the source, or app authors, and the app's load page is a login page. There's an h2 database, which I explored but found that it has no tables in the public schema.
Then I also found some views in ./WEB-INF/grails-app/views/connection, such as create.gsp and editConnection.gsp and also a JDBDriver folder with create.gsp.
My thinking is that there's a url to setup this app, but I can't figure out what it is.
Grails url mappings are declared in a file called UrlMappings.groovy so you might try decompiling this class. UrlMappings typically make heavy use of Closures so you will likely have a bunch of related classes to decompile as well.

How does a Grails plugin add its own URLMappings?

I am creating a Grails plugin and I would like for it to add its own UrlMappings. The UrlMappings.groovy file in the plugin source is ignored by the application using the plugin, so where should these be defined?
See http://grails.org/doc/latest/guide/single.html#plugins: Notes on excluded Artefacts
In addition, although UrlMappings.groovy is excluded
you are allowed to include a UrlMappings definition with
a different name, such as MyPluginUrlMappings.groovy.

What is a Grails Plugin? What does it mean to Install a Plugin?

I used Grails recently, and added Grails plugin for JQuery, but I don't think it did anything more than just copy some jQuery files over.
So far, I have seen info only on 'how to install and use' plugins...but I can't find anything that describes the concept of a plugin.
Can somebody please tell me, what is a Grails Plugin? And what does it mean to 'Install' a plugin?
A Grails plugin is (or should be) a self-contained bundle of functionality that can be installed into a Grails application. When a Grails plugin is installed, it can do any of the following:
define additional Spring beans
modify the generated web.xml
add new methods to the application's artefacts (controllers, domain classes, services, etc.)
provide new tag libraries
make additional resources and classes available to the application
provide new Grails commands
For example, when you install the JQuery plugin
the JQuery JavaScript files are added to the application
a new Grails tag <jq:jquery> is added to the application
a new Grails command grails install-plugin jquery is added to the application
When you install a Grails plugin, that plugin's functionality is made available to the installing application. However, the plugin itself is not actually copied into the application, only the plugin name and version is added to the application's application.properties file. The plugin itself is downloaded to $HOME/.grails and the application loads it from there.
The structure of a Grails plugin project is identical to that of a Grails application, with the exception of a configuration file (known as a plugin descriptor) that is included in a plugin's root directory.
Well, a Grails plugin is some piece of software that extends the frameworks funcionalities in some manner. Generally, installing a plugin in Grails means copying it to your Grails folder, so projects can refer to it and Grails will know where to find it.
Grails plugins have this folder structure:
grails-app
controllers
domain
taglib
service
etc
lib
src
java
groovy
web-app
js
css
So anything it has there will also be available to the application that uses it. For example, the Searchable plugin has a service class which you can use to perform advanced searchs in your own domain classes .
The jQuery plugin you mentioned has the jQuery .js file, and a tag to include that file.
For information on creating plugins, see http://grails.org/doc/latest/guide/12.%20Plug-ins.html
A plugin is just a set of functionality around a desired purpose. So the Spring Security plugin provides a way to lock down your app, assign roles to users, restrict access, whatever. The Searchable plugin allows you to integrate advanced searching into your app. There are lots of plugins
The point is to provide useful functionality so that you don't have to implement hard things yourself. Someone did something useful, and they wanted to contribute back to the community, so they organized their functionality and made it available.
A plugin is code and configuration, like any functionality you would implement yourself.
There is some documentation here: http://grails.org/doc/latest/ref/Plug-ins/Usage.html

How does Grails resolve Controller name conflicts?

What is the recommended approach when an application Controller name conflicts with the name of a plugin's Controller?
I've seen these Grails JIRAs:
GRAILS-4240
GRAILS-1243
...and Burt Beckwith's replies to these two threads imply that the only recourse is to rename one of the Controllers (presumably the application Controller since hacking plugin code is not desirable)
How to use the package name to differentiate between classes in grails?
How to extend/override controller actions of plugins?
However, Burt's own spring-security-ui plugin advocates the exact approach of naming an application Controller the same as a plugin Controller - see spring-security-ui docs.
This approach actually seems to work in both development mode (grails run-app) and when the app is deployed as a WAR. So can this functionality be depended on? If so, what is the Controller conflict resolution rule? The grails docs do not make any mention of it. Perhasps Burt can share his insight?
Having a "plugin" architecture like grails' without even a basic namespacing facility to handle conflicts like this seems pretty broken to me...
The problem is that while you can use packages for any artifact, the convention for controllers is to remove the package and "Controller" to create URLs, e.g. PersonController -> /appname/person/action_name. So in effect everything gets flattened.
In 1.2 and more so in 1.3 things were changed so plugins are compiled separately from application code (and are compiled first) and this gives you the opportunity to replace a plugin artifact with the application's version. Since you shouldn't edit plugin code, this gives you the flexibility to extend or replace a plugin artifact just by using the same name.
I tend to use UrlMappings to get around stuff like this when there are two similarly named controllers. For example say you have an admin UserController that allows low-level CRUD actions and a regular UserController that users work with. I'd name the admin controller AdminUserController and map it to /admin/user/* and leave UserController as is. The admin GSPs will be in views/adminUser and the others will be in views/user so there's no conflict there. This has the added benefit of being able to easily secure - map /admin/** -> ROLE_ADMIN. The conventions are convenient, but this is a simple configuration step that solves this issue for me.
The good news is that GRAILS-1243 will definitely be implemented in 2.0 and possibly in 1.4. And the plugin that Kim Betti references in the comments of GRAILS-1243 looks interesting.

Is it possible to add Grails MVC classes at deployment time?

I'm writing a Grails app which I'd like 3rd parties to augment at runtime. Ideally they would be able to add a JAR/WAR to the webapp directory which contains new domain, controller and service classes, new views, and other content.
Is there a simple way to do this within grails? Would it be simplest to create a startup script which copies the new classes etc. into the relevant directories and then updates grails.xml and web.xml?
You will be able to do this in version 2 of grails in which plugins will be also OSGI plugins http://jira.codehaus.org/browse/GRAILS/fixforversion/15421
It seems that the Grails plugins will actually fit quite well for this: http://www.grails.org/Understanding+Plugins
A plugin can do just about anything... One thing a plugin cannot do though is modify the web-app/WEB-INF/web.xml or web-app/WEB-INF/applicationContext.xml files. A plugin can participate in web.xml generation, but not modify the file or provide a replacement. A plugin can NEVER change the applicationContext.xml file, but can provide runtime bean definitions

Resources