0

I would like to define a version number in a main class in each jar file that is assigned at compile time, like what can be easily done in C with an #include statement with a value from an external file. I would like to only set a value in that external location once, so any jar files that get compiled/built until I change it gets that same value.

My first thought was to define it in a common class then simply reference it like this:

I create a Base.java file:

class Base
{
    public final static String version = "1.2.3";
}

Then I compile Base.java and jar it up.

And then I create a Module1.java file:

class Module1
{
    public final static String version = Base.version;

    public static void main( String[] args )
    {
        Module1();
    }

    Module1()
    {
        System.out.println( "Module1: "+this.version );
    }
}

But of course, this won't compile without importing Base class, so I insert this just before the Module1 class:

import Base;

And I compile Module1.java and jar it up, and execute it; and as expected it returns:

Module1: 1.2.3

So far so good. But then I edit the Base.java file and change the version value to something different, like, say, "1.3.0", then compile Base.java and jar it up.

And now I want to create a Module2.java file:

import Base;
class Module2
{
    public final static String version = Base.version;

    public static void main( String[] args )
    {
        Module2();
    }

    Module2()
    {
        System.out.println( "Module2: "+this.version );
    }
}

And I compile and jar up Module2, and execute it it correctly returns:

Module2: 1.3.0

Also good. But as a sanity check I expect (want/hope) Module1 to return the same results as before, so I rerun Module1, but Bogus! It returns:

Module1: 1.3.0

Any advice on how to pull this off? So the version in a module remains as it was at compile-time, not set during each session at run-time?

Mike
  • 103
  • 8
  • Hmm, this behavior is correct, you using same jar for Module1 and Module2, so what else do you expect? – Pham Trung Feb 02 '15 at 07:08
  • 1
    It's not *hard* to externalize values, but I'm concerned - why wouldn't you want to use your CVS (Git, Subversion, Mercurial, etc) for your versioning instead? It'd be a lot safer than placing the value into your source code. – Makoto Feb 02 '15 at 07:09
  • I think he'd like a different method that keeps the value that it had when it was compiled, which is trickier. Are you packaging the Base.jar with your Module1.jar? – Evan Knowles Feb 02 '15 at 07:10
  • Instead of updating Base.java, can't you update the source of Module directly? – aioobe Feb 02 '15 at 07:11
  • @EvanKnowles: There's not much sense in that. Git offers tags so you can see the exact version of code that you marked as a specific version. Subversion has magic markers that you can place into code (groan) that basically replicates this functionality in a sense. – Makoto Feb 02 '15 at 07:12
  • More directly, do you plan on using this value in your code for any other reason than simply keeping track of a version number somewhere in source? – Makoto Feb 02 '15 at 07:12
  • @Makoto I agree entirely, I was just wondering if there was any chance of getting what he'd tried to work. – Evan Knowles Feb 02 '15 at 07:13
  • In this example all three classes are compiled into separate jar files. – Mike Feb 02 '15 at 07:30
  • The Base class is only an idea, not part of my requirement (per se). The intent is to set the current version someplace, and any other modules that get compiled inherit that version until I change explicitly. – Mike Feb 02 '15 at 07:33

1 Answers1

1

In Java, the standard place for storing the version of a .jar file is the manifest file (META-INF/MANIFEST.MF), not a class file. Specifically, put this line there:

Implementation-Version: 1.2.3

See here for more details.

To access this information from your code, use the java.util.jar.Manifest class, and specifically the getMainAttributes() method.

yole
  • 92,896
  • 20
  • 260
  • 197
  • I use manifest files to specify the class-path and main-class information. But each jar file has it's own manifest. I'm hunting for means to create a single common location that all jar files can find that value. Can I import a value from another file external to the manifest files themselves? – Mike Feb 02 '15 at 08:19
  • You can't import anything in the MANIFEST file itself. However, you can update the build script that builds your .jar files (for example, using the Ant task) so that it would take the version from an external location (for example, a .properties file) and put it into your manifest. – yole Feb 02 '15 at 08:22