Details
-
Type:
Bug
-
Status:
Resolved
-
Priority:
Blocker
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: None
-
Component/s: None
-
Labels:None
-
Environment:Windows XP, Tomcat 6.0.18, JDK 1.6.03
Description
I installed the Facebook Connect v0.1 plugin for my Grails application and it works fine when using the built-in Jetty web server (i.e., "grails run-app" from within my project root). However when I created a WAR file ("grails war") and deployed it against Tomcat (v6.0.18) the application fails to start with this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flowRegistry': Cannot resolve reference to bean 'flowBuilderServices' while setting bean property 'flowBuilderServices';
...
nested exception is Error creating bean with name 'facebookConnectService': Invocation of init method failed; nested exception is java.io.FileNotFoundException: C:\webservers\apache-tomcat-6.0.18\bin\grails-app\conf\FacebookConnectConfig.groovy (C:\webservers\apache-tomcat-6.0.18\bin\grails-app\conf\FacebookConnectConfig.groovy)
at java.security.AccessController.doPrivileged(Native Method)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
...
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
Further investigation into the code of FacebookConnectConfig.groovy shows that in the afterPropertiesSet() method it attempts to load a file from a location which is inexistent in the WAR file:
FacebookConnectService.groovy, lines 14-19:
void afterPropertiesSet() { GroovyClassLoader loader = new GroovyClassLoader(getClass().getClassLoader()) //Class clazz = loader.parseClass(new File("src/templates/_FacebookConnectConfig.groovy")) Class clazz = loader.parseClass(new File("grails-app/conf/FacebookConnectConfig.groovy")) facebookConnectConfig = new ConfigSlurper().parse(clazz) }
The correct way would be to perform a check for the existence of the compiled Java class FacebookConnectConfig, which will be available in the WEB-INF/classes of the generated WAR file. Something like:
void afterPropertiesSet() {
// check if there is a compiled class for the Facebook connect config groovy script
// this will be the case when an application is bundled in a WAR
def config = new FacebookConnectConfig()
if (config != null) {
// compiled config class found, we must be running as a WAR
facebookConnectConfig = config
} else {
// no compiled class exists for the config, we must be running the Grails built-in web server
GroovyClassLoader loader = new GroovyClassLoader(getClass().getClassLoader())
Class clazz = loader.parseClass(new File("grails-app/conf/FacebookConnectConfig.groovy"))
facebookConnectConfig = new ConfigSlurper().parse(clazz)
}
}
I've attached the modified FacebookConnectService class in case it's helpful.
Oops, the code I posted with the correction is missing one line. Here it is in full again:
void afterPropertiesSet() {
// check if there is a compiled class for the Facebook connect config groovy script
// this will be the case when an application is bundled in a WAR
def config = new FacebookConnectConfig()
if (config != null) { // compiled config class found, we must be running as a WAR facebookConnectConfig = new ConfigSlurper().parse(config.getClass()) } else { // no compiled class exists for the config, we must be running the Grails built-in web server GroovyClassLoader loader = new GroovyClassLoader(getClass().getClassLoader()) Class clazz = loader.parseClass(new File("grails-app/conf/FacebookConnectConfig.groovy")) facebookConnectConfig = new ConfigSlurper().parse(clazz) }
}