Grails "respond" renders the wrong view when launched from .war file - grails

A Grails application has a lot of auto-generated (from standard Grails 2.3.0 scaffolding) code using the new RESTful "respond" feature. For example, the index methods generally look like this:
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
respond Alpha.list(params), model:[alphaInstanceCount: Alpha.count()]
}
This works completely fine when the application is run as "grails run-app" however fails when the application is packaged as a .war and launched that way inside a non-embedded servlet container.
It works for the first controller/view combination used, but for subsequent ones uses the view folder of the first view rendered. E.g., if we try /alpha/index first, and then afterwards /beta/index then the /alpha/index will work fine, but /beta/index will use /alpha/index.gsp for rendering (instead of the expected /beta/index.gsp).
If, however, I change the method to:
def index(Integer max) {
params.max = Math.min(max ?: 10, 100)
render(view: 'index', model:[alphaInstanceList: Alpha.list(params), alphaInstanceCount: Alpha.count()])
}
then it works fine in both deployment options.
I added some debug code to some of the .gsp-s to output ${this.getGroovyPageFileName()}, ${controllerName} and ${actionName}.
That shows that while the controller and action names are always the expected ones, the view used on views rendered after the first one remains the view used on the first one.
For example, the initial invocation for /alpha/index has controller as alpha, action as index, and view as /WEB-INF/grails-app/views/alpha/index.gsp, however the consequent invocation of /beta/index has controller as beta, view as index, but view as /WEB-INF/grails-app/views/alpha/index.gsp (note the wrong "alpha" here). Consequent invocations of alpha remain fine.
If we had started with beta, and then moved to alpha, it would have been the other way around (beta is fine, alpha is broken).
I tried running it unders JPDA but while my IDE appears to be connecting it is not actually hitting any breakpoints (probably unrelated issue).
I'm using Grails 2.3.0, JDK 1.6, and Tomcat7.
There is nothing bad that I can see in the logs.
Any ideas what the issue may be, or even just how to approach debugging it?
http://goo.gl/aFKYYb <-- grails app
http://goo.gl/aDP6Lx <-- .war file

Upgrading to Grails 2.3.1 fixed this problem for me. (Reading the defect you posted pointed me in the right direction - thanks.)
Note that you will also have to upgrade your hibernate plugin to version 3.6.10.2, or you will get an error message similar to "Method on class [] was used outside of a Grails application."

Possible Grails defect (although they cannot reproduce):
http://jira.grails.org/browse/GRAILS-10614
I did a "install-templates" and am modifying the scaffolding templates as a work-around.
Edit - yes, confirmed; I forgot to update this response but upgrade to 2.3.1 solves the issue, as per the defect linked.

Related

grails can't find view from plugin

