Keeping Project JAR Files Up To Date - java

When using multiple APIs in a single project, the JAR files required for each API are added to the project in addition to other needed libraries such as Apache Commons, logging, etc. that are already used by the project. This sometimes results in a large number of jar files.
When a certain API or library is no longer used, it would be nice to remove the JAR files associated with it. However, there is a risk that another API or library requires it. This would NOT always become apparent during the building of the project. Sometimes, JARs that are missing throw errors only at runtime.
I have the following questions:
What is the best way to deal with this issue? In other words, be able to remove JARs without running the risk of runtime errors later?
I have been told that Maven solves this problem. Does it? Would it work if the external APIs used are not Maven-based? Would I be able to remove JARs without worrying about runtime errors? Do I need to rewrite my entire project to be based on Maven?
How do non-JVM platforms deal with the issue of shared libraries and removing them? Is Java lacking in this area or it is a common issue for all platforms?

Yes I agree Maven could help you in this case. Basically in Maven compile & runtime dependencies for each artifact (jar/war/ear/etc) are declared on pom.xml file. If multiple dependencies depends on same artifacts the latest version is used -- for example:
A-1.0.jar -- depends on --> C-2.0.jar
B-1.0.jar -- depends on --> C-2.1.jar
Only C-2.1.jar is is included in your project.
If a required dependency couldn't be found / taken out, Maven build will automatically fail. So to avoid runtime dependency missing, you can declare a dependency in runtime scope to a particular artifact -- and when you no longer need it you just take it out

There is an old trick I used to use on UNIX many years ago, it might still work for you. First use UNIX "touch" to set the date/time on all your files to the current date/time. Then wait for at least one minute. Then run your application. Then run UNIX "ls -lut" to list all your files, but this time the ones that were not used will have the date/time set in the first step whereas those that were used will have a more recent date/time due to the "u" switch reporting the last used date/time.

Related

How can I control the dependencies of IntelliJ Scratch files?

I have a scratch file using guava collections, and I get some weird errors that I have to assume is due to the editor and the actual run environment assuming different versions of the guava collections:
Exception in thread "main" java.lang.IllegalAccessError: tried to access method com.google.common.collect.Range.<init>(Lcom/google/common/collect/Cut;Lcom/google/common/collect/Cut;)V from class
com.google.common.collect.Ranges
at com.google.common.collect.Ranges.create(Ranges.java:80)
at com.google.common.collect.Ranges.closedOpen(Ranges.java:114)
at Scratch.main(scratch_2.java:69)
Not that I can actually know that for sure because I also can't figure out how I'm supposed to see which version the scratch file is pulling in. I've removed guava from my project's deps ENTIRELY and the scratch file still works... WHY? Where is the library coming from??? The scratch run config is completely empty of anything that would dictate this:
And yet it still runs just fine. I discovered that if I delete the guava entries from my local ivy cache, it won't run anymore. If I then add guava back to my project's deps, it ends up in my ivy cache again, and then even if I remove guava from the project deps the scratch file is fine again. So does the scratch file just pick a random version or something? The ivy cache, which is at ~/.ivy2/cache/com.google.guava, looks like this:
But there's also that "jars" folder that has a guava-12.0 for some reason:
And again, I have no idea which version is being used, or why the cache has so many different versions of it. Any ideas?
One way that proved to be the simplest to me was to select "use classpath of an existing project module" (which has dependencies configured) in the run configuration dialog. This is useful if you want to pull out a piece of functionality from your project to play with in isolation but still use the configured dependencies.
I had a similar issue in PyCharm that I just fixed - so your mileage may vary here. It terms out that there was a Python virtual environment attached as the default to the project window (I had had multiple projects open in the same window - but evidently the first one became the default).
I dug into the list of interpreters, found the one I wanted and edited its properties, specifically Associate this virtual environment with current project.
I checked that box for the virtualenv that had the libraries I was looking for and this fixed the compilation errors in the editor itself.

