tags:

views:

309

answers:

3

We are using Maven to compile our project on a build server. We update our sources from SVN and then run "mvn install" from the project folder, building a jar we then deploy to our production servers.

To save time on compilation, we keep the compiled classes before we recompile (in the target/classes folder maven creates). This way, Maven only needs to recompile new or changes java files.

But there is a problem with moved/deleted files: the SVN update removes the .java files from the sources path, but Maven doesn't remove the compiled .class files from target/classes. Same goes for files which are deleted from the main/recourses folder. So, the deleted/moved classes and deleted resources still end up in the jar file we deploy to our production servers, and this causes problems.

I know we can "mvn clean" to get rid of any compiled files, but this way we need to recompile the whole project on every build, which costs a lot of time.

Does anyone know a way to remove obsolete .class files and resources before or during Maven compilation?

A: 

I don't think it possible. Look at javac documentation

javac determines whether the class file is out of date. If the class file is out of date, javac recompiles the source file and uses the updated class file. Otherwise, javac just uses the class file. javac considers a class file out of date only if it is older than the source file.

Maven compiler plugin (or ant task) doesn't do more than javac does.

I strongly recommend using clean target. Not using it might cause a lot of problems especially if you instantly deploy your artifact to production (like. javac relying on file timestamp is fragile, some resources might be filtered etc.)

If you have problem with build performace, try to find other solutions - e.g. divide your module into smaller submodules.

cetnar
+1  A: 

So, the deleted/moved classes and deleted resources still end up in the jar file we deploy to our production servers, and this causes problems.

You really should perform a full clean build when building artifacts that are going to be deployed to your production servers. It's not only a best practice for reproducible builds (as mentioned in Hudson Best Practices for example), but, more important, it's the only way to prevent runtime errors with multi modules builds (unless you use the maven-incremental-build plugin). Imagine the following situation:

module-parent
|--- module-api
`--- module-impl

The API module defines interfaces that are implemented by the IMPL module (which thus depends on the API module). If you change the API module by modifying a method signature and doesn't change anything in the IMPL module, performing a build from the parent module will succeed, the IMPL won't be recompiled and the whole thing will break at runtime (see this discussion about this behaviour). What you are currently doing is really not safe!

Does anyone know a way to remove obsolete .class files and resources before or during Maven compilation?

I'm not aware of anything doing that. And as I said, your current practice is not safe. You should change it, at least at the continuous integration server level and especially for "production builds".

Pascal Thivent
A: 

Alexander Malfait,

If your problem is just in an integration environment, i join my mind with Pascal Thivent, cetnar,

However, your problem is all the same a problem in other contexts. Indeed, in developpement phase, I found very bad to do clean systematically to avoid this kind of problem. I think that Maven should do a differential between source and compiled in order not to act as a blind when you want juste compile. Ok Javac doesn't do it but Maven is not javac. It's a over-layer of javac. So, it could be its role.