I'm trying to write a grails plugin that can view files. Actually, I'm just trying to upgrade this one here... https://github.com/intelligrape/File-Viewer-Grails-Plugin to grails4, and get it working in my app.
Anyway, after I get it working in the app, I visit http://localhost:8080/file/index and I get this error:
URI
/file/index
Class
javax.servlet.ServletException
Message
Could not resolve view with name '/plugins/file-explorer-0.1/file/fileList' in servlet with name 'grailsDispatcherServlet'
This occurs when the controller does this...
def index(String filePath) {
Map model = [locations: fileLocations.locations]
// blah blah
render(view: "/file/fileList", model: model, plugin: 'fileExplorer')
}
The render() method is called (I checked in the debugger). I also tried removing the plugin: parameter, but it made no difference.
Now if I run the plugin as a standalone app (by going to that folder, and running "grails run-app", then it works as expected, and http://localhost:8080/file/index renders the view as one would expect.
This all leads me to believe that the plugin is basicly working and installed into my app EXCEPT the view component, which for whatever reason cannot find the views from a plugin.
If you want to know what the source looks like, it's basically what you see here:.. https://github.com/intelligrape/File-Viewer-Grails-Plugin Except I've renamed it from FileViewer to FileExplorer.
I'm using grails 4.1.0.M5 I don't know if it could be a bug in this version or what.
It seems that I should have had
plugin: 'filexplorer'
instead of
plugin: 'fileExplorer'
I could have sworn I tried this already. I guess the thing is it can be confusing which name to use where as far as plugins, as in the build.gradle name, the name in the *Plugin.groovy, the name in settings.gradle, the package name etc. Anyway, somehow I screwed up.

Groovy Grails Tool Suite: `static mapping` code block breaks syntax highlighting and content assist

When you add a static mapping code block to a grails domain class, the content assist and syntax highlighting does not work anymore for this domain class. This does not only affect the .groovy domain class file but also the rest of the workspace.
Steps to reproduce:
create a new project with two domain classes Test1 and Test2 being in the same package.
Add the following code:
Test1.groovy
package org.test
class Test1 {
Test2 someOtherObject
String someProperty
def doSomethingWithSomeProperty(){
someOtherObject.someMethod.replaceAll(/hello/, '$1 friend')
someProperty
}
}
Test1.groovy
package org.test
class Test2 {
String getSomeMethod(){
return 'hello'
}
}
Everything should work fine so far. In Test1 someProperty and someMethod are highlighted in blue, as they are both either a property or an implicitly called get method.
Now, if you add a static mapping code block to Test2, the syntax highlighting of someMethod call in Test1 will switch from blue to black-italic. Also, content assist does not work anymore; the replaceAll is underlined because someMethod is not actually recognized.
This already restricts usability, but if you add another static mapping code block to Test1, the method of Test will not even be recognized anymore. As soon as you remove the block, everything works fine again.
I've set the priority to major because this is slowing down all working processes significantly, although it may seem trivial at the first glance. Typos happen more frequently if you do not have the content assist telling you about it. If this is not a major bug, just set it to minor.
I already filed an issue for that, but if anybody knows a workaround, please let me know.
EDIT: Sorry, I forgot to add version and operating environment information:
OS: Windows 7 x64
IDE: GGTS 3.5.1
Grails: 2.4.x
EDIT 2: Not reproducible with grails 1.3.7.
It sounds like you're having problems with the groovy eclipse plugin.
You might be better off submitting a bug here instead: http://jira.codehaus.org/browse/GRECLIPSE
GGTS is just eclipse with Spring and Groovy plugins already installed.
You could try updating to the latest developer snapshot to see if that fixes the problem.
Just use the update site for the version of eclipse you're using.
http://groovy.codehaus.org/Eclipse+Plugin#EclipsePlugin-DevelopmentSnapshotBuilds

cakephp highchart fatal error while rendering

Here I am, again. With another question concerning cakephp-2.5 and the plugin 'highcharts'.
I've been looking at the demo's an all the different things I could find were the extendings from the controllers. But... that isn't required because it's a plug, am I right?
So, I have included th plugin to my loadings inside the bootstrap file, and when I'm trying to render my HighChart I'm receiving the following error;
Error: Chart: "1" could not be found. Ensure that Chart Name is the same string that is passed to $this->HighCharts->render() in your view.
But the demos are working fine! Any idea what I f*cked up? The names are the same, I even renamed them to 'asd' ( both! ) and it still doesn't work. ^^"
I know this is an incredibly late response but for the benefit of those still experiencing problems with this, the CakePHP 2.* Highcharts plugin has been updated and is compatible up to CakePHP version 2.5.7.
Do note however that in order to maintain product name consistency throughout the repo, all previous references to "HighCharts" have been changed to "Highcharts" and "high_charts" is now simply "highcharts" . So for eg. you now have to call $this->Highcharts->render() where before you would have used $this->HighCharts->render().
The plugin was not yet compatible with CakePHP 2.5. Right now as we speak the developer is working on a new release for 2.5. :)
In CakePHP 2.5, you can avoid the error above and render your chart by calling it.
For example from within index() within your controller, use:
$this->bar();
In this example, bar() is the name of the function containing your chart.

Overriding plugin views in Grails 2.2

