I have a rather monolithic Grails 2 application that I am attempting to upgrade to Grails 3 (specifically 3.2.7) and refactor into a set of plugins - the current app uses various services on Amazon AWS, I want to refactor it so I can more easily switch to Microsoft Azure or OpenStack.
At present, the big app uses various plugins including Spring Security UI, and the app overrides some of the GSP views from the plugin with its own. In the refactored scenario I have the main app (which will implement the AWS-specific bits), depending on a "core" plugin (with the cloud-agnostic functions) which in turn depends on spring-security-ui. The problem I'm having is that when I put my custom auth.gsp view in the "core" plugin rather than in the top-level app, it no longer overrides the s2ui version of the same view. If I copy the "core" plugin's auth.gsp to the same location in the top-level app, it overrides correctly.
In general, if I have app depends-on plugin1 depends-on plugin2, is there a way to ensure that when I run the app, views provided by plugin1 take precedence over the same views provided by plugin2?
The core plugin will need to specify it should be loaded after spring security ui. You can do that with:
def loadAfter = ['springSecurityUi']
This is documented here: http://docs.grails.org/latest/guide/plugins.html#understandingPluginLoadOrder
Related
I'm playing around the idea of a very huge vaadin application, which consists of a skeleton (providing the ui framework) and hundreds of functional units (providing the specific vaadin views).
The main architectural point is to let the skeleton be agnostic about the functional units, so not a single java dependency to a functional unit should be injected into skeleton. Every single functional unit has to be in it's own distinct JAR.
The vaadin container is started by the skeleton-module. It is perfectly possible to build a navigation with all the necessary routes to the functional units (/routeToView001.../routeToView999) without having further details about them.
However, I don't see, how the started vaadin spring boot container would load the java classes from the independent JARs when navigation occurs in browser. Practical attempts failed. Any ideas?
The Spring Boot integration is by default looking for #Route classes within the Java package that contains the #SpringBootApplication class. This can be further configured by passing package names to the #EnableVaadin annotation.
I haven't tested this in practice, but it might be possible to have a multiple #EnableVaadin annotations so that there would be one in each module and through that also provide multiple locations to look for #Route classes from. In that case, the #EnableVaadin class in each module would also have to register itself in the same way as any other #Configuration by using the regular Spring Boot autoconfiguration mechanism.
Another alternative is that you register route classes manually to the application's route registry (accessed using ApplicationRouteRegistry.getInstance(new VaadinServletContext(servletContext))). In that case, you might still need to have at least a dummy #Route in the base module since Vaadin might not automatically enable itself in a Spring Boot environment unless at least one #Route class is discovered in the regular way.
I have a fairly complicated grails plugin dependency structure within my project and I am having problems overriding classes from the security plugin.
My structure is a little something like this:
Web App
|_ Audit Plugin
|_ Spring Security Core Plugin
|_ Security Wrapper Plugin
|_ Audit Plugin
|_ Spring Security Core Plugin
The reason it is like this is audit is shared between some apps which have the security wrapper, and some what don't, which is why it pulls in Security-Core (it needs at least the ability to get the current principal).
Similarly the wrapper is shared between multiple web apps therefore we put it in a plugin. My problem comes after upgrading Spring-Security-Core to version 2.
My wrapper has a customer auth.gsp and LoginController.groovy. In the older version of security this was fine, as the plugin templated those and made them available in the source of the installing plugin.
However now these files are internal to the plugin, and although I know you can override them within the main app, when trying to override them within another plugin I get some bizarre results.
The Spring-Security-Core version of the login page always overrides my custom login page. I cannot get mine to take precedence.
The second problem is that the LoginController.groovy from the Spring-Security-Core plugin sometimes takes precedence over my one from the wrapper. It seems almost random between builds as to which one will be in use.
Is there any correct way to go about making sure my views and controllers take precedence?
OK playing around with things I found a solution that seems to work for me:
Firstly I couldn't change the order in which the plugins load because the security wrapper does a lot with spring beans and it has to load after the core plugin for this to work. So after a bit of digging in the (DefaultSecurityConfig.groovy) I noticed that you can set the following properties:
grails.plugin.springsecurity.failureHandler.defaultFailureUrl = '/login/authfail? login_error=1'
grails.plugin.springsecurity.failureHandler.ajaxAuthFailUrl = '/login/authfail?ajax=true'
grails.plugin.springsecurity.auth.loginFormUrl = '/login/auth'
So I created a custom controller and login page which have a different name to the ones use in the core plugin and changed these properties to point to my locations.
To neaten this up, in the UrlMappings for the wrapper (named: SecWrapperUrlMappings) I put a mapping from /login/** to /seclogin/**.
Make sure that these new locations aren't locked down so that people can access them and that seems to work well. I now reliable know, whichever order they load in my login page and login controller are used.
In Grails-4.013 and spring-security-core-4.0.4, I did the following trick.
In my custom plugin instead of LoginController and LogoutController I named them as SigninController and SignoutController respectively. And in UrlMappings.groovy of App mapped them like..
static mappings = {
"/login/$action?"(controller: "signin")
"/logout/$action?"(controller: "signout")
....
....
}
I have a modular application where in one module I have spring security ui(s2-ui) setup, with some controllers and views overridden.
In the other module I'm having troubles because grails is not using the spring security ui(s2-ui) configured in the first module but rather a fresh s2-ui installed as a result of the dependency of the first module on s2-ui.
For example, I've customized the register controller and views but this is not being reflected in the 2nd module.
FYI I've set the loadsAfter property to tell my plugin to load after the s2-ui plugin.
If the overridden views and controllers are local to the first plugin, then you need to copy them to the second plugin as well. The second plugin is inheriting the base plugin files from your home folder.
When you start a new project (whether it's personal or professional) what do you have at hand to quickly start developing the project?
For example, when I start a new project at work, I have the following already setup from a custom sandbox:
Two different authentication classes, LDAP and CAS which I can change via app.yml
Custom form widgets which I use across most applications
Capistrano deployment script for deploying the project to staging or production servers.
A mail template class which uses an XML file for the templates to send emails
Mail server, ldap etc. settings all configured.
Bunch of icons and the same CSS (which with some exceptions is always the same for each project)
custom error pages, layouts, login layout etc.
static pages such as about, contact us etc.
Useful plugins such as sfFormExtraPlugin, twig etc.
jquery and jQuery UI libraries
Basic local ACL and translation model classes and some other default models.
Tasks - send email task and build translations.
custom tools class for doing some custom stuff
custom factories and some default routes
helpers which I will most probably use are enabled by default (i18n, partial etc.)
And some other things :-)
I'm just wondering what you do to make your development quicker and more efficient when starting a new project. Hopefully I'll learn some new things from what you do.
Thanks folks!
Great question and great list. Here's some more:
As a general practice, whenever we develop a feature that could be used across projects, we develop it as a plugin so it can be easily dropped into other projects.
Custom form formatter that uses our own widget/validators in place of the default Symfony ones.
Custom mailer with support for sending processing templates as emails and better HTML email support.
Plugin for minimizing/combining CSS and JS assets.
Symlink from web/sf to lib/vendor/symfony/data/web. Better than an alias in apache.
Custom admin generator templates.
Quick setup script that takes commandline options or read a config file to create full local dev env (init the project, setup a vhost, modify etc/hosts, import to svn, create svn externals for Symfony and key plugins like sfDoctrineGuard)
Custom Project skeleton
Custom Javascript helper based on Apostrophes new a_js_*() helper functions
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