Grails: how to remove AppName from production url - grails

I am trying to deploy Grails 2.2.3 project to a production and having issue with URL.
I setup reverse proxy in Apache and have http://example.com -- as example.
I set following property in Config.groovy:
grails.serverURL = "http://example.com/"
and set in the application.properties following:
app.context=/
However all of my resources and links always reference to
http://example.com/AppName/...
How do I remove application name ("AppName") from resource and links reference?
Example of resources:
<r:require modules="bootstrap"/>
<g:javascript library="jquery"/>
Example of environments Config.groovy:
environments {
development {
grails.logging.jul.usebridge = true
}
production {
grails.logging.jul.usebridge = false
grails.serverURL = "http://example.com/"
grails.app.context = "/"
}
}
I think Grails application must have some sort of property that could be set!? Otherwise it seems like a pain the neck.
Please help!
P.S: If I access any resource directly (manually remove AppName from URL) I get the right stuff such as css, js and image.
Update:
I set following in application.properties:
app.context=/
serverURL=http://example.com/
and created absolute URL in grails:
<g:createLink controller="Sample" absolute="true"/>
and it creates proper URL!!! However resources use relative path and start with AppName/... It seems like a curse, I just can't get rid of that AppName.
Update:
If I run prod run-app then all URLs come out properly, however the moment I deploy to Tomcat 7, AppName appears in URLs again.

There are other options, but probably the shortest approach is to deploy it like ROOT.war.
Just change the default war filename in the BuildConfig.groovy:
grails.project.war.file = "target/ROOT.war"
Set the right grails.serverURL property for you and you're done.
Hope it helps.

Related

Configuring grails datasources with username and password from OS environment

I am currently working on a grails application. Previously I have been using Django alot to create webapps. In django you can easily create settings that are collected from the OS environment. I find that to be an easy solution for making sure that you don't check in usernames and passwords into the source code repository.
So what I would like to do is in the DataSource.groovy be able to lift in the username and password from the OS environment. Has anyone done anything like this, or is this not the way to go forward?
If this is not the "grails way", how is it supposed to be done, because having the username and password in the repository just feels wrong?
You can write code in DataSource.groovy and Config.groovy to get env variable and then set username password and other things. I always to it for my production app, sample code is as follows
//Eample is based on url structure like "mysql://username:password#host/database?autoReconnect=true&useUnicode=yes&characterEncoding=UTF-8"
dataSource {
String mysqlUrl = System.getenv("DATABASE_URL")
println ">>>>>> Got DATABASE_URL: ${mysqlUrl} <<<<<<<"
URI dbUri = new URI(mysqlUrl);
username = dbUri.userInfo.split(":")[0]
password = dbUri.userInfo.split(":")[1]
String databaseUrl = "jdbc:${dbUri.scheme}://${dbUri.host}${dbUri.path}"
if (dbUri.port > 0) {
databaseUrl += ":${dbUri.port}"
}
String query = dbUri.query ?: "reconnect=true"
query += "&autoReconnect=true&useUnicode=yes&characterEncoding=UTF-8"
databaseUrl += "?${query}"
url = databaseUrl
dialect = 'org.hibernate.dialect.MySQL5InnoDBDialect'
}
This is one of the way I am sure there must be some simpler way to do this.
PS: I find it simple though :)
You can create a environment variable in Windows. Example DBCONNGRAILS. In config.groovy (...\grails-app\conf\config.groovy) you can use something like
def myConnectionString = System.getenv(DBCONNGRAILS)
WARNING: If you get variables from the environment(Windows) there will no problem when loading the value when in development. But when you are working with a production server, there will be cases when you will need to resart the OS for tomcat to be able to pick up the changes. I would recommend externalizing the config files.
You can externalized the configuration in any other place and load/merge it simply in your application configuration.
We use JNDI at work for exactly this scenario. We have context.xml files located within the individual server's Tomcat directories. The context.xml contains the datasource properties and then within the datasource closure (defined in Datasource.groovy), the jndiName property is set accordingly.
More Links about JNDI:
http://grails.github.io/grails-doc/2.3.7/guide/conf.html#JNDIDataSources
http://grails.asia/how-to-make-grails-use-jndi-datasource-with-tomcat