How to use different version of a library at Runtime?

I have a java project where I use an external jar (not controlled by me).
Until now whenever that a new version of that library is out, I update
my project to use the more recent one, but now is required that the
project uses different versions of that library.
My problem is I don't have any clue how to do that.
How do I tell in java to make the imports according a version of a jar,
What I need to do:
int versionFlag = getVersion2use();
if(verssionFlag = 0){
use imports from last version
}else if(verssionFlag = 1){
use imports from last version 1
} else if(verssionFlag = 2){
use imports from last version 2
}
This is to be used at runtime!
This is usually something that a project will do at build time rather than dynamically at runtime.
That said, here's a good answer on how to add a jar to the system classloader dynamically at runtime, which is something you could work into your general logic above:
How should I load Jars dynamically at runtime?
With respect to imports, there's no way around the fact that you can't dynamically pick your imports. So if you're lucky the two versions have the same basic API. If that holds, add the jar to classloader as early as possible in your app and then develop like normal.
If the two versions have different a different API, however, then you're going to have to write some very convoluted code that tries building objects and almost ubiquitously catches all the many different class load / class incompatibility exceptions (such as ClassNotFoundException). Worse, you'll probably have to do this behind some sort of facade or factory architecture so that you can actually keep running software insulated from all these class loading shenanigans. In short, if the two have different APIs you may actually be better off writing two separate products.
At Runtime
Classes with the same name in the same package follow a first available rule. The first one that is on the classpath is the one that is used.
You can not easily do what you want at runtime without a wrapper program to move the libraries into and out of the system classpath before the Java application is started.
A launcher script/program that dynamically builds the classpath and only includes the version you need of each library and passes it to java -cp is the only way to do what you want at runtime.
At build time
If it is at build time, then just use something like the shade plugin in Maven to build an uberjar with all the required libraries embedded in a single .jar for each of the versions. So 3 versions would be 3 separate uberjar assemblies.
If you can do it at build time, you can use a dependency manager, like Maven.
It provides you with a means to be able to select which versions of which library you use at build-time.
If you need to do this at runtime, you might need to package all libraries in your project. You can use shading (see here) to make sure you don't get import issues, because when importing different versions of libs you end up with similar imports.
Shading can help you make for example:
com.foo.Class in jarv1
com.foo.Class in jarv2
To become
com.foo.v1.Class in jarv1
com.foo.v2.Class in jarv2
This will make sure your code can still use all libs you want.

Info about version dependancies of enterprise java libraries

I am new to enterprise application developement and trying to create a REST server with Spring REST, JPA taking to mySQL database and Javascript on the client side. As I see loads of opensource libraries doing specific task, I started off with using 'maven project' with different 'arch type' (which is nothing but predefined POM with relevent libraries as I understand) provided by Eclipse. But I often run into version mismatch issues, in many cases found specific solution to that perticular libraries in StackOverflow or other sites.
Hence I started looking for a information these version dependancies such as, this version of JPA works with that version of Hibernate library and so on. I checked maven repository of major libraries, I did not find such information so far.
My queries are:
Where can I find these information about the versions dependancies?
Are these pre defined POM in eclipse reliable? Who owns them, where can I get last modified dates on these maven 'arch types'? (I find the ones I choose having fairly old version of libraries).
If I have to start off on my own creating a Maven dependacies, where will I get information about what are the dependent libraries, for example, if I need spring MVC, for sure it needs java servlet library. I am worried becuase the maven 'spring-mvc-jap' arch type whooping 50 libaries as dependancies.(Coming from embeded domain, I find to too hard to digest :D). So not sure if it is the right way.
Please correct if I am missing anything in my understanding.
You can find this information, if you are using maven and some IDE you can go to the dependancy and make click un > and this will show the librarys used for this dependancy or if you want to use the console you have http://maven.apache.org/plugins/maven-dependency-plugin/examples/resolving-conflicts-using-the-dependency-tree.html this will show the same that the IDE.
After normally in the documentation of the library used, you can find some doc about the dependancy about this.
Other solution is get the .jar and use 7zip to see the POM and know the dependancy used.
And for finish my answer if the IDE tell you that you dont have x dependancy normally you have to add this because any of the other dependancy used have it (they used only for the compiling task), but sometime somes projet change a lots of code between the version .a to .b so you will have some problem using the version .b, at this moment i didnt find one good and easy way to fix this, only using the way that i told you (only if i found some problem in the compilation)
3> I am not sure how it works in eclipse but in IntelliJ IDEA when you start using some class without proper dependency IDEA suggest you to add proper dependency automatically. The same approach should be in eclipse.

