Showing posts with label IntelliJ IDEA. Show all posts
Showing posts with label IntelliJ IDEA. Show all posts

Sunday, May 15, 2016

NPM module Browser-Sync in Java / Web projects

Browser-Sync is a handy Node.js based NPM module which can be used for a faster web development. Browser-Sync synchronizes file changes and interactions across many devices. The most important feature is the live reloading. We can use the Browser-Sync in Java / Web projects too. Cagatay Civici created a great video tutorial how to use this module with the PrimeFaces showcase. The PrimeFaces showcase has a built-in Jetty server which looks to the source folder src/main/webapp as the web context root. After the Browser-Sync installation via the Node.js package manager NPM
 
npm install -g browser-sync
 
we have to start the Jetty server for the PrimeFaces showcase at http://localhost:8080/showcase. Afther that we can use this URL as proxy for a built-in server included in the Browser-Sync. The Browser-Sync should listen to changes under src/main/webapp
 
browser-sync start --proxy "http://localhost:8080/showcase" --files "src/main/webapp/**/*"
 
As result, a default browser will be started at http://localhost:3000/showcase with the PrimeFaces showcase. The port 3000 is the default port for the Browser-Sync.

This approach works well until you have made changes in Java files. Java files are not web resources under src/main/webapp. In Maven projects they located under src/main/java. That means, changes in Java files will not be recognized. The solution is exploded WAR. An exploded WAR is a directory where the web application gets deployed from. Every application server can deploy an exploded WAR. For Maven projects, this directory is normally target/webapp. The Maven WAR plugin has the goal war:exploded too. If you have an IDE, you can configure your web application as an exploded WAR. I have blogged about Hot Deployment with IntelliJ IDEA a couple of years ago. In IntelliJ, you can automatically copy changed files (CSS, JS, HTML resources and compiled Java files) to the directory for the exploded WAR.


Now, if you refresh the browser manually, you will see the changes in Java classes too. But we want to do this better. We want to use the highly praised live reloading! To achieve this goal, set files to be watched as follows
 
browser-sync start --proxy "http://localhost:8080/showcase" --files "target/classes/**/*.class, target/webapp/**/*"
 
The output looks like
[BS] Proxying: http://localhost:8080
[BS] Access URLs:
 ---------------------------------------------------------------------
       Local: http://localhost:3000/showcase
    External: http://192.168.178.27:3000/showcase
 ---------------------------------------------------------------------
          UI: http://localhost:3001
 UI External: http://192.168.178.27:3001
 ---------------------------------------------------------------------
Now, I can do any changes in all important files and see something like in the console
 
[BS] Watching files...
[BS] File changed: target\webapp\META-INF\MANIFEST.MF
[BS] File changed: target\webapp\WEB-INF\classes\some\showcase\bean\SomeBean.class
[BS] File changed: target\webapp\views\someView.xhtml
[BS] File changed: target\webapp\META-INF\MANIFEST.MF
The browser page gets updated by the Browser-Sync automatically (which uses WebSockets by the way). If you have trouble with your IDE, you can use Gulp to rescue! Here my idea for a gulpfile.js (Gulp 4).
var browsersync = require('browser-sync').create();

// init Browser-Sync
gulp.task('browser-sync', function() {
    browsersync.init({
        proxy: "http://localhost:8080/showcase"
    });
});

// compile changed Java files by Maven "mvn compile"
// compiled classes will be transfered to target/classes automatically
gulp.task('java', function () {
    // use 'spawn' to execute command using Node.js
    var spawn = require('child_process').spawn;

    // set the working directory to project root where gulpfile.js exists
    process.chdir(__dirname);

    // run "mvn compile"
    var child = spawn('mvn', ['compile']);

    // print output
    child.stdout.on('data', function(data) {
        if (data) {
            console.log(data.toString());
        }
    });
});

// copy changes from src/main/webapp to target/webapp 
gulp.task('webapp', function () {
    return gulp.src('src/main/webapp/**/*', {since: gulp.lastRun('webapp')})
        .pipe(gulp.dest('target/webapp'));
});

// watch files for changes
gulp.task('watch', function () {
    gulp.watch('src/main/java/**/*.java', gulp.series('java'));
    gulp.watch('src/main/webapp/**/*', gulp.series('webapp'));
    gulp.watch(['target/classes/**/*.class', 'target/webapp/**/*'], browsersync.reload);
});

