Recompilation of dependencies with Maven - possible? Any performance boost? - java

I was thinking about dependencies in Maven. Maven downloads them but it is unknown for what target version of JVM are they compiled for and with what compiler. This raises two questions:
Would dependency recompilation bring faster dependency libraries?
I tried to search for this, but have not found sufficient answer. I found out that for 1.6 there is Split bytecode verification, that is done when compiling with target 1.6.
There is also a question Are Java 6's performance improvements in the JDK, JVM, or both? where it is mentioned that newer versions of javac might generate more optimized code.
Is it possible with Maven to perform recompilation of depending libraries? Would it be possible to configure Maven to download sources, put there information about 1.6 target and perform mvn clean install?
I am aware of Maven Dependency plugin and dependency:sources goal. That could be used for source download.
There is also Maven Replacer Plugin allowing replacing of text in files. As stated in its Issue 58 there was implemented XPath support for it.
Would it be possible to implement it with these plugins for dependency and also for its dependencies to perform it? I am not sure on how to perform it on the dependencies - perhaps with Maven Replacer Plugin injecting the configuration into unpacked dependencies pom.xml?
Or is there a simpler way to configure target java version with build profile in user's settings.xml that would take precedence of project settings and therefore avoiding pom.xml modification?

The javac does next to no optimisations and those it has have been there from the earliest days. (And could even be considered historical) If you have code built by Java 1.0 you might find an improvement but anything from the last tens years is likely to be as optimal in byte code as it is today.
Most of the optimisation is done in the JVM itself, and you should find that Java 6 update 30 runs faster than Java 6 update 0 even for the exactly the same code.

Let's think for a moment what a Maven dependency is. In the most general sense, it's a piece of software developed by someone else, living its own life cycle that:
is packed in an archive,
which exists in a repository
under a version descriptor (group, artifact, version).
That's all Maven guarantees. Note that it even does not say it's Java (could be resources, or native libraries, for example). Not much. Far too little to demand automatic recompilation of dependencies.

Related

Distribution of java class library code

I need to put some old java class library code that I have into a repo, from where others can check it out and build it. You know, like any public repo.
But, I'm not sure what the best way to do this is in the java world. In old-fashioned projects, we just used to supply the build scripts and a list of dependencies. You gathered or installed the dependencies separately before running the build scripts.
But these days for many languages, you have package managers and the like that pull from remote locations and your build scripts need to include dependency fetching.
Basically, I'm not familiar with how java libs and programs are packaged.
Should I include the (dependency) libs in the repo? And update them whenever a new version is out?
Does java now have a package manager that will pull in the latest versions of the dependencies?
Do I leave it upto the people checking out to download the libs themselves before they run the build scripts?
I'd prefer it if the solution didn't involve installing a huge package manager. Gradle wants to pull in like 150MB+ of stuff and as far as I am aware, it isn't ubiquitous on java deployments.
Thanks.
Use Maven. I believe these days it's the #1 "package manager" (not a term that's usually used to describe it, but quite apt) by a large margin. It's built into Netbeans, IntelliJ IDEA, and I believe Eclipse.
However, it won't just "pull the latest versions" of your dependencies, since your application may break. Only the versions you specify. Therefore, you should periodically update (and test) your code to reduce incompatibilities when someone tries to use your library in an application which directly or indirectly pulls newer versions of the same libs (and they get into a bit of "dll hell"), or reduce your use of third-party libraries in general.
You should also consider publishing your library in a compiled form to Maven Central so that using your library would be as easy as adding a dependency to the pom.xml. The problem that Maven solves, after all, is not so much making it easy to build your library (since just bundling the dependencies gets you most of the way), but making it easy to use your library.

Maven and optional runtime dependencies

