Grails 3 multipart request with Spring Security - grails

I have a Grails 3 rest application, with a call to save uploaded files.
def saveAll() {
request.fileNames.each { filename ->
if(!filename.empty){
File file = params[filename];
file.transferTo(grailsApplication.config.filesPath)
}
}
}
The problem is that the code works correctly, except when I have the control secured with Spring Security, then the params are empty and I find no alternative
(I know that with Spring security there is a wrapper for request, and found several with this issue but still didn't find a clear solution)

The solution was to actually add #Transactional to the function. I have no idea why this is the case. but it worked this way

have you tried using request.getFiles() instead of request.getFileNames(). I have an app that uses springSecurityRest plugin and is secured using annotations and part of the working code is similar to this.
if(request instanceof MultipartHttpServletRequest){
request.getFiles().each { MultipartFile file ->
// ... the code to transfer the file goes here
}
}
I´ve experimented, and in controllers that inherit from RestfulController, it seems that the data of the request is flushed once it is bound. This might be the reason why your params are appearing to be null. I don´t know if it applies here, or if I´m correct in my assumption, though.

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.

Grails Cache and EHCache Plugin caches Controller methods but not Service methods

I'm having trouble getting the Grails EHCache Plugin to cache service methods. Here is my setup:
Grails 2.4.2, JDK 1.7
BuildConfig.groovy compile ":cache-ehcache:1.0.4"
Config.groovy defines the following cache named "cache"
grails.cache.config = {
cache {
name 'cache'
timeToLiveSeconds 60
}
}
The following controller method properly caches. I have tested by setting a breakpoint in the method, and it only is hit the first time, until the cache expires.
#Cacheable('cache')
def index() {
render "index-$params.id"
}
I can check the keys in the cache with:
grailsCacheManager.getCache('cache').getNativeCache().getKeys()
and see the value:
localhost:GET:/grails-cache-test/cache/index?id=34
So far so good.
The following service method exists:
#Cacheable('cache')
public method1(id) {
"method1+$id"
}
I set a break point in here, and this method is always called, regardless of the #Cacheable annotation. I've tried setting the value and key annotation attributes manually, and no change. I test calling this method from a non-cached controller method, as well as directly from the console plugin. When I get the keys in the service method I see that there are no keys set.
I've looked through examples in the official documentation, code samples online, github, a book I have, everything looks good, so I'm not sure where the problem lies.
Any ideas on why this service method does not cache the value? Thanks!
UPDATE 1
I've been digging into the grails cache-1.1.8 plugin (as well as the associated cache-ehcache-1.0.4 plugin), and believe I've found something helpful. In PageFragmentCachingFilter.doFilter() there are calls to check the controller's annotations - but nothing to check the service. It appears that as a result, the service annotations are never honored. There is a lot of documentation that mentions service methods, so I don't know if there is something elsewhere that handles this, or if it's a less common use case compared to controller methods.
UPDATE 2
It appears that Controllers and Services are handled separately. In CacheAspectSupport.execute() there is a for() loop that will call cachePutRequest.apply(result.get());, which will actually add the entry to the cache. Unfortunately after the entry is added to the request, it is not immediately available to be retrieved. The underlying put() code is part of Spring Source, so at this point I'm not sure if it's a grails plugin issue or a Spring Source issue.
I have created a JIRA issue for this plugin GPCACHEEHCACHE-16

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...

Grails URLMappings

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.

web service code in actionscript

im calling an actionscript class from my main mxml file. the actionscript class is responsible for calling a web service and handling the response, however im having trouble and keep getting the following error; (im new to flex btw)
Error #1009: Cannot access a property or method of a null object reference.
my code goes as follows;
public function getSites(argWsdl:String):void{
ws = new WebService();
ws.loadWSDL(argWsdl);
ws.getSites.addEventListener(ResultEvent.RESULT,echoResultHandler);
ws.getSites();
}
public function echoResultHandler(event:ResultEvent):void {
var siteField:ArrayCollection = event.result as ArrayCollection;
Application.application.setSiteField(siteField);
}
when i run the debugger the code never reaches the result hanlder and i see the #1009 error in the variable list.
any ideas?
looks like you have it sorted, but just to add more information in case someone else comes along to this question, you generally see this error when you are trying to use something that hasn't been created yet. A lot of the time you will see it when trying to access UI components that have not yet been created (its good to rely on the creationComplete event for these sort of things), but in this case it looks like you are using the webservice before it is completely ready (the wsdl hasnt been loaded yet).
Just so you know, you can also define your webservices in mxml (mx:webservice) and specify the wsdl there or you can also load the wsdl later on from a configuration file afterwards just by referencing the ID.
sorted it out,
i needed to created a loadEvent and loadhandler. Once loadWsdl is called the loadhandler specifies the laodHandler to use, inside the loadHandler i call the method name as seen in the wsdl
thanks Ryan,
the main reason im using a seperate actionscript class is so i can reuse the same web service calls across my components without having to retype the same code. I couldnt think of a better way to do this - maybe a could have done the same with a custom component

Resources