I have a maven based project which I need to deploy into a local tomcat server (for development).
Now, on the front-end, I want to have a grunt dev-build ( jslint, concat, karma, sass, etc).
I looked at some questions, but I cannot figure out how to make it all work
This may or may not work for you as I'm not sure if you want everything to be entirely integrated.
This method will let you run your Tomcat server, allowing you to make front-end changes with automatic reloading (plus any additional tasks you may want to run) and no Java recompiling/reloading in Tomcat. I use it and for front-end development it's extremely fast.
Summarized idea:
Run your Java application using any means (maven tomcat plugin, Eclipse Servers tab, etc). Run it on a standard port (e.g. 8080). I'll assume you know how to do this.
Use grunt, grunt-contrib-watch, grunt-contrib-connect, grunt-contrib-proxy. Run grunt-contrib-connect on a different port than tomcat, e.g. 9000. Setup grunt-contrib-proxy to proxy requests from grunt-contrib-connect server to backend tomcat on different port, rewriting the URL if necessary.
To get you started, here is the relevant parts of the Gruntfile.js (modify to your app):
// Watches files for changes and runs tasks based on the changed files
watch: {
js: {
files: ['<%= my.app %>/scripts/**/*.js'],
tasks: [],
options: {
livereload: '<%= connect.options.livereload %>'
}
},
livereload: {
options: {
livereload: '<%= connect.options.livereload %>'
},
files: [
'<%= my.app %>/**/*.html',
'<%= my.app %>/.tmp/styles/**/*.css',
'<%= my.app %>/images/**/*.{png,jpg,jpeg,gif,webp,svg}'
]
}
},
// The actual grunt server settings
connect: {
options: {
port: 9000,
// Change this to '0.0.0.0' to access the server from outside.
hostname: 'localhost',
livereload: 35729
},
proxies: [{
context: '/rest',
host: 'localhost',
port: 8080,
https: false,
changeOrigin: true,
rewrite: {
'^/rest': '/myapp/rest'
}
}],
livereload: {
options: {
open: true,
middleware: function(connect) {
return [
require('grunt-connect-proxy/lib/utils').proxyRequest,
connect.static('src/main/webapp/.tmp'),
connect.static('src/main/webapp/'),
];
}
}
},
To develop, you start your backend Tomcat app, then using a console, run: grunt serve. Make any front-end changes you want and they'll automatically be reloaded and any associated grunt tasks will run with every change. Your app will work as normal as all backend requests are proxied to Tomcat and frontend requests are handled with grunt-contrib-connect.
Your layout is almost the same as that of many projects. It's common, dare I say typical, for Grunt to process client-side resources, and Maven to build the Java backend. As @wallace-sidhree says, Grunt also does most of the things you need out of the box.
I suggest you read up on Grunt first. The part of Grunt which threw me for a loop was it's odd configuration structure, so the configuration guide is a must-read. In short, you need to load the grunt-contrib-watch plugin, and that plugin expects a particular Javascript object for configuration in your initConfig
.
A very simple example from the manual is
// Simple config to run jshint any time a file is added, changed or deleted
grunt.initConfig({
watch: {
files: ['**/*'],
tasks: ['jshint'],
},
});
Regarding Tomcat, putting the output of Grunt under Tomcat control, at least during development, is just going to cause headaches. For example, Tomcat will overwrite any client-side resources Grunt puts inside the exploded WAR whenever Tomcat explodes a changed backend WAR. And to avoid that you'd need to put client-side resources in a different WAR. But if you have to split them anyway, you're better off hosting the client-side resources with lighttpd or httpster, at least during development. That should help achieve your sub-second updates.
I'm not sure about IDE-independent auto-reloading of the page, I use JetBrains' Chrome extension for that; the other answers might cover it better.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With