I'm starting to fix a java project that has used maven and while I've got the project to build, at runtime it fails with missing dependencies. I've had a look and the errors are missing optional dependencies of included compile time dependencies. I can go through and add these but it seems to me that I can have everything building and running nicely only for some piece of code that I missed to use a missing dependency and the whole thing falls apart.
What I really want to know is whether there is an automated way to find optional dependencies that I have chosen to not include. I have used mvn dependency:tree but this only shows the dependencies I have (not sure of the scope it checks) and I have tried mvn dependency:analyze but this seems to show dependencies it thinks I don't use and those that have been pulled down indirectly. What I cannot see is how to see a list of optionals I don't include.
Currently my method of working around this is to read the poms and try to work it out from there, but I don't see this as particularly robust.
For reference, I am fairly new to maven style dependency management and on the face of it like it, but this optional thing is a bit of a stumbling block for me. I understand that optionals stop me pullin down dependencies I won't be using, but it hasn't clicked for me how I can workout what optionals are available and that I do need.
I am using Eclipse Juno, m2Eclipse (also have maven 3.0.5 cli), java 6/7.
Anyone got any ideas of how I can do this better, or what I am completely overlooking?
No the things are - somewhat - just this way. Maven does not do dependency management, it allows you to do dependency management by offering tools to use and analyze them. So the work still is on the developers side. People often mix that up.
This is mainly caused by the fact that projects often have different deployment targets. As a result sometimes they collect a bunch of jar files which are copied once into tomcat and a different set of files for weblogic. So there might be a readme in your project that states what to copy prior to deployment of the maven artifacts. Or it is implicit knowledge - then you're doomed.
dependency:analyze works on bytecode not on sources. therefore it does not see what maven knows.
Maybe mvn help:effective-pom gives a better basis to analyze the whole thing? Or you could try to modify the dependency plugin to show that information as well. Maven plugins are not so hard to work with.
I'm not aware of a plugin that displays all optional transitive dependencies. But since the pom.xml files of dependencies are downloaded into the local maven repo you could do a text search there.
A while ago there was a discussion on optional dependencies as well: Best strategy for dealing with optional dependencies - it might be helpful too.

Finding out all conflicting packages/classes of referenced jars in an Eclipse project

I am currently dealing with a huge Eclipse project (not written by me). This project doesn't use any dependency management tools. It references hundreds of JARs.
Some of these JARs contain same packages (and classes), but in different versions. Currently, resolving conflicts works by manually (and randomly!) reordering these JARs in Order&Export (in Project Properties).
This was done for a long time now, and there are now lots of packages/classes with different vendors/versions/product-lines.
Reordering causes some parts of the project to fail while other parts start working, and oppositely.
Strangely, lots of orders do not cause build errors, but only runtime errors.
Can this mess be solved by an tool, which would suggest certain automatic order of dependent JARs?
Google for JarAnalyzer, that helps at least to figure how the dependecies are build up. Use the jars, your eclipse project is producing, as well. However you can not really automate this. Imagine one of your eclipse projects in needing bad-1.0.jar and another one uses bad-1.2.jar. Very often you can not replace the 1.0 one with the 1.2 one because your project wont compile any more. So in the long run you have to REMOVE outdated jars, switch to a "common version" amoung all subprojects and fix the compiler errors. And while you do that, switch to ivy or maven.
Do your jar files even have proper names or do you have 3 different versions of bad.jar which look the same in the filesystem but are in fact of different version? If so, start by renaming all relevant jar files to include the version number (can often eb found in the manifest file) ... heck I once did what you do and wrote me with JArAnalyzer, a bit groovy and some shell scripts a small tool that generated all the ivy files for the project.
you can use maven, ivy to clean the mess :) . And that spring doesn't work properly try this:first clean then build the project.
"Strangely, lots of orders do not cause build errors, but only runtime
errors."
This is not strange. As you wrote, classes are present in different versions, which does not necessarily means compilation error, but means different behaviour and different sub dependencies.
Avoid a "random" or "automatic order" approach. I would advise you the usage of Maven for handling your dependencies (in order to know precisely which library depends on which one). You will probably discover that many of the libraries you're including are not required, and that the dependency management tool will handle for you "automatically" all dependencies between dependencies, you will have however to add/force exclusion for specific libraries versions.
Much more, it will help you to simplify the code and eventually remove one line of code and 40 dependencies...(relying on a side framework misused such Spring or any other one).

What is the most elegant solution to managing various Java external libraries?

