Put version to my java application - Netbeans - java

Is there any way that i can give a version number to my application in netbeans.And then access that version number inside my code.
Something similar to the Assembly number that we use in .Net.Is there anything like that in java or in netbeans...?

Define an Implementation-Version in the manifest of the Jar at build time. It is common to use some form of the date as the version number. E.G. 14.07.28
The value can be retrieved in code using..
String version = this.getClass().getPackage().getImplementationVersion();
<tstamp>
<format property="now" pattern="yy.MM.dd"/>
</tstamp>
...
<jar
destfile="build/dist/lib/${jar.name}"
update='true'
index='true' >
<manifest>
<attribute name="Created-By" value="${vendor}"/>
<attribute name="Implementation-Title" value="${application.title}"/>
<attribute name="Implementation-Vendor" value="${vendor}"/>
<attribute name="Implementation-Vendor-Id" value="org.pscode"/>
<!-- This next property is retrieved in code above. -->
<attribute name="Implementation-Version" value="${now}"/>
</manifest>
<fileset dir="build/share">
<include name="${package.name}/*.class" />
<include name="${package.name}/*.png" />
</fileset>
</jar>
This comes from a build file for a project I have open at the moment. The relevant attribute is the last one in the manifest section.

In my JavaFX app created in Netbeans, I can set the build version (Implementation version) in the Project Properties window shown here:
This number is then used everywhere, for example it is automatically inserted into the filename of the installer. It is also the number retrieved by this.getClass().getPackage().getImplementationVersion(); mentioned by the accepted answer.

I don't know about .NET assembly numbers, but if you're creating a web application you can certainly put a version number into the manifest of your WAR file.
Any Java package can have a build info text file added to it so you can tell these things.
Your version number could be a build number from Ant, a version number from Subversion, or a combination of the two.

Related

Use ENV Variables only in build mode

I have JAVA library that I am working on and I am using Ant build system, I am trying to generate a .jar file from and using in another application, what I am trying to do is to enable some specific ENV variables only in Debug build and have them disabled in production/release, and I was wondering how can I achieve that?
In my build.xml I have a property called "debug", which is boolean.
In C/C++ You have the NDEBUG macros where you can define what you will exclude/include in debug mode,
is there something similar in JAVA?
I have tried to read Ant documentation, I see that they use properties but the documentation doesn't state exactly how you can pass those properties into the source code, In fact, I tried to do that but with no success.
As mentioned by #Joachim Sauer above, Java does not feature conditional compilation. You can argue either way for this being a good feature, but it's not available.
What can you do, then?
One method you can use is to write information into the jar's manifest.
For example, you could include the build version and your debug flag like so:
<jar destfile="my.jar" basedir="build/classes">
<manifest>
<attribute name="Package-Title" value="My Package Title" />
<attribute name="Package-Version" value="${build.current.version}" />
<attribute name="Debug" value="${debug}" />
</manifest>
</jar>
Then, in your code, you would attempt to read your own jar's manifest: Reading my own Jar's Manifest
Another simpler option might be to include a properties file in your jar, and just read that. You can use the ant task 'echo' to write out a properties file before the jar task:
<echo file="build/classes/my.properties" encoding="ISO-8859-1" append="false">
Package-Title: ${package-title}
Package-Version: ${build.current.version}
com.example.app.debug=${debug}
</echo>
Then, you can just open "my.properties" in the code as a resource, and use that.

Classpath length when running 32 bit java with ant

