Copying only non-existent files in ant - java

I'm deploying my project to a web-server to be deployed with java Web Start. However, Web Start uses modification date to figure out whether to download the resources again (by default).
What I want is a way to only deploy those (jar) files that do not already exist. This is made possible by having build-version numbers on all my jars, so 2 jars with the same name have the same contents.
Notes:
The jar modification dates will always be newer in the build (which is why I'm getting this problem), due to downloading from svn or ivy
There's a way to do this using sun's download servlet, more files etc, but I'm lazy, don't need it, and this (simpler) solution will be more robust in the long term

If you are using ants copy task (you don't explicitly say you are), you could try the present selector: http://ant.apache.org/manual/Types/selectors.html#presentselect.
<copy todir="target">
<fileset dir="src">
<present targetdir="target" present="srconly" />
</fileset>
</copy>

You could attempt to set the granularity attribute very, very high, to basically disable the "copy files with the same name if the source file is newer than the destination" feature.

We had a similar problem, and I wound up implementing my own jar task to do what I needed. The Ant source code is a good place to start; if you're lucky you might be able to just subclass Ant's jar task. It's not nearly as difficult as it might sound, and was much more straightforward than the half dozen workarounds I tried or considered.

We solved this issue with maven and JavaFX and WebStart Plugin that keeps maven layout and version in the JNLP, and using "non-unique" SNAPSHOT will keep the same jar (ignoring the timestamp).
I know it's maven so not good for you, but someone may give it a try?

Related

How to Make Java .jar files be automatically found in any environment

I am trying to add an external library to my Java project. The library files are in .jar format, and every time someone tries to run the project in a different environment, they have to modify the build path so that their environment can find the .jar files.
Is there any way to make it so that the .jar files are automatically found by the build path? Maybe by specifying where in the project the .jar files are located?
Edit: Here is an example -
In my linux environment, the .jar files are located in:
/home/MyUsername\SomeDirectory\workspace\java_project_name\data
In my windows environment, the .jar files are located in:
C:\MyUsername\SomeDirectory\workspace\java_project_name\data
In the example above, the project root directory is "java_project_name", and the .jar files are always in the java_project_name\data folder. Even though this is the case, different environments can't seem to detect that it is always in the same path in relation to the project's root directory.
I have looked in many places on how to do this, and some people told me it isn't possible. This doesn't sound reasonable to me, which is why I am posting this question here.
Thanks in advance for your help!
you can add a ClassPath: entry in your manifest file of the main jar, and use relative paths. As long as the jars are found relative to the main jar it will work.
This issue was one of my main motivators to start using maven.
#YoK nicely quotes here the relevant reasons to this question https://stackoverflow.com/a/3589930/1493954
Here is one the relevant quotes from Benefits of using Maven
Henning
quick project setup, no complicated build.xml files, just a POM and go
all developers in a project use the same jar dependencies due to
centralized POM.
getting a number of reports and metrics for a project
"for free"
reduce the size of source distributions, because jars can
be pulled from a central location
This is a common problem for developement environments.
I myself use the following solution in netbeans [Hope so that it works in your IDE too]:
Create an Ant variable [for e.g. JAR_LOCATION].
Each and every JAR that you refer, must have it's location relative to JAR_LOCATION.
Now, in every development environment that you're gonna use, you can set up the same ANT variable and it'll automatically pick up the JAR.
You can see the example in the given snapshot of netbeans..

How to make JavaC copy existing class files to the target dir?

I hope somebody can give me an advice...
Problem
In source directory of my project some packages contain resources which are not ".java"-files. Now I need to put there compiled ".class"-files. The problem is that ANT filters them out when I am building the final JAR. ".dll" and ".png" files are not filtered out.
How can I achieve that everything is copied to the target directory?
I use following Ant task:
<javac srcdir="${src}" destdir="${temp}" target="1.5" encoding="8859_1" debug="${compile.withdebug}" >
<classpath refid="libs_path" />
</javac>
Background
I had to put in the final JAR multiple other OS-dependent JARs (SWT distributions). Only one JAR would be loaded at a program start. However it is not possible to let JVM load JAR from JAR without any special class loader. So I extracted all JARs to a package and JVM can load them now.
Why I want to put them under source (in Java package)? Because I want reference them relatively to the helper Java class:
org.example.swt_jars\
swt_linux_32\
swt_linux_64\
swt_win_32\
swt_win_64\
SWTJarsResources.java
Thanks!
Javac is a compiler; getting it to move files around is using the wrong tool for the job.
I would suggest simply using an Ant copy task directly before or after the <javac> task to move existing class files across. Something like:
<copy todir="${temp}">
<fileset dir="${src}">
<include name="**/*.class" />
</fileset>
</copy>
EDIT for Eclipse: what you're really trying to do here isn't have Eclipse copy the files, but for it to recognise that there are classes there that it needs to reference. So the simplest approach and one that I'd try first is to mark your src directory as a location that contains classes as well as one that contains sources.
I don't know if this would work for Eclipse - IDEA for example doesn't let a folder act as dual-purpose in this way. And again, it doesn't seem like it's quite the right tool for the job, as an IDE build is just collating the binaries it needs to run the app, and copying files around based on some project settings seems wrong somehow.
Ultimately I don't think your design is the cleanest, mixing classes in with source files is likely to be confusing. I appreciate that you're doing this because you want to use relative references, but perhaps you ought to abstract this out from the filesystem itself and use Classloader.findResource() (or probably getResourceAsStream()). This way you could arrange the files however you want, and so long as you run your application with both directories on the classpath, Java will be able to find the resource you're after. This will give you more flexibility in general, as well as solving this particular situation.

How to set up a subvresion repository from my netbeans project

I was recently given some code that was worked on by someone other than myself, and after lots of work involving hunting down external dependencies, and editing the build.xml file to get ANT to build things in a sane way, I'd like to now get the code into a subversion repository.
The team I'm working on is rather small, but the members on the team change often. So I want people to be able to start working on this code as quickly as possible. A simple checkout from the repository, and opening the project in Netbeans to have everything building and executing properly would be ideal.
How do I achieve this when there are external dependencies that are not going to be on other team members machines?
Should I place the libraries my project uses in the VCS?
How do I instruct subversion to not track generated files such as class files and jar files?
Should binary resources that are unlikely to change such as images and sounds be placed in the VCS? If not what would be the best way to distribute them?
Thank you.
1) yes. Anything needed to build and deploy the application and isn't generated by the build process goes into version control (yah, I know the maven fanz don't like that).
2) make sure everything that's generated goes into distinct directories that you exclude from version control.
3) see 1). Same thing. Same with project documentation, release notes, etc. etc.
The biggest problem of course are directory names which will be set in your IDEs configuration files and differ between development machines.
Not just the location of the project directories, but the IDE itself, JDKs and other tools, appservers, can all be different between machines. It's a constant problem.
I usually use maven cause you can have a repository for jars and dependencies this makes life easier, but since you have already refactor your code to use ANT maybe this is not what you want, to use subversion with netbeans then you might want to add another folder for jars like libs or something and then another for the binaries like audio etc. Also check for the svn plugin for netbeans it will add the ignore to the dir and just update java files.
To add files to ignore you can use
svn propset svn:ignore -F .
or you can look for the config file in your subversion home and add something like this
global-ignores=*.classs
Hope this helps