grails 2.5 does not read properties from home dir when added to grails.config.locations

At the top of config.groovy is this line (now uncommented):
grails.config.locations = [ "file:${userHome}/.grails/${appName}-config.properties"]
So we created a properties file on windows in our home dir /.grails, which contains these lines for the database migration plugin:
contents of c:\Users\me\.grails\myapp-config.properties:
grails.plugin.databasemigration.updateOnStartContexts=XXX
grails.plugin.databasemigration.updateOnStart=true
we restart the app, it completely ignores these values.
If however, we change to a groovy file thusly:
grails.config.locations = [ "file:${userHome}/.grails/${appName}-config.groovy"]
And create the following file: c:\Users\me.grails\myapp-config.groovy
grails.plugin.databasemigration.updateOnStartContexts = 'XXX'
grails.plugin.databasemigration.updateOnStart = true
It works perfectly. It seems it is not possible to use property files with the database migration plugin at least.
However, we need to be able to change these values on production (tomcat + war), which we assume cannot compile groovy files, so wont work.
Luckily, the below part does actually work:
if (System.properties["${appName}.config.location"]) {
grails.config.locations << "file:" + System.properties["${appName}.config.location"]
}
But we would really like to get the home dir version working, so we dont have to worry about system properties and command line arguments in our dev environments.
Any ideas?
change the path separator for windows from / to \
try to put the complete path in locations to check the file can be read

Grails - Images located in a different path when running from a war

I've been developing an Grails application that uses some FileResources located in this directory:
MyGrailsApplication\web-app\images
I'm able to get this directory through grails naturally through GrailsResourceUtils.WEB_APP_DIR. However, when I convert my Grails project into a .war file and deploy it to a tomcat server, that code does not work - the path gets messed up.
Through some debug statements, I was able to find a hacky work-around to this (essentially, do a code modification right before I make the war):
// BELOW 2 LINES WORK IN THE WAR FILE, BUT NOT WITH THE RUN-APP CMD
new FileResource(new File("../webapps/InstanceChecker-0.1/images/ok.png"))
new FileResource(new File("../webapps/InstanceChecker-0.1/images/http404.png"))
// BELOW 2 LINES WORK WITH RUN-APP, BUT NOT IN THE WAR
new FileResource(new File(GrailsResourceUtils.WEB_APP_DIR + "/images/ok.png"))
new FileResource(new File(GrailsResourceUtils.WEB_APP_DIR + "/images/http404.png"))
Is there a way to cleanly get the image path both in run-app and also when its deployed as a .war? Are there some best practices that I'm missing out on here?
Edit: Perhaps I'm not putting the images in an ideal directory? I'm open to advice on that as well.
For get a resource file you can use this:
def basePath = grailsApplication.mainContext.servletContext.getRealPath('images')
Check if end with "/":
basePath = basePath.endsWith("/") ? basePath : basePath + "/"
And then:
new FileResource(new File(basePath+"fileName"))
Remember to inject grailsApplication in your controller/service
you can (also) utilize grail's linkGenerator like
final headerImage = new Image(null, new ExternalResource(Grails.get(LinkGenerator).resource(dir: "images", file: "logo.png")))

Grails app not loading js and css from cloud front

