Grails URLMappings - grails

I have a plugin that relies on a custom url mapping. When i install the plugin i need to copy the content of the UrlMappings.groovy of the plugin and merge it with the one in the application where the plugin is installed
I would like however to register these url mappings directly into the grails framework without copying the content into the application itself. I don't want the user to change these mappings as they are core to how the plugins works.
Anyone can give me hints where to venture to achieve that.
Thank you
-ken

Create another file in grails-app/config/ with a name ending in UrlMappings.groovy and put the customized mappings in there, for example myUrlMappings.groovy

Seems like i need to interface with UrlMappingsHolderFactoryBean directly to be able to do that. I was hoping that there might be an easier way to do that. The code below is taken from the UrlMappingPlugin itself, the only source that i found to help me solve my problem.
if (application.isUrlMappingsClass(event.source)) {
application.addArtefact(UrlMappingsArtefactHandler.TYPE, event.source)
BeanBuilder beans = beans {
grailsUrlMappingsHolderBean(UrlMappingsHolderFactoryBean) {
grailsApplication = application
}
}
ApplicationContext appCtx = event.ctx
beans.registerBeans(appCtx)
HotSwappableTargetSource ts = appCtx.getBean("urlMappingsTargetSource")
ts.swap appCtx.getBean("grailsUrlMappingsHolderBean")
}

Personally I use Java approach and inject mappings form plugin (I have only one plugin for that).
But generally my approach is following:
1.App
class UrlMappings {
static mappings = DimaURLMappings.getMappings()
}
2.Plugin (called "Dima")
class DimaURLMappings {
static def getMappings(){
return {
//Mappings here
}
}
}
Yes I need to add it manually, but on the other hand it's quite obvious where application gets that mappings, and there are no magic.
I use it in such way because I have few applications that use my plugin. If you have few plugins with mappings you will just need to merge them I think it is not hard. you could also return closure from plugin. But don't forget to change "delegate" in application.

Related

Is that possible to read data from Database into Config.groovy?

I need to to read data from database to be read into Config.groovy.
Is that possible to get data from Database into Config.groovy?
No it is not possible. In the sequence of events when a Grails application is starting up the Config.groovy is processed before the Datasource is made available to the application.
Without knowing what you are trying to accomplish I can't make a suggestion on how else to approach this issue.
Updated (based on comment)
In your comment you explain that you are trying to use the feature switch plugin (which is designed to be run time and not persistent). Looking at the source code for the plugin you should be able to make your own service that will load the settings from the database and toggles/updates the feature switch settings. Here is just a simple sketch/example:
package example
import org.springframework.beans.factory.InitializingBean
class MyExampleService implements InitializingBean {
def grailsApplication
void afterPropertiesSet() {
// here is where you would do whatever you needed to load the settings
grailsApplication.config.features['somefeature'].enabled = true
grailsApplication.config.features['otherfeature'].enabled = false
}
}
That should at least give you an idea.
Alternatively you could just write it all in Bootstrap.groovy which can access the datasource/GORM as well.

What is a good way to provide common methods to all of my services in Grails?