Easiest way to manage my CLASSPATH?

I'm beginning to play with Clojure a bit and my Java experience is pretty limited. I'm coming from the dynamic world of Ruby and OO, so the functional side of things is very interesting!
Anyway, as I discover libraries and various tools for use (and the tutorial files for the Pragmatic Clojure Book), everything typically calls for placing files in the CLASSPATH in order for Clojure to see the library for use.
Is there such thing as good CLASSPATH practice? Would I ever want to only have a CLASSPATH with just the external libraries of files I need or can I go ahead toss any library or file I would ever need in a directory and simply define it as my CLASSPATH and only require what's needed?
If it helps, I'm an OSX and Emacs user (Using slime and swank-clojure).
I recommend using leiningen and lein-swank to manage this. You can start a REPL in the directory and connect to it from Emacs.
Personally, I'm using a variant of a clojure-project elisp function by Phil Hagelberg, see source in this post to the Clojure group. It sets up the classpath appropriately for the project you'll be working on, then launches SLIME. (EDIT: You'll need to change the value which gets assigned to swank-clojure-jar-path to point to clojure.jar. I'm using (expand-file-name "~/.clojure/clojure.jar") as the default.)
To answer the question about having everything on the classpath all the time vs only throwing in what's needed: to the best of my knowledge, nothing will actually break if you take the first approach (I know I do that for experimental purposes), but apparently things might break with the first approach (see cjstehno's comment below) and in a proper project I find the second to be cleaner. At some point it'll be necessary to determine what libs are being used (and which versions of them), if only to tell leiningen (or maven) about it -- why not keep tabs on it as you go.
We are using Clojure and use a number of infrastructure tools, especially Eclipse (IDE) (http://en.wikipedia.org/wiki/Eclipse_%28software%29) and maven (http://en.wikipedia.org/wiki/Apache_Maven). maven manages libraries and jar dependencies so if you have a number of these and they are likely to grow start using maven.
In answer to your original question you can just put your jars in one directory and you can access them by name every time you run. But you will benefit from the tools...
If you are just exploring then Eclipse will probably manage your jar files fairly painlessly. You can add these to the project as required through the Build Path -> Configure Build Path option.
As your work progresses you will possibly wish to split it into Projects which Eclipse supports so you can add your (or other projects) to your Build Path.
If you use external Clojure libraries look to see if they have been packaged as maven projects (they will have a pom.xml file). The POM will give a list of dependencies.
#
The usual CLASSPATH practice for Java is to put only the jar files needed for a project into this projects class path, which means to have potentially different class paths for diffent projects. This is usually managed by the IDE as part of it's project properties.
Since you are using Emacs and thus probably don't have or use something like projects it might be more convinient for you to set up and use a single global class path for all your clojure related stuff or maybe even simply put all the needed jar files into the java2se/jre/lib/ext directory of your java installation.
The two main problems that could arise from having unneded jar files in your class path are: 1. it has a minor negative impact on the start up time of the JVM and 2. it becomes more difficult to make sure that you are not having classes with different versions in the same class path (i.e. different classes with the same package and name in different jar files).
Since Java SE 1.6 (or JDK 1.6) you can include class path entries by wildcard. If your class files live in .\bin, and your library jar files live in .\lib, then on Windows you could define your class path like this:
set CLASSPATH=bin;lib\*;
This will let you add jar files into the .\lib directory and they will automatically be added to the class path for new instances of the JRE.
See this link for details: Setting the class path
Prior to JDK 1.6 you had to add each jar file onto the ClassPath individually.
I just discovered this bit which I need to give a shot:
(setq swank-clojure-extra-classpaths (list "/class/path/1" "/class/path/2" "/class/path/3" "etc"))
clojure-contrib/launchers/bash/clj-env-dir has an interesting property that you can point it at a directory and it will basically include anything in there. In the past I've had a ~/classpath directory which I would dump any jars into and link any commonly used directories and it worked great. Very simple way to dump and use. Now I tend to use Maven clojure-maven-plugin and that works well also though can be a bit tedious when you just want to muck around with some ideas.

Whats best way to package a Java Application with lots of dependencies?

I'm writing a java app using eclipse which references a few external jars and requires some config files to be user accessable.
What is the best way to package it up for deployment?
My understanding is that you cant put Jars inside another jar file, is this correct?
Can I keep my config files out of the jars and still reference them in the code? Or should the path to the config file be a command line argument?
Are there any third party plugins for eclipse to help make this easier? I'm using an ant build file at the moment but I'm not sure I know what I'm doing.
Is there an equivelent of the deployment projects in Visual studio, that will figure out everything you need and just make an installer? I've used install4j before, and it was powerful if no where near as automated as .Net deployment projects.
Cheers.
There is no one 'best way'. It depends on whether you are deploying a swing application, webstart, applet, library or web application. Each is different.
On point 2, you are correct. Jar files cannot contain other jar files. (Well, technically they can, its just that the inner jar file won't be on your classpath, effectively meaning that jar files do not contain jar files).
On point 3, you certainly can reference config files outside the jar file. You can typically reference a config file as a file or a resource. If you use the resource approach, it typically comes from the classpath (can be in a jar). If you use a file, then you specify the filename (not in a jar).
In general, most Java developers would use Apache Ant to achieve deployment. Its well documented, so take a look.
(1) An alternative to ant that you may wish to consider is maven.
A brief intro to maven can be found here.
For building a JAR, maven has the jar plugin, which can automate the process of ensuring all dependent jars are listed in your jar's manifest.
If you're using eclipse, then download the maven integration as well.
(2) Another alternative is to use OneJar (disclaimer: haven't tried this myself).
The answers vary depending on what kind of thing you're building.
If you're building a library, it's best to distribute your work as a jar file. It's possible to refer to your jar dependencies via the Class-path attribute in your jar manifest, although I generally think that's uncool. That attribute was designed for applets and it's used infrequently enough in libs that when this technique pulls stuff into the classpath (particularly common stuff the user might already be using), you can get unexpected version conflicts. And it's hard to track down why you're seeing them.
Publishing a jar to a Maven repo with pom info to track dependencies is an excellent choice for libraries as well. If you do that, please publish your Maven coordinates in your docs!
If you're building an app, the two popular choices are to distribute a zip/tar/whatever of a deployment structure OR to use an installer program. If the program is a server-ish kind of thing, the former is far more common. The latter is more common for clients. Generally, the installer program is just going to lay out the deployment structure and maybe do some extra tasks like installing in OS-specific locations.
To build your deployment structure (aka "kit") you'll want to create a repeatable process in whatever build system you're using. Ant has copious examples of this and Maven has the assembly plugins that can help. Generally you'll want to include a jar of your code, any dependencies, scripts to start the program, maybe a JRE, and any other resources you might need.
If you want to create an installer, there are many options both free and commercial. Some folks I know have recently had good experiences with the free IzPack but check out your options.
You should try FatJar. It's an Eclipse plugin that with just a right click at the Project can build a JAR file with all you need to run the application, including the necesary third party JAR.
We use it everyday, in conjuction with JSmooth to create the executables, to deploy our software packages to our customers, and works like a charm.
Well, if you are speaking of deployment of a standalone desktop application:
Before we switched to web start we have been creating three deployment archives, one for windows, one for mac and one for other platforms.
On windows we have successfully used the Nullsoft Scriptable Install System (known for it's usage by the older winamp versions) and its ant task, although some drawbacks are:
It is only usable on windows AFAIR
You have to do some work by hand, i.e. customizing the wizard-created script AFAIR
It can create a windows installation with start menu entries on the other hand. There also exists an eclipse plugin for integrated NSIS shell script editing.
On Mac OS X there is an ant task to create an .app file from your java files so that you can start it like a native os x application. But beware of not writing any setting to your home dir and using the the application dir instead.
For others you have to expect they are in a un*x env and deploy your app with a shell script to start the application.
In any case you may have to deploy your custom policy file to get access rights for your application.
If you want to get rid of all the packaging and stuff you should seriously consider using web start. We have saved much time since switching to it, i.e. simplified our deployment process, takes care of updates etc.
Update 2014
Use maven assembly plugin, see section "Creating an executable jar"
Ant. It's not the best thing in the world, but it's standard, it's apache, and it works.
There's some good examples on the web how to make a simple build.xml for any, and it's got some features like the 'war' task that knows how to put all the basic stuff (classes, web.xml etc) in the jar file for you.
You can also tell it to pick up other config files and jars and it will happily do it.
It's also really smart about what to compile. You give it a directory, and it finds all the java files and builds them only if their classfile is out of date, so you get some of the traditional make functionality for free without much effort.
You could look at other java projects (e.g. JMeter, SquirrelSQL, JEdit, Cernunnos, etc.). Each package their applications slightly differently, so consider your goals when you review these.

Categories

Resources