How Compile on Save works
The Compile on Save (CoS) feature is designed to make the "save / compile / run" cycle faster. This can be helpful for users accustomed to running and testing an application immediately after making changes to its sources. It utilizes *.class files produced while updating the internal data about projects. These files are always up to date, so there is no need to run Ant to regenerate them again before each run; they are simply copied from the NetBeans internal cache area to build/classes and the application is launched.
What Compile on Save is not
- CoS is not related to populating and updating the project class information cache, which is indicated by the label "Project scanning" in the IDE's status area.
- CoS is not related to error badges in the Projects view or error highlighting in the editor. All these features run out of the same underlying cache.
- CoS is not responsible for building JAR files.
How it works
The class files in the user directory (internal cache area) are always up to date; this is how the Java infrastructure works. The first time the application is run, the classes are copied to the build folder (e.g. build/classes) and the application is launched with this folder on its classpath. After any further modifications are made from the editor and saved, the class files are updated in both places: in the userdir and in the build folder. This makes any further application run even faster, since the application is launched immediately without copying anything (copying class files can take some time especially for large projects). The build folder is marked to contain files produced by the internal Java compiler. The Compile action is disabled since all sources are compiled automatically.
The classes produced by the internal compiler are not suitable to be put in a JAR, since they may contain special code to recover from compilation errors (see below). To build a JAR, Ant is used just as if CoS were disabled. At first the build dir must be cleared to avoid mixing classes produced by Ant with those from the internal compiler. This clean must be called explicitly (see Action Summary). Then the sources are compiled to the build dir and finally the JAR is created from them. The Compile action is enabled again. Saving modifications does not change files in the build folder until the Run action is called again to populate this folder with classes generated by the internal compiler.
Here is quick summary of exactly what the actions do:
- Run, Run File - the class files are copied from the userdir to the build folder if it was empty or contains class files produced by Ant. The build folder is added to the classpath together with JARs and other class files the project depends on, and the application is launched.
- Clean - the content of the build folder is deleted.
- Clean & Build - this action behaves like invoking Clean and then Build, i.e. the output folder is cleared and then Ant is called to produce class files.
- Build - the build action works only when the build folder is populated by classes produced by Ant, and will create a JAR. The user should call Clean first if the build folder contains classes produced by the internal compiler, to avoid mixing the files in one JAR. A warning dialog will be shown in this case, to let the user decide whether to call clean first, or disable CoS.
- Compile - the compile action is only available if the build folder contains classes produced by Ant. Otherwise the action makes no sense, since classes are compiled automatically.
Errors in sources
When developing an application it is very common that the code is not compilable all of the time; some parts of the code are not yet finished or are missing completely. The internal compiler can therefore compile sources which are uncompilable by external javac. Any code containing an error is simply replaced by code throwing an exception. The IDE also shows a warning before running a project containing errors. A consequence of this approach is that classes produced by the internal compiler may not be suitable for inclusion in a production JAR, which is why the IDE tries to prevent this from happening.
"Need to Compile" badges
The Need to Compile icon badge (a little wrench next to the node in Projects) is shown whenever the class file is not up to date, such as when the source file was changed after the last compilation. If the build directory is populated by classes produced by the internal compiler (e.g. after Run is selected) this cannot happen: compilation is always performed after the file is saved. If the build directory contains classes generated by Ant (e.g. after Clean and Build) the sources need to be compiled explicitly to get rid of this badge. The cause is described earlier: the class files in the build directory are not updated upon save in this case.
After external changes is necessary to do Clean & Build so the changes are propagated correctly to the Java infrastructure.
When there are two projects, one depending on the other, the setting of the launched project is significant. When the main project (the depending project) has Compile on Save on and is launched, the internal compiler generates classes in all projects the main project depends on (their settings are ignored). And vice-versa: when the main project has CoS off, Ant is used to compile all the projects in the dependency tree.
When CoS is not appropriate
The Compile on Save cannot be used in some specific cases. For example:
- The build script contains additional actions added by the user which are necessary for running the application. CoS does not use Ant to launch applications so these additional task would not be performed.
- There are important files in build/classes. CoS in not usable when there is another task (another program, or a modified Ant script) producing some files in the build folder, as this folder is cleared before build (see the Action Summary).
- Generating JAR: it is better to turn CoS off when user wants to build JAR periodically and run the application at the same time. When CoS is enabled the build folder needs to be cleared before building the JAR so there is significant slowdown in this case.
How to turn it on/off
Compile on Save is a project-specific option. It can be enabled/disabled in project properties, on the Compilation tab. By default it is on for all new project. For projects from NetBeans 6.1 or earlier the behavior is not changed (CoS is disabled). When the CoS setting is changed, the Clean action is performed automatically to avoid mixing classes.
Using Compile on Save in Maven Projects
In 7.4 and later
Compile on Save has been reworked for 7.4. With Compile on Save turned on, all Run/Debug related executions are performed by Maven itself, only the Maven phases defined along with the goals are removed. Eg. if your Run File mapping executes 'mvn package exec:exec' with Compile on Save turned on the IDE will only execute 'mvn exec:exec'
What are the advantages here?
- Everything is executed by Maven, just as it would on the cmd line.
- By skipping phase execution, the build becomes faster (but still a bit slower compared to the previous solution, there is one JVM startup for the maven build added)
- It works not only for tests and main class execution, but any Run/Debug action mapping and any project packaging.
What are the limitations of skipping Maven phases during execution?
- Compile on Save in the IDE will currently only perform a subset of your regular build. The more complex project setups might face the need to turn CoS off for that reason. Specifically, CoS will compile your java file and place appropriate .class file in the output directory. Including .class files generated by annotation processors. Please be aware however that non class files generated by the annotation processors are not included. That's important especially when developing on top of NetBeans platform.
- Along with the class files we also copy non-filtered resources to the output directory. If a filtered resource was touched or the pom.xml was touched we will include the phase into the execution to make sure everything is processed properly.
For executions with Maven 3.x, the project links between open projects will be established. Eg. if project A depends on project B at runtime and both have CoS turned on, the execution classpath will include B/target/classes and not the artifact in local repository. If some mandatory content is missing in B/target/classes, then the option at hand is to turn off Compile on Save in project B, so that A consumes just the final bits from local repository. A build of B is then required after any changes done to sources from project B. (In post-7.4 project B has to be both OPEN and CoS enabled to establish the link, see issue 237528)
PLEASE NOTE: The class files generated by the IDE are not 100% percent equal to those generated by javac. If you encounter an error, perform a clean build to get rid of these IDE generated files. Special care is advised when performing mvn deploy or any other activity that uploads your project's binaries to a remote repository or similar shared location. Also for any added or changed annotation processed by annotation processor, the IDE will only use the generated class files and will discard any other files generated by the annotation processor. Again a clean build is necessary after such a change. See issue 221781
When running Netbeans Platform applications in 7.4, please see issue 236324 NetbeansRCP (maven) can't run if not enabled "compile on save"
In 7.3 and before
In Maven projects, CoS is by default only turned on for tests (pre 7.2). In 7.2 it was enabled for application execution and in 7.3 it's turned off by default. Go to the project properties dialog, Compile panel, to turn it on for main source execution as well.
Resources (as defined in the POM) are not copied before CoS-enabled Run/Debug is performed, but immediately upon editing. They are copied into the relevant output folder (target/classes for main sources and target/test-classes for test sources). TargetPath, Includes and Excludes of the resource definition are taken into account. Resources that shall be filtered are skipped. If you have changed such filtered resources, please perform mvn process-resources or mvn process-test-resources.
The .netbeans_automatic_build stamp file is placed into the relevant output folder to tell the IDE's Java infrastructure to start compiling and copying the class files there. The stamp file is created upon project open and before executing any action in the IDE (with the exception of Build Project and Clean & Build Project). This should ensure that while working with the project in the IDE, projects that have CoS enabled will have their classes compiled and resources copied all the time. This is useful, for example, when using JavaRebel; or when using Tapestry invoked via mvn jetty:run.
For web applications, resources are copied from the output folder to the expanded web application. When using an IDE-managed server deployment, the webapp gets redeployed eventually (depending on the application server).
How to turn it off
The simpliest method is to invoke the project's Properties dialog and in the Compile panel uncheck the Compile on Save checkbox. That will create or update the $[basedir}/nb-configurations.xml file with the setting. However it only applies to this single project. If you want to turn off CoS for multiple projects or all of them, you should do the following
- if you know of a group of projects that don't work well with CoS, just set the property <netbeans.compile.on.save>none</netbeans.compile.on.save>, in the parent pom.xml and all child projects will inherit the value.
- to disable for all projects or to selectively turn off without modifying the workspace files (pom.xml and/or nb-configuration.xml), you can place the property in the ~/.m2/settings.xml file. After adding the property <netbeans.compile.on.save>none</netbeans.compile.on.save> to a profile there, just make sure the profile is always (or selectively) activated.
Applies to: NetBeans 6.5+