06.21
Did you know that you can have a complete modular enterprise application up and running in under 5 minutes with Grails? The architecture will be a lot more flexible and maintainable than any “Enterprise Java” structure with Ant or Maven too!
First things first, how many different modules should an application have? Well, every application probably needs three essential things these days: website, mobile website and API. Wait, why do you need an API if you don’t necessarily have any plans of sharing data? Well, the answer is you might need native Android and iPhone apps in the future, so you might as well plan for them right away. The HTML5 frameworks are getting pretty good though! Take a look at Sencha Touch if you haven’t yet as it’s pretty cool! So why can’t you just use one project for the API and the website? Well, I don’t recommend having a controller that returns JSON or HTML based on the request. It seems cluttered to me plus you might want to return more or less data given the target and have a completely different security setup for each (basic, digest or token for API vs forms for web). Also, versioning the API is a lot easier if it’s separate from the website. Plus as you’ll see in a bit, it’s really easy with Grails to separate out the API into a separate project and reuse code.
First, create a parent folder for the entire application. Then create three separate Grails applications in this parent folder.
- grails create-app sampleapp-web
- grails create-app sampleapp-api
- grails create-app sampleapp-mobile
Next, create a Grails plugin for the core part of the application. This is where you’ll put all reusable code for your application like domain classes and services.
- grails create-plugin sampleapp-core
Now we need to set a reference to our plugin in each of the three Grails applications we created. This is slightly different from installing regular Grails plugins. Since this plugin is going to be changing a lot as you develop the application, you don’t want to be constantly packaging and installing the plugin into each of the three apps. So, instead add this line to the end of grails-app/conf/BuildConfig.groovy for each of the three (web, api and mobile).
- grails.plugin.location.’sampleapp-core’ = “../sampleapp-core”
Now you can add a class to “core” at any time and it’s automatically available to all three projects! You never have to compile the core plugin, but rather when you run or test any of the three main apps, it will automatically pick up changes made in core. Pretty slick, huh! We’re not done yet though! You obviously want to test all three at the same time, right? Ha! Ok, maybe not, but I do for some reason! Plus I like to run other stuff on 8080 anyway, like Jenkins for example, so let’s add this line to grails-app/conf/BuildConfig.groovy so that they run on different ports and there’s no conflict on port 8080.
- sampleapp-web/grails-app/conf/BuildConfig.groovy:
- grails.server.port.http = 8081
- sampleapp-api/grails-app/conf/BuildConfig.groovy:
- grails.server.port.http = 8082
- sampleapp-mobile/grails-app/conf/BuildConfig.groovy:
- grails.server.port.http = 8083
Next, I’m never nearly as good of programmer as I pretend to be, so I always add the code review plugin!
- grails install-plugin codenarc
Finally, the last thing actually has nothing to do with setting up an application, but rather is just cause I’m kind of lazy, ha! Let’s shorten the typing required for run-app and test-app scripts. This may seem really trivial, but think about how many times you’ll type these commands, makes sense to make them as short as possible, doesn’t it? Plus, it will also show how cool our setup is by being able to reuse scripts across all four Grails projects! You could also create scripts that are available to all Grails projects on your computer, but I think it’s better to keep each application completely independent.
Run the following command while in the core plugin (sampleapp-core):
- grails create-script ra
- grails create-script ta
This will create two files in sampleapp-core/scripts. Erase everything from these two files and add this:
- sampleapp-core/scripts/Ra.groovy: includeTargets << grailsScript(“RunApp”)
- sampleapp-core/scripts/Ta.groovy: includeTargets << grailsScript(“TestApp”)
With these two scripts setup in core, you can now simply execute grails ra or grails ta instead of grails run-app and grails test-app in any of the four Grails projects!
Well, I hope you enjoyed my Grails Setup article! It certainly is a better setup than any crazy stuff I used to do with Ant or Maven! Let me know if you have any suggestions for ways to improve it. Happy coding!
Nice article, gives some insight on how to partition up my grails apps. If you setup things like this and you add some stuff the the core part, is there a way on automatically let this being picked up by a running web part for example?
[...] Grails Setup [...]
Thanks for a helpful article.
It’s not clear where you install the codenarc plugin. Is there one in each of the three apps, or is there only one in the core plugin?
BTW, I also came across this. What do you think of it as an alternative to separate apps?
http://www.grahamdaley.com/computing/mobile-layouts-with-grails-automatically/
Hi Lee! Thanks for commenting on my blog. I just installed CodeNarc into the core, but you could certainly use if for all three if you’d like!
That’s an interesting article and certainly another way to accomplish it too. I personally haven’t tried it, so can’t offer any advice about implementing it, but it looks pretty slick and I’ll have to try it out sometime. Thanks, Bobby!
How do you do authentication in this scenario? Lets say my api access the domain app through REST, and my webapp access my api through REST? Where does the webapp authenticate? At the domain app? At the api? And how do credentials get passed from the webapp to the api app to the domain app?
Roberto: Each app (web, api, mobile) needs to do it’s own authentication, but you would have your User, Role, UserRole domain objects in the plugin (core) so that the credentials are the same across the different apps.
How does this setup look like a deployment time? Are you running each of the apps under separate contexts in Tomcat in your production environment? If so how do you handle caching across entities in the API and mobile and website apps?
Each app (API, Web & Mobile) runs in its own JVM (Tomcat) clustered (AWS BeanStalk). I’m not currently doing caching across the apps.
Hi Bobby, I’m trying to follow your model and I’m creating the domain in a plugin. However, I have some issues with joda time. Seems that I can’t use LocalDate or any joda time type in my domains. I configured joda time as declared in the documentation, but doesn’t seem to work in a plugin, but works in a normal app. Do we have to stick with the built in gorm types when trying to do this? Or is there a workaround?
Regards
How do you have the JodaTime plugin configured in your domain plugin? Do you have it listed in “dependsOn” or in BuildConfig?
I have it listed in BuildConfig, not in dependsOn
Hi, one more silly question.
Is it possible to run integration tests on a domain class plugin? I have created my domain classes as a plugin, but there are some logic that can not be unit tested because I’m using HQL instead of criteria.
Nevermind, I figured it out.
Hi Bobby,
thanks for your great article.
Maybe you have some insight if the following is possible and makes sense:
Application A, the frontend, is connected to a database and should be able to fetch all classes defined in sample app-core via Gorm,MySQL and put some tasks on a message cue, e.g. Rabbitmq or amazon sqs including some kind of serialized version of my domain model.
Application B, the backend should then be able to read from the message cue and deserialize my messages back to my domain models defined in sampleapp-core and run a task for each message. Application B should not have any Database access.
E.g.: app A authenticates users found in its database and allows them to send an email.
The email domain class is serialized and sent to the message que. an instance of app B picks up the scheduled email to send and reprocesses it.
Therefore only app a will have access to the user credentials while instances of app B are just smart enough to send emails.
So, can I just ‘disable Gorm’ for App B?
Thanks, Jan
Where do I declare my data source.groovy?
Hi Bobby,
Thanks for the great article as this was very useful for me and just started a project in which I’m implementing this design.
One question I have though is how do I get the database to update it’s columns when I change a domain class in the app-core plugin automatically without having to re-run my app-web project.
Thanks,
Danny