This has to be some type of configuration issue, but I can't figure out what it is. My grails app when deployed to elastic beanstalk will load my index.gsp and show an image. Now this is a stripped down application with nothing but a single page. The page has one image and I'm trying to load the css/js/image from cloudfront. The image loads fine.
http://d55az6m6nudec.cloudfront.net/images/placeholder.jpg
Css + js do not load at all:
http://d55az6m6nudec.cloudfront.net/js/application.js
But as you can see the js comes from the same cloudfront and the URL is formatted the same. When I inspect the webpage and click on the js or css files, I get redirected through cloudfront and the browser shows it's trying to load this URL:
http://awseb-e-m-awsebloa-1bzuvx2wx2h91-492777361.us-west-2.elb.amazonaws.com/statichttp://d55az6m6nudec.cloudfront.net/js/application.js
So it's got the 'static' prefix in there, and I don't know what's going on. Here are some of the relevant parts of my Config.groovy:
grails.resources.mappers.baseurl.enabled = true
I've tried this next line both commented on/off:
grails.resources.mappers.bundle.excludes = ['**/*']
Here is my base url:
grails.resources.mappers.baseurl.default = "http://d55az6m6nudec.cloudfront.net"
I have tried this on/off:
grails.resources.uri.prefix = ""
I have tried this with/without values:
grails.resources.adhoc.patterns = []
and:
grails.resources.adhoc.patterns = ['/images/*', '/css/*', '/js/*', '/plugins/*']
I'm running out of combinations, and at this point I'm just doing trial and error which is taking forever to figure out what should work. I'm also using a load balancer.
It turns out the problem was I did not have the grails.serverURL variable set for my production environment. Now I'm not sure why this caused the error, but I redeployed with the server set and now the css and js files are loading fine.

Grails External Config Read Incorrectly on First Load

Grails 1.3.7
I have some configuration located in an external config file. One of the entires looks like this:
site.maintenance.mode = false
I have a filter which checks for certain config settings for specific URLs. When I do a run-app or deploy a WAR into Tomcat and do:
boolean maintenanceMode = grailsApplication.config.site.maintenance.mode
maintenanceMode is coming back true. If I look at the config object in debug mode, this is what I get:
site={maintenance={mode=false, message="<p>Our trail guides are working hard to get the system back on track.</p><p>We're sorry, the account system is down for maintenance at the moment. We'll get it back online as quickly as we can. Thanks for your patience.</p>"}}
I have a controller that I use to reload this config file dynamically and hitting this controller will fix the issue. But I'm curious as to why it is incorrect on first runs and why the discrepency in what is getting put in the maintenanceMode variable vs what is actually in the config object.
Are you using a Java properties file or a Groovy file? If you're using a properties file then I believe Grails will interpret site.maintenance.mode=false the same way as site.maintenance.mode='false' and since Groovy will interpret:
"false".asBoolean() == true
then that would explain why you would see that initial true value.
I just ran a simple test locally to verify this behavior. When I externalize my properties in a file called test.properties then site.maintenance.mode=false initially gets a boolean value of true, when I use a file called test.groovy then it interprets the boolean value of site.maintenance.mode=false as false. I believe this is because when you use a Groovy file Grails uses ConfigurationSlurper to process it but when you use a properties file Grails interprets everything as String name/value pairs.
What I do is to have an external Config.groovy file, for instance: MyConfig.groovy
At the end of the standard grails Config.groovy file, I have the following:
def ENV_NAME = "MY_EXTERNAL_CONFIG"
if(!grails.config.locations || !(grails.config.locations instanceof List)) {
grails.config.locations = []
}
if(System.getenv(ENV_NAME)) {
grails.config.locations << "file:" + System.getenv(ENV_NAME)
} else if(System.getProperty(ENV_NAME)) {
grails.config.locations << "file:" + System.getProperty(ENV_NAME)
} else {
println "No external Configs found."
}
So now you can have a MyConfig.groovy file anywhere in production environment (for example) and then set an Environment system variable to point to this file (or pass it as parameter to startup.sh), before you start tomcat:
MY_EXTERNAL_CONFIG="/home/tomcat/configs/MyConfig.groovy"
export MY_EXTERNAL_CONFIG
That's it. Now you have an external MyConfig.groovy file. The properties in it are accessible from your grails app as they were part of the standard Config.groovy
import org.codehaus.groovy.grails.commons.*
//...
ConfigurationHolder.config.foo.bar.hello

Resources