How to access the ServletContext in resources.groovy for Grails 3? - spring

I need to define several beans for spring and to configure the beans I need access to the ServletContext. Previously in Grails 2.x we had code like
beans = {
...
dataProvider(DataProvider) {
def context = ServletContextHolder.getServletContext()
// use context to configure this bean
}
...
}
However in grails 3.x (3.1.10 to be specific), the context variable is always null. If there is another place other than the resources.groovy file that will accomplish this, then that's fine too.

I would use
def context = application.mainContext.servletContext

Related

Injecting spring beans into a groovy script

Is it possible to inject Spring beans into a groovy script?
I want to be able to use service/repository methods from a spring application in groovy scripts
Is it possible to inject Spring beans into a groovy script?
Yes. You can "inject" any object you like, Spring Bean or otherwise, into a Groovy script. It isn't injection in the sense that Spring does dependency injection, but you can get the variable into the script easily by putting it in a shell binding:
def binding = new Binding()
// instead of "new"-ing up an instance, you could do this
// from wherever in your Spring app that you have injected
// the SomeHelper bean
binding.someHelper = new SomeHelper()
// script could be loaded from a file, or hardcoded,
// loaded from a db, etc...
def groovyScript = '''
println someHelper.magicNumber
'''
def shell = new GroovyShell(binding)
shell.evaluate(groovyScript)

Using both WebApplicationInitializer and web.xml in spring mvc+spring security+spring session redis web application

I'm trying to implement Spring redis session in an existing Spring MVC (ver 5.1.6) application. In web.xml we have ContextLoaderListener, DispatcherServlet and contextConfigLocation are all defined.
After required dependencies are included and suggested code changes are done, i'm getting below error:
Caused by: java.lang.IllegalStateException: Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader definitions in your web.xml!"}}*
As part of code changes i'm extending the class "AbstractHttpSessionApplicationInitializer",(from Spring session core library) which internally implements WebApplicationInitializer. Seems like that is trying to create another context and throwing the above error. We cannot avoid extending this class, as this does the job of registering redisHttpSession to context.
Most of the examples available are all with spring boot. So there they wouldn't have faced this issue.
Any solution, other than completely replacing web.xml and use only WebApplicationInitializer?
Just want to provide an update. Instead of extending AbstractHttpSessionApplicationInitializer abtract class, i have taken a different approach by initializing bean RedisHttpSessionConfiguration thru XML bean definition.
This approach worked.
Followed the steps mentioned in the below thread;
How to configure Spring sessions to work with Redis in xml?
Along with that we need to serialize the cookie as well;
#Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("SESSIONID");
serializer.setCookiePath("/");
serializer.setDomainNamePattern("^.+?\\.(\\w+\\.[a-z]+)$");
return serializer;
}

Dynamic autowire in /src/groovy

I want to be able to include Services in my Groovy Classes in /src/groovy
I found a solution with :
myBean(MyBean) { bean ->
bean.autowire = 'byName'
}
But I dont want to make this entry in the resources.groovy for all Class, so is there a Solution to Autowire all classes in a specific folder?
I'm using grails 2.4.3
This seems to be similar to this question: Grails 2.x service injection in Groovy/src
What we use and is proposed there is to get the service via the application context:
import grails.util.Holders
...
def myService = Holders.grailsApplication.mainContext.getBean 'myService'
It's not completely auto-wired, but seems to be the best way to get services into src/groovy.
Edit: also works for Grails 3
You can make a class com.example.MyClass in src/groovy a Spring bean by adding the following to BuildConfig.groovy
grails.spring.bean.packages = ['com.example']
and annotating the class with #Component, e.g.
#Component
class MyClass {
#Value('${conf.apiVersion}')
String apiVersion
#Autowired
SomeService someService
}
As shown above, you can dependency-inject the class with the usual Spring annotations such as #Value and #Autowired. I find this a much more convenient way to register a Spring bean than modifying resources.groovy.

get reference to spring bean from class in src/groovy

I'm writing a Grails plugin that defines a Spring bean in the plugin descriptor
def doWithSpring = {
myBean(MyBean)
}
I need to get a reference to this bean from another class in the plugin.
class Something {
def doIt() {
// I need to get a reference to myBean here. Is this the best way?
MyBean myBean = ApplicationHolder.application.mainContext.getBean('myBean')
}
}
Something is a class defined in src/groovy within the same plugin as the bean, but Something is not itself a spring bean. In Grails 1.3.7 is there a better way of achieving this than that shown above? I'm looking for a better way because I know the *Holder classes are deprecated in Grails 2.0
In Grails 2.x exists the Holders utility class to get the grailsApplication and the applicationContext.
In 1.3.7 I think the option is create your own holder, as described here.

How to select a service implementation in a Grails application?

I have several services implementing a common interface and I want to be able to choose one of them to inject into other services when my application starts up.
I have tried referencing the service implementation from resources.groovy as shown below but then Spring makes a new instance of the selected service and doesn't autowire its dependencies.
How can I get this solution to work? Or is there another way?
class MyService {
Repository repository
interface Repository {
void save(...)
}
}
class MySqlRepositoryService implements MyService.Repository { ... }
class FileRepositoryService implements MyService.Repository { ... }
resources.groovy:
beans = {
...
repository(FileRepositoryService) { }
}
It's of course possible to retrieve the reference to service from hand-built factory, but in my opinion, the approach you've taken is the best one. I use it myself, because it gathers all the information on configuration phase of the application in one place, so it's easier to track down which implementation is used.
The pitfall with autowiring that you've encountered can be explained very easily. All the classes put in grails-app/services are automatically configured by Grails as Spring singleton beans with autowiring by name. So the bean definition you've placed in grails-app/conf/resources.groovy creates another bean, but without the defaults imposed by Grails conventions.
The most straightforward solution is to put the implementation in src/groovy to avoid duplication of beans and use the following syntax to turn on the autowiring:
beans = {
repository(FileRepositoryService) { bean ->
bean.autowire = 'byName'
}
}

Resources