5

My company has elected to go with IntelliJ for development and deployment to a local Tomcat server. I have been doing my development on gVim, and have no desire to change.

When we were using eclipse I was able to have eclipse republish resources when the file was changed externally. ( I beleive the setting was Refresh using native hooks or polling) This was wonderful because I prefer to use command line tools to integrated ones.

We are using IntelliJ to manage the server, which I'm okay with, however I would like to not disrupt my current workflow.

I know IntelliJ stays in synch pretty well, and will update the files when I focus on it, and refresh them when I leave the frame.

Is there a way to have intelliJ update resources that have been changed externally ( Gvim, cli git... ext ) without moving to it?

BenJamin
  • 783
  • 4
  • 17
  • Run the server standalone. – Stefan Oct 04 '14 at 18:21
  • How would this help? – BenJamin Nov 03 '14 at 20:06
  • @BenJamin, have you ever found a solution for it? – Michael Radionov Sep 17 '15 at 11:36
  • @MichaelRadionov not a good one, and certainly not one in intelliJ. My work around was to set up a grunt task to watch the project files and move them over manually to the exploded war the tomcat was serving. It works well enough for what I am doing. But I do have to turn the grunt task on and off when I switch between projects. reading your requirements it sounds like that might work for you too, I'll put together an answer to my question and we can see what you think. – BenJamin Sep 18 '15 at 19:48

3 Answers3

2

Sadly, I have been unable to find a way to monitor external changes and update a Tomcat server inside IntelliJ.

I have implemented a workaround using grunt. ( a node.js task runner )

The theory behind this workaround is simple:

  • Tomcat serves an exploded war
  • grunt watches my front end files
  • when a file changes grunt moves my front end files into the exploded war

Some benefits of doing it this way are:

  • works for any external editor/tool/ect (vim, sublime text, nano, cli git, and any other you can think of)
  • you don't need to move into intelliJ to get your resources updated.
  • no java required to get this solution set up.

Down side is

  • you've got an extra process running.
  • you have another tool to deal with.
  • you need to deploy the front end stuff in exploded wars ( not really that bad in my opinion )

To learn more about grunt and get it set up you can visit gruntjs.com.

This workaround uses two plugins

  • grunt-contrib-copy
  • grunt-contrib-watch

First you set up a task that copies your files into your exploded war. This will use the grunt-contrib-copy plugin and will probably take some finagling, but it isn't too bad. Mine looks like this:

copy:{
    webfilesToOutdir:{
        files: [
            {expand: true, src: ['WebContent/**'], 
             dest: '../out/artifacts/attensity-q/exploded/attensity-q.war',
             rename: function(dest, src){
                    var ret = dest+"/"+ src.replace('WebContent/', '');
                    return ret;
                }
            }
        ]
    }
}

Next you will need a task to watch your files and run the copy when something changes. This will use grunt-contrib-watch and again it is nothing to bad, you will just need to adjust the paths. Here is mine:

watch: {
    web: {
        files: ['WebContent/**', '!WebContent/less/**'],
        tasks: 'copy:webfilesToOutdir',
        interrupt: true
    }
}

I hope this helps. I've been using this solution for some time now and it has done its job pretty well. Good luck, gentle men.

BenJamin
  • 783
  • 4
  • 17
  • Thanks! I've already tried this solution, but with grunt-sync plugin, which copies only modified files. It was working pretty slowly, maybe ~10 sec for one run. I'll try to test it with simple copy, but we have a lot of files to update. I think it's also worth to minimize the number of files to watch, but I'll definitely try it again. Solution actually is really nice and simple, but I am worried that Idea does some extra things when it updates resources, not just copies from one folder to another. – Michael Radionov Sep 18 '15 at 20:30
  • I guess it may depend on your settings but, at least for us, I don't think idea does anything fancy when it updates resources. ~10 seconds for one run is way to long, I wouldn't be able tolerate this if it didn't update in the time it took me to alt+tab from vim to chrome and hit refresh. I have not tried it with grunt-sync, maybe copy, despite moving a ton more, is faster, or maybe you just have more files than we do. ( it would surprise me, ours is also a pretty big project). either way.. Good luck to you. and I hope this helps in some way. – BenJamin Sep 18 '15 at 22:52
  • After a few tests I was able to achieve better results using [gulp](https://github.com/gulpjs/gulp) (`gulp.src` + `gulp.dest` vs `grunt-copy`). For ~4k files (~40mb) Grunt does his job in ~12 sec, while for Gulp it takes ~4 sec. I am still experimenting, but that's already a huge boost. – Michael Radionov Sep 21 '15 at 15:17
  • Glad to hear it! wow, 40mb is a huge amount, no wonder yours is taking longer than mine :) – BenJamin Sep 21 '15 at 19:12