// default task
gulp.task('default', gulp.series('browser-sync', 'watch'));
This file should be placed in the project root folder. Now, you are able to execute the command (Gulp should be installed of course)
 
gulp
 
and enjoy the live reloading! Please consider, the Gulp java task. Maven only compiles changed files. It works very fast! Without changes there are nothing to be compiled - the output of the mvn compile looks like:
 
[INFO] Nothing to compile - all classes are up to date
 
If we make a change in one Java file, the output looks like:
 
[INFO] Compiling 1 source file to <path>\showcase\target\classes
 
Note: The server should run in reloadable mode. E.g. Tomcat has a reloadable option in context.xml. Set it to true to force monitoring classes in /WEB-INF/classes/ and /WEB-INF/lib for changes and automatically reload the web application if a change is detected. JBoss has this feature automatically if you start it in the debug mode.

I can also imagine some complex Gulp tasks, such as compiling Java classes in dependent JAR files, build JARs and copy them to the WEB-INF/lib folder of the exploded WAR.

Monday, October 14, 2013

Hot Deployment with IntelliJ IDEA

Recently there was a voting in the PrimeFaces forum PrimeFaces IDE Poll for the best IDE used to develop PrimeFaces applications. The most people voted for NetBeans. NetBeans and Eclipse are free IDEs. My favorite IDE IntelliJ IDEA Ultimate is not free and I think this is a reason why there are less people using it on the job. I thought it would be a good idea to show some nice features in IntelliJ. This post will demonstrate how to configure IntelliJ for the hot deployment when developing web projects. Hot deployment means you can change web resources or classes at runtime and the changes will be recognized immediately without server restart. An useful feature during development process. In the example, I will take the application server JBoss 7, but any other server can be configured in the same manner as well. A good introduction to IntelliJ and JBoss there is in the IntelliJ Wiki. For a general information regarding working with application servers in IntelliJ please refer this help page.

We assume, the application server is already configured. The next step is to configure an exploded WAR artifact for the web project. An exploded WAR is a decompressed web application archive, a directory structure that is ready for deployment on an application server. IntelliJ creates it automatically, but nevertheless, you should go to File --> Project Structure --> Artefacts and ensure that the exploded web application ends with the extension .war. If you use Maven, the exploded WAR is created below the target folder. More info on the help page.


You should also check if the Hot Swap is enabled. Go to the File --> Settings --> Debugger --> HotSwap and ensure that all checkboxes are checked and the radio button "Reload classes after compilation" is set to "Always".


As next step, click on the "Edit Configurations..." and go to the configured server. In the "Run/Debug Configurations" dialog, select "Update resources" in the drop-down "On frame deactivation". That means, when you switch to the browser, IntelliJ will copy resource files (JavaScript, CSS) from the source location (src/main/webapp) to the directory where it builds the exploded WAR to deploy.


Hot deployment for changed Java classes is resticted by JVM. E.g. the hot deployment for classes with changed method signature(s) doesn't work. But if you changed a method body, it will work. So, if you don't use JRebel which allows the hot deployment for classes being structurally modified, you can still rely on IntelliJ. All what you need to do for changes in Java classes is to recompile them. For that, you can go to the menu Build --> Compile or simple hit Ctrl + Shift + F9. After that, go to the browser and refresh the page to see changes.


Thursday, July 26, 2012

Merging with Subversion and IntelliJ IDEA

A common task - merge software changes from trunk with branch and vice versa - is an easy task with IntelliJ IDEA. There are a couple of ways how to do this in IDEA. Recently, I found the easiest way in my opinion. Assume, we would like to merge changes in trunk with branch.

1) Check out the branch as a working copy.
2) Go to the menu "VCS" --> "Intergrate Project".
3) Select the checked out branch project on the left side.
4) On the right side, select branch URL and revision number, where you want to merge to, for the "Source 1".
5) On the right side, select trunk URL (revision HEAD), where you want to merge from, for the "Source 2".
6) Uncheck "Use ancestry" and click the "OK" button.

 
You're done. Review made changes in the "Changes" view and commit them. Happy merging!