Do you suggest that I use Inheritance, Mixins, ExpandoMetaClass or something else?
If your common methods are largely related to one another, use inheritance from a common class containing them.
If however you have separate concerns and would benefit from grouping them into more than one file, I suggest traits - they have deprecated Groovy's #Mixin annotation.
I'm using them to decorate my controllers and they have worked out very nicely. I have read somewhere that the Grails team is also going to use them to replace the 'magic' metaclass decoration of artefacts like controllers (which is how methods like render are currently provided).. can't find the link, though :(
If you want to add this behavior to services in your application and also those from plugins, use the getServiceClasses() dynamic method in GrailsApplication and add to their metaclasses, e.g.
def grailsApplication
....
grailsApplication.serviceClasses.each { sc ->
sc.clazz.metaClass.foo = { bar -> ... }
}

Wiring Custom HandlerInterceptor for Urls in Plugin?

I'm wanting to convert my filters to a handlerInterceptor in my plugin but am not quite sure how to go about it. It looks like I am supposed to use 'doWithSpring' and map a handler interceptor but I'm not seeing where I map the url's.
To save some discussion, I know filters do this in grails. I just want to convert this code to Java in my plugin and use a HandlerInterceptor to decrease overhead on these calls.
Anyone have any ideas?
In Grails all handler interceptors are registered with the filterInterceptor bean which is a CompositeInterceptor. To add new handler interceptors to this bean use the addHandler method.
The source code for the CompositeInterceptor should give you a better idea of how this is done. Off the top of my head it may look something like this:
def doWithSpring = {
filterInterceptor.addHandler(MyCustomHandlerClass)
}
As far as what URLs your handlers respond to, well, that's up to your implementation inside the handler.
Actually I think I may have solved it. You have to extend the HandlerInterceptor and register the bean...
mvc.'interceptors'() {
mvc.'mapping'('path': '/your/uri/**') {
bean('class': 'CustomInterceptor')
}
}
Here's a link to what I'm talking about (bind Spring HandlerInterceptor only to one controller)
Going to try this out and test it...

Using resources.groovy to define services

I'm using the resources.groovy to declare a service e.g.
aService(com.foo.OrganizationService)
so that I can tie aService to my controllers instead of using organizationService which could change in the future.
I've noticed that the OrganizationService doesn't get treated special like other services "not" declared in the resources.groovy. For example it doesn't get injected with grailsApplication, and likely a hibernateSession etc and other things I've not hit yet....
Now, I know I can manually wire in stuff to my service but I'd rather not have to maintain that...
Is there a special way to declare a service in the resources.groovy so that gets treated like another service that grails loads up?
TIA
The short answer to your question is "no".
Under the covers, Grails services are driven by some intelligent code that is referencing a specific location and expecting certain properties.
Viewing the source code (especially around the ServicesGrailsPlugin.groovy) is a good way to see the "magic" in how these are wired together.
Is there a reason you wouldn't want to use a bonafide Grails service to solve your problem? If you are expecting things like a grailsApplication, it seems like that use is pretty specific to Grails and would be a good candidate for porting over to a "true" Grails service.
Good luck!
So I've come full circle on this. This is a timing problem. Where services haven't been grails initialized yet.
Basically when you use the resources.groovy to do service wiring you run the risk of using a Service that might initialize itself e.g. afterPropertiesSet method or static initializers that use grails services (log, hibernate session, ..) that haven't been injected yet.
So... What I've turned to instead is to create my own BeanBuilder in a BootStrap.groovy file.
BeanBuilder builder = new BeanBuilder(grailsApplication.parentContext)
def bb = builder.beans {
LoginListener(com.foo.LoginListener) {
springSecurityService = ref("springSecurityService")
userService = ref("userService")
}
}
bb.registerBeans(grailsApplication.mainContext)

How to separate interface from implementation in Grails services?

I was wondering if it's possible to create a service interface on Grails and I can't find a proper way of doing it.
This explanation isn't satisfactory, since it seems to mix Java and Groovy:
http://www.grails.org/doc/latest/guide/8.%20The%20Service%20Layer.html
It seems to me like a bad design flaw of the framework, given that the interface mechanism is one of the best features of Java (and most OO languages).
Any idea to clarify this issue?
Thanks!
Mulone
You can have an interface, but actually you don't need one. If I understand you correctly you would like to have two implementations of a service and be able to choose which one to use.
Simply implement two services named for example MyService1 and MyService2, then in grails-app/conf/spring/resource.groovy you can specify:
beans = {
...
// syntax is beanId(implementingClassName) { properties }
myService(MyService1)
...
}
or even:
beans = {
...
if (someConfigurationOption) {
myService(MyService1)
} else {
myService(MyService2)
}
}
This is how you tell Spring which service to actually inject for myService. Now you will be able to use myService like:
public MyController {
def myService
...
}
and Spring will auto wire a proper implementation. This allows you to configure which service implementation to use based for example on some configuration.
Define the service interface in a class com.mycompany.mypackage.MyInterface.groovy stored under src/groovy
Define the service implementation stored under grails-app/services
class MyService implements MyInterface {
// service implementation goes here
}
Its not a design flaw. Groovy is different than java in that it is a dynamic language that uses 'duck-typing'. Whats interesting in groovy is that there are also interfaces. So if you follow #don's suggestion, you can make sure that your service conforms to the interface, but the way you do DI with grails is to just specify the service implementation. i.e. you do not get the compile time check where you use the service implementation, like you do in java.
Note that there is no tight coupling here. Coupling implies that something is bound to a type. But with groovy's loose typing system, types are essentially dynamic creatures. So in java, if you declare a type to be a specific implementation, the code might not compile if you change the type later. In groovy, the code will always compile if you use the 'def'...(I think this is correct)
The best solution I found for this is using Spring bean aliases. Basically you need to:
1) Create an interface in src/groovy ( MyService.groovy )
2) Inject your service wherever you need it:
class MyController {
MyService myService
}
3) Create your regular services implementing that interface ( ImplOneService.groovy, ImplTwoService.groovy )
4) Add an entry to resources.groovy where you define which implementation to use (eventually, testing for environment, or anything else you need):
beans = {
if (...development, useFTP, etc...) {
springConfig.addAlias 'myService', 'ImplOneService'
} else {
springConfig.addAlias 'myService', 'ImplTwoService'
}
}
Complete sources here
My comments: Using interfaces in groovy really seems like some kind of "I want to stick with some java stuff I'm more comfortable with". In this case, strong-typing. But it's exactly the nice part of groovy saying "No worries, you can keep the java way if you want".

Resources