Contents
- Intro + Building Grails App + Domain
- Adding the Grid + Form + Image Upload
- Registration + ACL’s + Filter Data for User + Securing User Data + Updating Image Uploads to User Dir
- Edit and Delete on Posts + eMail
- Setting Up MySQL with Grails + Tomcat Config Changes + Deploying WAR to Production Environments
[divider]
Setting Up MYSQL + Deployment to Production
At this point the core functionality is done. Update the UI as you see fit. Maybe change the CSS on registration/login… whatever you want. But by now you should have a working web application that:
- handles user registration and login
- data view for each user
- data is shown for current user only
- user can only edit/delete their own data
- image upload capabilities (images are uploaded to user directory stored outside webapp)
- mail controller is added to send registration emails and any other mail communication requirements
- easygrid is now configured with a setup to allow edit within the grid with a special formater
MySQL
At this point you want to start using a database that will resemble the one you’ll be using in your production environment. MySQL is what I’ll go over here, but if you want to use Postgresql, MongoDB, you should look into how to add those.
For MySQL you will need to first make sure you have a local installation of MySQL. If you don’t have it, download and install it… make sure you get the MySQL Workbench so you can remote in and see the data.
Once you have a local MySQL installed, and your local server is up and running…. Create a db in your local env. You could call it tradingcarddb.
In Grails, open /conf/BuildConfig.groovy and go to the dependencies closure. Uncomment the line:
runtime ‘mysql:mysql-connector-java:5.1.24’ (You may have a different version number.)
Now open the project file: /conf/DataSources.groovy.
1. At the opening dataSource closure, make sure the driverClassName = “org.h2.Driver” is commented out (we don’t want to use it.)
2. Add driverClassName = “com.mysql.jdbc.Driver” in the dataSource closure at the top
3. add a username and password for your mysql database, in the datasource closure
4. Under the environments closure make sure that the development { dataSource{ closure has a url like this:
url = “jdbc:mysql://localhost/tradingcarddb?userUnicode=yes&characterEncoding=UTF-8&autoReconnect=true”
That should do it. The development database is set to create-drop by default. That means each time you restart your Grails application it will dump the data. It’s good for dev, because you might change your schema, etc. When you go to production, you’ll want that to be a update only.
Deployment To Production
I’ll tell you what I’ve recently learned from deployment to production. First thing… where will you deploy? Are you going to host this in your companies infrastructure? Or will you use third party?
If you’re like most lone developers, you’re going to need to pay for hosting. If you are developing for company work, then you don’t need to worry as much about memory and heap, as you have fully control over that. If however, you are looking for private hosting, the heap size and memory considerations will increase your $$ amount per month.
Types of Hosts
VPS
Cloud Pay per Need
Cloud Pay per Use
I’m sure there’s more types but those are the categories I think of when I look at hosting. The difference is detailed below:
VPS
VPS is a virtual private server. It’s a VM probably that lets you have X RAM, X HD Space, X Bandwidth and X Heap Size. You get a persistent server, so your website will be up all the time (hopefully.) You are given a monthly cost up front for what you need. You’ll be doing a old school production launch – Tomcat/Jetty with MySQL. You upload a WAR file (a file generated from a Java app, that has all the files necessary to run the app. You have full control and insight into what’s going on. The downside is this will be a configuration mess if not done right.
Cloud Pay per Need
Heroku and OpenSHIFT are examples of this type of host. They provide you with an interface, that hooks into your github (or in openshift’s case, you clone your code into their git repo) and it runs your deploy from your git repo, building on their servers. You shouldn’t have to do much. The downside is, it’s a black box. You have little to visibility into the database, things just “work” or they don’t.
I found Heroku to work well with Rails, but with Grails it was buggy. I had to use their preferred db (Postgresql) and they kept telling me I’d have to pay for more memory as it was running out on initial deploy (the heap size most likely.) But Heroku is pretty user friendly. OpenSHIFT is a pain. It’s not user friendly, you end up doing too much config… it’s so much easier to just get a VPS rather then use OpenSHIFT.
Cloud Pay per Use
This is the Amazon’s AWS, Google App Deploy and Cloud Foundry model. You pay for some sort of usage fee. AWS is a nightmare of hidden costs. If you’re a corporation you probably don’t care if AWS charges an extra $50-$200/month. If you’re a little guy like me… you can mistakenly get billed for thousands. AWS had me on a free tier a year ago. Then all of a sudden I was getting hit with monthly charges! Turns out my usage flipped to a different IP (west coast US) that took me out of the free tier… all without telling me. Scoundrels. I called and complained and they refunded me… but I won’t go back.
I haven’t used Google’s app deploy but the same method of Pay per Use is used by them… and it just scares me. I did apply for Cloud Foundry. It’s so funny. These guys act like they are God’s Gift to developers. You register with them and they send you an email about how you are on a “waiting list” and they’ll “review to see if they’ll let you in.” It’s like some high end club.
Well I got in. Logged in and was hit with their first screen telling me if I continue I’ll be in a 60 day trial and after that it’s X per some usage fee. Once I saw they went with this model, I opted out. It might not be expensive. They may not employ the tricks of AWS, but I just like my costs upfront.
In the end I went with a affordable Java VPS called: www.javaprovider.net
They are already set up to work with MySQL and Tomcat.
Many VPS solutions offer a free trial for 30 days or so. It gives you a chance to see how your app will behave in their environment.
I Got My Host, Now What?
As long as your app is working locally with MySQL it should be fine to get ready to deploy. But there are a couple things to consider:
- You may need to Tweak your MySQL connection pool settings
- You will definately need to tweak the Tomcat settings
MySQL Connection Pool
By default Grails doesn’t supply you with this. But if you look at their website you’ll see they mention you should have these properties in your DataSource.groovy’s production closure:
url=… //what the host told you to point to, with the addition of your db name you set up with your host’s db
username = //what the host told you to use
password = //what the host told you to use
dbCreate=”update” //you could do a create-drop for the first few deploys, if you think you’ll make major changes
pooled=true
properties {
maxActive = 50
maxIdle = 25
minIdle = 5
initialSize = 5
minEvictableIdleTimeMillis = 60000
timeBetweenEvictionRunsMillis = 60000
maxWait = 10000
validationQuery = “select 1 as dbcp_connection_test”
testOnBorrow=true
testOnReturn=true
testWhileIdle=true
}
Update 3/7/2014: The bit in red above was updated from my first post. Once I added those lines, I no longer had issues with MySQL connections!
The stuff in Red is what’s the add on stuff. Without it you may face a problem with the database connections closing and your app not being able to talk to the db afterwards. This has happened to me and I’ve been told the solution is to have the properties closure there. The magic is evidently the valdiationQuery = “/* ping */” I guess that keeps the connection alive.
What you may find without it, is that overnight, if no activity occurs in the app the connection to the db is lost, and in the morning you won’t be able to pull any data from it without a restart of Tomcat.
Other solutions would involve c3po, etc. But that gets into a whole new level of complexity.
Steps To Deploy
Once your app is all wired to talk to the production environment, you will need to decide how people will reach it.
Do you want people to go to: yourhost.com/theapp’sname? Or do you want people to hit the main domain and get your app (i.e. yourhost.com = your app)?
I prefer that the domain name is the app. I don’t want people going to sub directories for my apps.
This means, that our WAR file will have a special name. It will be called ROOT.war. If you let Grails make a generic war, it will be named after your app. Tomcat will then create a sub directory off the domain with that name, and that’s where your app lives. IF however, you name the WAR ROOT.war, then it will deploy to the “/” of the Tomcat webapps folder.
What I first do is FTP to the server and go to the Tomcat webapps folder. I rename the existing ROOT folder to ROOTBAK or something. You won’t need to do that again.
- in your project folder type this on the command line: grails war
- when it’s done, it will place the war in the projectname/target folder. It will by default be named after the project. We will now rename it to root: mv target/[YOUR WAR] ROOT.war
- You can do a grails war ROOT.war HOWEVER IF YOU DO IT WILL PROBABLY BE CORRUPT. I have found from personal experience that some static files don’t get included in the WAR if you use Grails to make an alternate name for the war. Why? I don’t know. It has just happened to me in Grails 2.3.4 where making a named war created it without the js and css. But when I did the generic: grails war and renamed it to ROOT it worked fine.
- You will upload your ROOT.war file to the tomcat /webapps folder
- Once it finishes uploading, restart tomcat. Many providers offer a restart button a page some place. Else you’ll need to restart via ssh’ing to the box
- Tail the log file which is in the tomcat /catalina/logs/catalina.out (tomcat 7)
When Tomcat is restarted, you should be able to go to your domain and see the Grails app you built running. Login to verify your bootstraped users are working (this tests spring security as well as MySQL.)
Updating Tomcat To Work with Your Uploaded Images
This is a tricky subject. It will change depending on your version of Tomcat.
Back in Part 1, we did the image upload… Recall that if we were to have uploaded images within the / directory that is our application, on each redeploy of our app, we’d loose all files that were uploaded…
So instead, we attempt to save to ../gallery.
- First: Make a folder “gallery” in the webapps folder of Tomcat.
Your Tomcat directory will be like:
ROOTgallery
- Second: We need to make a Tomcat Alias to webapps/gallery = ROOT/gallery
What we’re doing here is storing the image files in webapps/gallery, but making the application think it’s in /gallery. This is so weird to me, but make it makes sense to others out there…. It took me hours to find the solution here. The solution for Tomcat 6 (adding a context tag in the host tag) will not work for Tomcat 7. This is how it works for Tomcat 7:
- In your apache Tomcat folder, there’s a conf directory. It’s usually inside /apache-tomcat…/conf Inside that is a sub folder called Catalina. Within that folder is a sub folder called localhost (and/or it may be your domain name if you registered one for this provider.)
- We go into the sub directory here (localhost or domain name) and create a file named: ROOT#gallery.xml
- This file is saying, we are talking about a directory in root called gallery. The file name is critical. If you use version numbers or you use non Root deploys you need to see the Tomcat naming conventions for this file. Version numbers have two ## in them. like ROOT##42#gallery.xml But if you don’t use version numbers just make it ROOT#gallery.xml
- Open that file up and add this one line: <Context aliases=”/gallery=/gallery”/>
- That line is saying I have an alias /gallery (corresponding to your application/gallery) which is equal to the real /gallery (which is webapps/gallery on the file system.)
- Restart Tomcat
After Tomcat restarts, check the site and login. Try and do a post via the dashboard form and submit an image. Using your FTP client, validate the image successfully uploaded to webapps/gallery and not webapps/ROOT/gallery
If all works out well, your site’s files are now safe from redeploys.
One response
[…] Setting Up MySQL with Grails + Tomcat Config Changes + Deploying WAR to Production Environments […]