Specifying classpath when executing another java program from within a java program

I'm looking at an application and it has the following statements
executeProcess("java.exe -cp { 500-characters worth of stuff } someProg");
This is done several times through the program, since this application launches other programs to perform certain tasks. The previous developers decided to just copy and paste again and again as long as it works.
The problems I have with this are
it's redundant. That classpath is copied a dozen times. I can refactor it and move it to a single location, so that's easy to deal with for now and makes life easier for the next guy that might have to maintain this thing.
everytime a program adds a new dependency, I need to update the class path. All of our libraries are stored in a single folder (with subfolders for different libraries), so I can't just use wildcards because they do not check recursively: -cp "path/to/lib/*
Currently I'm the only one maintaining our entire tool set, so if I add a library, I know what to do to make it work, but in general this seems like bad practice.
What are some ways to make these process calls easier to manage?
You can add it as an environment variable and then refer to that, if
that is feasible.
As you already suggested, you can refactor it to a
single location.
I have had good experience with using ant and maven-ant-tasks for launching java applications without managing the classpath manually. Of course, in order to do that you would have to use maven for build/dependency management or at least install your jars to a local nexus instance.
The end user needs to checkout a maven project that declares a list of top level runtime dependencies (transitive dependencies will be resolved automatically, for libraries that are maven projects) that also contains some ant scripts with targets that execute the application.
You will have to figure out how the java application will know the actual location of the ant scripts (an env variable maybe?), but it's an extremely superior solution to manual jar and classpath management.
This might look like a gargantuan task - and it kind of is - but the benefits of transparent jar version and classpath management are so huge, that I cannot even dare to remember how we did it in my current company before setting up the infrastructure for this.
Also, note that apart from installing ant (with maven-ant-tasks) and maven (with nexus configured) everything else you need to launch is on the SCM.

Can Java annotation do this?

I'm looking into a solution that displays the subversion revision number and last modification date in my application (written in GWT, therefore reflection is not available). Encode the revision in subversion keyword doesn't work as it applies only to the current file. Is there a better solution using annotation? (e.g., a separate class that's executed during the compile time, grab the latest revision # on the whole project and inject the revision and last modification date to the source code)
I kn
#SvnRevision("$Id$")
public class Foo {
}
Then your classes are all annotated with their version. You need to make sure the annotation is defined as having runtime retention so it can be queried at runtime.
EDIT
OK, since SVN doesn't have that feature, I'd write a Maven plugin to emulate it. Maven has access to the SCM information for every file so during the build phase you could have it do the same keyword expansion.
Annotations are not really designed for this. It's easiest to do it as part of the build.
Using Ant you can generate a file that contains the version information, include it in your application's JAR, load it as a resource on the server, and serve it out to the browser-side code by RPC. Ant can also do string replacement in files as it copies them, which you can use to include the version number in your application's HTML files (no need for RPC then).
No idea about Maven, but I would be very surprised if it could not do the same kind of thing.
Subversion still has the $Id$ feature, but it needs to be enabled explicitly using the svn:keywords property on the files (set it to 'Id').
See also: http://svnbook.red-bean.com/en/1.5/svn.advanced.props.special.keywords.html
So the idea of Jherico above with #SvnRevision would work.

Categories

Resources