Perhaps the reason I stalled learning Java until now is because I HATE how Java handles external libraries. I'm stuck keeping them in one place, adding them individually, fixing problems with versioning and every time I move/rename them, and copying and writing the classpath over and over each time I release a Java application.
There has to be an elegant solution to all of this. I keep all of my libraries (regardless of task, platform, or other) in their own little folder inside a "lib" folder in my development folder, kind of like this:
Dev
-lib
+JS-jQuery
+Flex-Degrafa
-Java-Xerces
+Xerces-1.2.3
+More libraries
I can use either Netbeans or Eclipse for Java dev, but none of them provide a very streamlined (and not to mention idiot-proof) way of managing all of these.
A nudge in the right direction or an online article/tutorial on this would be greatly appreciated.
You can either use Ant + Ivy or Maven to manage your library dependencies.
If it is only dependency management you're after and you're happy with the rest of your build process, I would use Ivy, as it can unobtrusively manage your dependencies, leaving your existing build process intact. There is a plugin for Eclipse called IvyIDE that contributes your dependencies via a classpath container.
Maven 2 has a steeper learning curve but provides a much richer set of functionality for building your projects and Eclipse integration through m2eclipse or IAM.
Personally I use Maven as I have a large number of projects to work with and Maven is particularly suited to efficient development across lots of projects.
Have a look at the introductory documentation to see what works for you.
Ivy Tutorial
Maven Getting Started Guide
Netbeans 6.7.1's Maven support is quite good and comes out of the box with the IDE.
The Eclipse addon was frustrating enough that I gave Netbeans another try.
A third choice besides ChssPly76's options is to use Ant with the Maven Ant Tasks. I don't know if I'd call any of these solutions particularly "elegant," but they do spare you the need to manage your own lib/ directory and classpath variables.
If you're working on Linux you can install Java libraries with APT or RPM.
Otherwise, I normally check precompiled JARs into a lib directory in my project's version control repository and make sure the names of the JAR files include full version information. E.g. lib/foo-1.5.6.jar, not lib/foo.jar.
To avoid having to manually set the classpath before running your app, you can set the classpath in the Manifests of the JARs themselves to define the dependencies of each JAR file. The JVM will follow all the dependencies when loading classes.
Maven is often more trouble than it's worth, but the ability to open a maven project directly into IDEs such as IntelliJ is excellent. For example, IntelliJ will download all dependencies and have them available without having to run a build first, or an mvn command and then a project refresh. It also isn't necessary to re-generate the project every time a dependency is added. I work with a number of Eclipse developers who switched to IntelliJ for this alone.
However, one shortfall of Maven is that many libraries (or versions of libraries) are not available on public repositories. Therefore it is often necessary to set up a local repository such as archiva. In ant, it would just be a matter of adding it to the lib directory in the repository.
Maven can also attack when you need to do something that maven doesn't directly support via a plugin. What would normally be a few lines of ant can often turn into a morning's worth of work.
Finally, buildr is an excellent way of using Maven's dependency management and plugins, while also supporting ad-hoc tasks.

Maven replacement?

What would you suggest as a replacement to the Maven Java build toolset? Just plain Ant scripts? SCons?
It depends on what you use anyway. Maven 1? Maven 2? I find Maven 2 decently documented, and quite powerful, when used in combination with Ant tasks and some home baked Java plugins.
There are Ant tasks to use Maven features from Ant: http://maven.apache.org/ant-tasks/index.html . So you don't really need to write your own "library".
And you can call Ant from Maven: http://maven.apache.org/plugins/maven-antrun-plugin/ .
You can also script things using Groovy for example: http://groovy.codehaus.org/GMaven+-+Executing+Groovy+Code .
Or just write Java code for the custom bits you need: http://maven.apache.org/guides/plugin/guide-java-plugin-development.html .
There's no reason not to mix and match, when you can do it ;)
While I like the idea of Maven, I always find myself fighting it for anything but the simplest configurations. Its architecture is plugin-based, and the quality of the plugins varies widely. Documentation is sketchy at best; half the time I can't figure out if the doc I'm reading is for Maven 1 or 2. And how often have you had to resort to using the maven-ant-plugin to do something basic?
I've been using Apache Ivy for about a year now, and I'm pretty happy with it. There is a bit of a learning curve though. But there's an active mailing list, and the author is very responsive.
What I ended up doing was writing a "library" of a few simple Ant targets such as "resolve", "compile", "install", etc. that expect things to be in standard Maven places (such as src/main/java) and then <import> the targets into my various projects. This way you get the best of both worlds- Maven-style configuration, and all the power of Ant.
I'm fond of using Ant with Ivy. Ivy uses Maven repositories to fetch library dependencies without forcing you to change your entire build system to suit Maven.
I've been using buildr for some of my projects. Very terse and readable build scripts (no xml) and it uses maven repos (with trivial effort, maven 1 and maven 2).
I was looking for something post-maven1 to work on for some projects and m2 wasn't all that appealing. Maven had already left all m1 users high and dry with the need to redo all of their build systems (and some of mine cannot be expressed in m2 as far as I can tell).
I really like using ant4eclipse - you set up your project dependencies in eclipse as normal and you can write a single ant script that'll build all the projects in the right order.
For third-party libs, you can either set up a single eclipse project containing (and exporting) all of your jars [I DON'T RECOMMEND THIS], or a separate project for each third-party lib, exporting the jar. [I recommend the latter b/c you can track project->third-party deps and upgrade parts when needed.]
I would go with buildr, if i am expecting complex build targets in my build. The benefit is, you are not dependent on any particular library at all. You have all the APIs from Ruby to do whatever you want; unlike Ivy in which case you are still tied up to ANT. Effort of migration to Ivy is worth if you want to introduce library dependency to an already established ANT based build mechanism which does all the operations you want to do.
There are at least three different parts of Maven: the repository, the implementation independent lifecyle and the conventions for a default project. Using Ivy provides only the repository.
I've not used it but I think that easyant is designed to be a more complete replacement to Maven. It uses Ivy as the repository but then adds conventions and standard modules.

Categories

Resources