We work on rewriting the build system for a software company. Their build has lots of generators, that use various 3rd party deps, one of them is whole Weblogic. We have a "depchain" pom, that consists of all weblogic dependencies. When we run some kind of generators with this depchain in classpath, we fail on CreateProcess error=206, The filename or extension is too long on 32 bit JVM, but everything works well with 64. It's quite obvious, that it fails on the length of the classpath, because every jar in the depchain is the absolute location within .m2 folder (previously they did not have the understanding of binary repository and the classpath was a simple directory). We execute generators with simple antrun plugin executions. Is there a way to make it work on 32bit java, besides trimming the classpath?
UPD After a day of sweating I finally made it working using #Evgeniy Dorofeev 's idea. I couldn't use mvn plugin because the part of creating the artifact I run in, is executing this generator. So I had to use ant to build a manifest only jar that contains this giant classpath string. The issue that the classpath string used absolute paths, and I had to convert it to relative (MANIFEST.MF format). It was a headache of it's own:
<var name="relative.classpath.property"/>
<for param="curr.dep" list="${combined_classpath}" delimiter=";">
<sequential>
<local name="relative.dep.location"/>
<property name="relative.dep.location" relative="true" basedir="${project.build.directory}" value="#{curr.dep}"/>
<local name="classpath.hack.temp"/>
<propertyregex property="classpath.hack.temp"
input="${relative.dep.location}"
regexp="\\"
replace="\/"
default="${relative.dep.location}"
global="true"/>
<var name="relative.classpath.property" value="${relative.classpath.property} ${classpath.hack.temp}"/>
</sequential>
</for>
And to build a jar with all this stuff later:
<jar jarfile="${project.build.directory}/classpath.hack.jar">
<manifest>
<attribute name="Class-Path" value="${relative.classpath.property}"/>
</manifest>
</jar>
And then my <java> will have only ${project.build.directory}/classpath.hack.jar in the classpath
You can add Class-Path attr to your app jar manifest, this is how we do it in Maven
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
...
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
...
</plugin>
this way there's no limit for classpath length
Java's 64-bit javac generates the same code as the 32-bit version so you should don't need to use Java 32-bit unless you only have a 32-bit OS.
Java 6 added directory/* to include all JARS in a directory and this can shorted a classpath significantly.
The source of your problem is that all 32-bit programs run in the Windows XP/32-bit emulator and has all the same restrictions such as maximum command line length and environment variable length. Changing/fixing this is something MS themselves didn't try and I suggest you avoid this too.

Filtering out service provider files from META-INF

My application needs to run both from the command-line and a web app. The way I've chosen to implement this is to have the entire application in a single jar file (i.e. my application-specific classes coexist with the classes from the jars my app uses). This makes the command-line use case simple, as the user only has to type java -jar JARNAME. For the web app use case, I simply include the jar in WEB-INF/lib and all is well, almost.
The problem I have is that a few of the jars I'm slurping into the single jar define providers in META-INF/services for the same service, so the single jar ends up with multiple entries in META-INF/services with the same name. (For the curious, these are Jersey jars, and the services are javax.ws.rs.ext.MessageBodyReader and javax.ws.rs.ext.MessageBodyWriter.) So I'm trying to prevent the MessageBody* service files from being slurped into my jar file. Here's how I'm trying (and failing) to accomplish that:
<jar destfile="build/jammies.jar">
<archives>
<zips>
<restrict>
<fileset dir="lib">
<include name="*.jar"/>
<exclude name="servlet-api.jar"/>
</fileset>
<rsel:not>
<rsel:name regex="META-INF/services/javax.ws.rs.ext.*"/>
</rsel:not>
</restrict>
</zips>
</archives>
</jar>
I do have the rsel namespace defined at the top of build.xml.
<project basedir="." default="compile"
xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors">
So I don't understand why the restrict task isn't filtering out those particular service provider files.
I think its because the regex starts matching the filename strings from the start however no file begins with META-INF, they would begin with ${basedir}/WEB-INF/lib/META-INF...

JAR classpath and external jars

I actualy have 2 problems
I use eclipse -> export project to generate a jar file for my simple desktop (GUI) program
It generates a jar file and an ant script.
first problem:
the generated jar works fine when double-clicked.
When I use the generated ant script to generate the jar
by myself, it doesn't work.
What can be wrong with a target like this (assuming that all dependencies are met)
<target name="create_run_jar">
<jar destfile="G:/dev/myproj/myproj.jar">
<manifest>
<attribute name="Main-Class" value="view.myproj"/>
<attribute name="Class-Path" value=". myproj_lib/grouplayout.jar"/>
</manifest>
<fileset dir="G:/dev/myproj/bin"/>
</jar>
<delete dir="G:/dev/myproj/myproj_lib"/>
<mkdir dir="G:/dev/myproj/myproj_lib"/>
<copy file="G:/dev/.metadata/.plugins/org.dyno.visual.swing/layoutext/grouplayout.jar" todir="G:/dev/myproj/myproj"/>
</target>
//nevemind
//Second problem:
//when I double click on the auto-generated jar file the program launches and works fine.
//when I do java myjar from the command-line I get main class not found exception..
//weird huh?
I suggest that you take the JAR files generated the two ways, use the jar command to expand them into temporary directories, and then use diff in recursive mode to compare them.
However, I suspect that #Pace has put his finger on the problem; i.e. that you are using relative paths in the Class-Path manifest entry and this is liable to cause problems.
java -jar <jar name> is the proper way to execute a jar.
The ant target is creating a manifest with a classpath attribute. If you look at those paths you'll notice that they are relative to the current directory. When you execute java -jar from the command line are you in the...
G:/dev/myproj
...directory?

ant : jar and zipfileset - copy files from one JAR into another

I am currently doing this:
<jar update="yes"
jarfile="${pwd}/dist/${release}_installer.jar">
<zipfileset src="${pwd}/dist/app.jar" includes="com/izforge/izpack/panels/**"/>
<zipfileset src="${pwd}/dist/app.jar" includes="com/xyz/img/logo.png"/>
</jar>
My existing installer JAR gets updated to include the files as needed, extracted from the app JAR.
So far, so good.
However, I want to modify the behaviour such that the path of the image file is different than what is being copied from:
Currently:
com/izforge/izpack/panels/MyIzPanel.class
com/xyz/img/logo.png
What I want:
com/izforge/izpack/panels/MyIzPanel.class
blah/img/logo.png
So I need to copy the files, but use <zipfileset> and <jar> in such a way that I can modify the directory structure.
Is there a way to do this, apart from unzipping the entire contents copying file and then zipping it back up again?
EDIT:
Link to earlier related question: ant task to remove files from a jar
You can use the fullpath attribute:
<zipfileset src="${pwd}/dist/app.jar"
includes="com/xyz/img/logo.png" fullpath="blah/img/logo.img"/>
If you need to copy several files you may want to have a look at the prefix attribute, e.g.:
<zipfileset src="${pwd}/dist/app.jar"
includes="**/*.png" prefix="blah/img"/>
In order to modify the directory structure within the archive on the fly you can use the task in combination with <mappedresources>, eg:
<jar file="target.jar" update="true">
<mappedresources>
<zipfileset src="source.jar">
<include name="com/xyz/img/*.png"/>
</zipfileset>
<mapper type="glob" from="com/xyz/img/*.png" to="bla/img/*.png" />
</mappedresources>
</jar>
You should probably look into zipgroupfileset as explained here.

Categories

Resources