1

Note: solution provided works for Ubuntu (14.04) + Sublime Text 2/3

I've ended up with a very tricky trick but I'm very happy about it. IntelliJ Idea updates resources in two cases (if enabled in settings):

  1. When IDE window loses focus
  2. When pressing a button in the Run section or using a shortcut for it Ctrl+F10

So I've started with the first case looking for an utility for my operation system (Ubuntu 14.04), which can focus IntelliJ Idea window and the un-focus it, to make it update the resources. I've stumbled upon xdotool, which allows to get the id of the window by it's title and to focus a window by it's id. I've created a simple .sh script:

current_id="$(xdotool getactivewindow)" # get id of current window
idea_id="$(xdotool search --name 'IntelliJ IDEA')"
xdotool windowfocus "${idea_id}" # switch to idea
xdotool windowfocus "${current_id}" # switch to current window

windowfocus just focuses the window, which means if the window is on the background or on another workspace, you won't get switched to it, you'll stay where you were, but the window will just obtain a focus. But it did not work with IntelliJ Idea, resources were not updating, seems that it wants full attention.

So I've tried to replace windowfocus with windowactivate - it switches to the window whenever it is (even if it is on another workspace) so it becomes focused, active and visible. But in combination with switching back to the original process, it produces like a visible switch between two windows (like when you Alt+Tab between windows), which is pretty noticeable, but it actually does it's job - resources get updated.

There was also a second option left - using a shortcut. xdotool has an option to send a keystroke to a window by it's id as well:

xdotool key --window "{$idea_id}" --clearmodifiers CTRL+F10

but it did not work, even in combination with focusing the window, also leaving behind an after-effect of a pressed Ctrl key. There is a section Sendevent Notes in xdotool docs, telling that a key-event generated by xdotool sets a special flag, and as a result an application which receives the event may analyze it for a flag presence and ignore the event, which might be the case with IntelliJ Idea.

After some research I've found another key-sending tool - xvkdb - and it worked like a charm, because I guess it uses another way of sending/generating a key event:

xvkbd -window "*IntelliJ IDEA*" -text "\C\[F10]"

When run alone this command keeps the focus on a Intellij Idea window, I've used xdotool to bring the focus back to a current process. Here is a final version of the script:

current_id="$(xdotool getactivewindow)"
xvkbd -window "*IntelliJ IDEA*" -text "\C\[F10]"
xdotool windowfocus "${current_id}"

To integrate it with Sublime Text 3, which I use as a code editor, I've installed a plugin Sublime​On​Save​Build, which can run a custom build (terminal command or a script) when one saves a file in Sublime Text. Here is a simple build setup:

{
    "shell_cmd": "/path/to/script/idea_update_resources.sh"
}

So now I have an Intellij Idea open on another workspace, and when I save a file in Sublime Text, resources get updated by sending a shortcut to Intellij Idea window. The time of focusing the windows using this implementation is not noticeable as I can say. As a result it is way more faster then Grunt or Gulp task, I would say instant, because IntelliJ Idea does an update by itself, and also it is safe to use in case if IntelliJ Idea does some extra operations when updating resources. Thanks @BenJamin for the question, hope it will help somebody.

Update:

After using this setup for a while it is not working as expected: if IntelliJ Idea is on another workspace or it's interface is fully covered with another window, the solution with xvkdb will unfortunately fail and won't execute resources update. I switched back to using windowactivate.

Michael Radionov
  • 12,859
  • 1
  • 55
  • 72
  • Nice solution! I also tried an automated widow activation and found it too intrusive. Sounds like you got a winner with xvkdb. I may even play with it a bit. Either way, thanks for taking the time to post your solution! – BenJamin Sep 24 '15 at 15:53
0

WebStorm — another IDE by IntelliJ — has something that looks a lot like what you are describing.

Maybe your IntelliJ IDE has it too.

enter image description here

romainl
  • 186,200
  • 21
  • 280
  • 313
  • I've read about it a bit and it seems to be the opposite of what we are looking for - it allows to run external tools from within IntelliJ Idea. What we need is to run Idea's built-in tool from external tool/editor. – Michael Radionov Sep 18 '15 at 14:57
  • yeah, not quite. I did pull vim into intelliJ to see how that felt. turns out it was less than ideal, for me at least. Thank you for the suggestion. – BenJamin Sep 18 '15 at 19:52