最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

java - local tomcat server with grunt watch auto-reload - Stack Overflow

programmeradmin1浏览0评论

The project

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).

What I need

  • A solution which is not tied to only one IDE ( and should also work in the command line )
  • I don't want to deploy a war file only a dist folder.
  • I don't want to recompile java each time I change a client-side resource: js,css,html,images etc.
  • grunt should watch the files and do pre processing / concatenation / lint / tests
  • after the watch grunt should deploy the files to a local tomcat and autoreload the page
  • It MUST be fast! and I mean less than a second.

I looked at some questions, but I cannot figure out how to make it all work

The project

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).

What I need

  • A solution which is not tied to only one IDE ( and should also work in the command line )
  • I don't want to deploy a war file only a dist folder.
  • I don't want to recompile java each time I change a client-side resource: js,css,html,images etc.
  • grunt should watch the files and do pre processing / concatenation / lint / tests
  • after the watch grunt should deploy the files to a local tomcat and autoreload the page
  • It MUST be fast! and I mean less than a second.

I looked at some questions, but I cannot figure out how to make it all work

Share Improve this question edited Mar 3, 2014 at 21:51 Ilan Frumer asked Mar 3, 2014 at 15:00 Ilan FrumerIlan Frumer 32.4k8 gold badges72 silver badges84 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 9

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:

  1. 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.

  2. 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.

My strategy is for this kind of projects is separating client side from backend by restifying my backend. By doing this, I can use any kind of client for my backend service. This was the summary, let's go deep in to details.

Backend: Let say that you are using Spring MVC for your project. You can design your model and controller part first. Your url mappings should be in user friendly structure like;

/user/update/{userId}

You have services for different operations, and this means your controller does not depent on your views. You don't return a ModelAndView, you return json data from your services. You can use this service from web client, mobile client, or desktop client. I think, you have questions like "What about restriction part?". In this model, you won't use java sessions, you will also give authentication as service like Oauth or Oauth2. Simply, you have login form, user enters username and password. When click Login button, username and password send to backend and evaluated from db. You generate a unique token that has expire time. From now, you will do your request with this token. You can also define an interceptor to check this token validity for every request. You can keep this token in client by using local storage. Finally, you have authentication mechanism, and services. Those are don't depend on client applications.

Frontend: Let say that you have a client application that has much user interaction. You can use AngularJS for web app and Twitter Bootstrap for theming. For example, in article list page, you can make ajax calls on page load to your backend services. You can do that with AngularJS easily. Also, you can bind returned data to your page models. Ok, you ave client app and it is capable to make request to your services for getting specific data. For example AngularJS project, you can refer here. You can use yeoman to create an AngularJS project. You can also use grunt to minify, uglify, your static files, you can also have a look at here.

Summary:

  1. You can deploy your backend code separately from your client app
  2. You can develop multiple client applications for your needs. Today, develop web app, someday develop mobile app
  3. You will startup your backend, and then you will open client side app. You don't need any container or for using client side app. You can serve your client app by using web server like apache

Are you familiar with Grunt? You would accomplish most of what you're asking for with it, out of the box, if you configure it right.

  • You can split your tasks and run only the ones you'd like to run, i.e. only compile the resources relevant to the task(s).
  • Grunt is command-line based, and will run upon file changes (no IDE required).
  • The watch task won't deploy anything, it will just keep an eye on file changes and run tasks you have specified within it. Those are the tasks that will deploy concatenated, beautified/minified, linted, tested files to the directories you specify.
  • The speed of the build will depend on how many tasks you're running and how deep into the application the tasks have to chew to spit their output. If you want less than a second builds you'll have to split your tasks nicely and run only few at a time.

Here is one of my projects. It relies heavily on Grunt, is lean and fast. :)

This might not be a chewed-up solution you might be expecting for the bounty, but is a lead. Try solving some of the problems you're trying to solve and build up from there following my suggestions.

发布评论

评论列表(0)

  1. 暂无评论