I'm trying to customize the HTML markup of the excellent FilterPane grails plugin, however I'm having some difficulty. FilterPane provides a bunch of tags for rendering the search/filter form, and I would like to override these in my application.
I had thought that I could simply copy the _tagName.gsps that I wanted to override from
plugins/filterpane-2.0.1.1/grails-app/views/filterpane
into
grails-app/views/filterpane
and modify them, however it looks like Grails never checks whether the application is overriding the views of a plugin, if the render method is called with a plugin name property specified.
org.codehaus.groovy.grails.web.pages.GroovyPagesTemplateRenderer.findAndCacheTemplate contains the following code in a private method:
...
GroovyPageScriptSource scriptSource;
if (pluginName == null) {
scriptSource = groovyPageLocator.findTemplateInBinding(templatePath, pageScope);
} else {
scriptSource = groovyPageLocator.findTemplateInBinding(pluginName, templatePath, pageScope);
}
...
so when a non-null pluginName is specified, we just grab the plugin's view and never check whether the application is overriding it.
I thought a simple way to get around this problem would be to just override GrailsConventionGroovyPageLocator.findTemplateInBinding, or some other similar method in GrailsConventionGroovyPageLocator, however it doesn't appear to be possible to do this from within a Grails application either!
I created a simple class overriding GrailsConventionGroovyPageLocator, replacing the findTemplateInBinding method with one that checks the application's view directory before checking that of the plugin. I then modified resources.groovy, adding a doWithSpring closure to replace the beanClass property of the default groovyPageLocator:
def doWithSpring = {
def pageLocator = delegate.getBeanDefinition("groovyPageLocator")
pageLocator.beanClass = MyConventionGroovyPageLocator
}
However this doesn't seem to be called when my application starts up.
I'm really at a loss here. I'd expected this to be straightforward, but it's turned into a bit of a can of worms. Does anyone have any suggestions? All I want to do is override the views provided by a plugin...
You can modify the plugin source, instead of changing the location of the template.
The location is: user_home\.grails\version\projects\project\plugins\plugin-name
I am not a grails expert, but in order to override plugin views you should recreate them in your main projects views folder. For example, I changed the /auth/login.gsp from Spring Security Plugin by simply creating the same thing in my /project/views/auth/login.gsp. If you make changes into the plugin files itself you could potentially lose them if you uninstall the plugin.
In order to change a view in a template of a plugin, perform the command
grails install-templates
source
This will copy the templates of the plugins to your project which you then can customize. What this does with for example the scaffolding plugin, is copy files to src/templates/scaffolding (note, not grails-app/templates/scaffolding). Therefore, in your case, I would try copying the files to src/views/filterpane

ASP.NET MVC ViewData (using indices)

I had a working solution using ASP.NET MVC Preview 3 (was upgraded from a Preview 2 solution) that uses an untyped ViewMasterPage like so:
public partial class Home : ViewMasterPage
On Home.Master there is a display statement like this:
<%= ((GenericViewData)ViewData["Generic"]).Skin %>
However, a developer on the team just changed the assembly references to Preview 4.
Following this, the code will no longer populate ViewData with indexed values like the above.
Instead, ViewData["Generic"] is null.
As per this question, ViewData.Eval("Generic") works, and ViewData.Model is also populated correctly.
However, the reason this solution isn't using typed pages etc. is because it is kind of a legacy solution. As such, it is impractical to go through this fairly large solution and update all .aspx pages (especially as the compiler doesn't detect this sort of stuff).
I have tried reverting the assemblies by removing the reference and then adding a reference to the Preview 3 assembly in the 'bin' folder of the project. This did not change anything. I have even tried reverting the Project file to an earlier version and that still did not seem to fix the problem.
I have other solutions using the same technique that continue to work.
Is there anything you can suggest as to why this has suddenly stopped working and how I might go about fixing it (any hint in the right direction would be appreciated)?
We made that change because we wanted a bit of symmetry with the [] indexer. The Eval() method uses reflection and looks into the model to retrieve values. The indexer only looks at items directly added to the dictionary.
I've decided to replace all instances of ViewData["blah"] with ViewData.Eval("blah").
However, I'd like to know the cause of this change if possible because:
If it happens on my other projects it'd be nice to be able to fix.
It would be nice to leave the deployed working code and not overwrite with these changes.
It would be nice to know that nothing else has changed that I haven't noticed.
How are you setting the viewdata? This works for me:
Controller:
ViewData["CategoryName"] = a.Name;
View:
<%= ViewData["CategoryName"] %>
BTW, I am on Preview 5 now. But this has worked on 3 and 4...
Re: Ricky
I am just passing an object when I call the View() method from the Controller.
I've also noticed that on my deployed server where nothing has been updated, ViewData.Eval fails and ViewData["index"] works.
On my development server ViewData["index"] fails and ViewData.Eval works...
Yeah, so whatever you pass into the View is accessible in the View as ViewData.Model. But that will be just a good old object if you don't do the strongly typed Views...

Resources