Monday, April 16, 2007

HOWTO: use ANT with JAVA to dynamically create build numbers

Overview
For me, build numbers are very useful. I like to use them where I can so I can keep true to a major, minor, and patch version purpose. The only problem is, how do you automate build numbers in a way that is easy to use in an IDE that doesn't automatically use them? The solution is partially included in ANT and the rest is a little bit of simple project setup.

While you are automating things, why not include simple information about your project bundled with each JAR you create. Including:
  • Program/Library/Project name
  • Author
  • Company/Organization
  • Copyright
  • Description (brief)
  • Version (major/minor/patch)
  • Build Number
  • Build Date
The following will describe the steps for automating ANT to do manage this for you. The example is using Netbeans, however, anything ANT capable should work using this technique.

The process is also being described from a JAVA perspective but there isn't anything truly JAVA specific. For this reason, the technique could be ported to other language. I just happen to like JAVA so that is what I am using.


Technique

What we are doing is simple:
  • Have ANT create/update a small properties file for us in the root of the jar
  • Use a small class or library to open a load this properties file at startup
  • Ensure all data is available through static methods for easy access through-out the program
This setup is done once per project and can then be forgotten about.


build.xml Setup
In Netbeans (and probably other IDEs) build.xml is a place to create your own custom build targets. A target needs to be setup for "-pre-jar" as follows
<!-- Custom Target for AppInfo.java -->
<target name="-pre-jar">
<buildnumber file="buildnumber.properties"/>
<propertyfile file="appinfo.properties"
comment="Everything can be manually updated except buildnum and builddate.">
<entry key="program.PROGNAME" default="${main.class}" />
<entry key="program.AUTHOR" default="" />
<entry key="program.COMPANY" default="" />
<entry key="program.COPYRIGHT" default="now" type="date" pattern="yyyy" />
<entry key="program.DESCRIPTION" default="" />
<entry key="program.VERSION" default="1.0.0" />
<entry key="program.BUILDNUM" value="${build.number}" />
<entry key="program.BUILDDATE" type="date" value="now" pattern="yyyyMMDDHHmmss" />
</propertyfile>
<copy file="appinfo.properties" todir="${build.classes.dir}"/>
</target>

This target can be cut/pasted right into your build.xml as is. It is doing the following:
  • Defines an implementation for -pre-jar to the build system
  • Creates a new buildnumber to be stored in buildnumber.properties.
  • Creates a new propertyfile called appinfo.properties. Within propertyfile many entries are created. All the entries are set to a default that can be updated by hand. These entry tags do not have a value="..." attribute within the tag. The ones with the value="..." will get updated at each build. In this case, the only entry tags affected are BUILDNUM and BUILDDATE.
  • Does a copy of the appinfo.properties file to the build.classes.dir so it can be included in the jar for this project.
After your first build, you will find two new files in the root directory of your project. This is the same directory as build.xml.

buildnumber.properties
This is a file created and maintained by ANT. If you delete it, ANT will create another starting at 1. The file will look something like this.
#Build Number for ANT. Do not edit!
#Sat Apr 14 01:25:36 EDT 2007
build.number=1

With each build, the build.number will be incremented by 1. You do not need to do anything with this file going forward since ANT maintains it.

appinfo.properties
All of the project summary information will be stored in here. After your first build, there isn't much but you can update the static fields as you see fit. The following is a file that was updated for a specific project.

#Everything can be manually updated except buildnum and builddate.
#Sat Apr 14 01:25:36 EDT 2007
program.PROGNAME=LangTrans
program.BUILDNUM=15
program.AUTHOR=Ken Langer
program.DESCRIPTION=This program uses Google Language Tool.(...)
program.BUILDDATE=200704104012536
program.COPYRIGHT=2007
program.COMPANY=StoKen Software
program.VERSION=1.0.0

I manually updated all the fields (using the rules of property files) above except BUILDNUM and BUILDDATE since they get updated dynamically. This is the file that will be included in the JAR output of your project.


Using appinfo.properties
Usage can be done in two ways. You can either roll-your-own, or use a pre-existing library I created.

Roll-Your-Own
Rolling your own is not to bad. Simply open the appinfo.properties file as follows:
InputStream in = null;
Properties props = new Properties();
//
// load properties file
//
try {
//
// get Application information
//
in = getClass().getResourceAsStream("/appinfo.properties");
props.load(in);

// DO SOMETHING HERE WITH THE props object....

in.close();

} catch (IOException ex) {
ex.printStackTrace();
} // end-try-catch

That is it. Accessing the values can be done using the props.getProperty(key); method.

Using Pre-Existing Library
To save me time, I created a simple library (that will get more tools added over time) that has much of this already setup. If you are interested, see stoken-utils. There is a class within the project all AppInfo that you can hand props (from above). It has some simple static accessors you can use for getting the key values you need.

Within the same library, you will see AppInfoPanel which can be stuck into a JFrame for creating a spiffy about box.

Both are used in a sample program I wrote called language-translate. If you look through this program you will see the usage of both.


Either approach above still requires the build.xml configuration but the second one already knows what to do with it after build.xml does its magic.


Final Thoughts
The technique above should allow you to simply and easily include build numbers and other centrally controlled project information.

UPDATE: I just discovered that if you have the compile on save feature in Netbeans 6.5 on, it seems to prevent appinfo.properties from being copied into your build/classes/... folder. This means that any executions within the IDE will probably fail or have errors/exceptions. I will look at a way around this but until then, turn off compile on save and just do a classic SHIFT+F11 to built before a test run.

Monday, April 9, 2007

HOWTO: config 915resolution to have widescreen resolution

Overview
There is a problem with Intel Graphics chipsets to where where it doesn't know about wide screen resolutions. I don't know about the back story but I would like to be able to use 1440x900 with my monitor. The good thing is that someone has created a solution that gets around this issue.

My system is a 2007 ASUS P1-P5945G that uses the INTEL 945G CHIPSET. I have a 19" (widescreen) Viewsonic monitor that supports up to 1440x900 resolution. This system was purchased from http://www.mwave.com/ for a pretty good price.

Disclaimer
What works for me might not work for you. Ensure you know your hardware before you try this. It may be possible to toast your system (motherboard/monitor/mind) in attempting this. Just be careful and sure.

Technique
The idea it to change one of the preset resolutions in the Intel Graphics chip from its default to your preferred resolution. The good part is that there is a command for it but the change is not permanent. To get around this, someone created an init script that ensures your change happens at boot :-) Here is what you do....Assuming FC6.

1. Install 915resolution: yum install 915resolution
2. Get a list of Resolutions and pick one to replace: 915resolution -l

  • this will give you a long list of all the supported resolutions and bit levels
  • in front you will see a hex value (5a, 5b,...). Look for ones you will not be able to use with your monitor.
3. Edit config file and add RESOLUTION="..." statement: vi /etc/sysconfig/915resolution

  • If you want 5a to be 1440x900 at 32bit set RESOLUTION="5a 1440 900 32"
4. Run FC6 setup from xterm

  • Turn on System Service "915resolution" so it sets RESOLUTION=".." each time you boot.
5. Reboot.

  • When you come back up, you should be able to select 1440x900 (or whatever you picked) as your Preference->Screen Resolution.
When you boot your linux system next, you will be able to go into the GNOME Preference->Screen Resolution and see 1440x900 (or whatever you set) in the list.

What to Check
On my monitor, I have a little button that tells me the current resolution and refresh rate. Ensure this matches what your monitor can support.

I would also look at your /var/log/xorg.log and see if you got any errors. If so, do a little reading to ensure there is nothing bad happening.

GDM
I have run into an annoying thing with the "greeter" for Gnome. If your /etc/X11/xorg.conf has resolutions higher then the resolution you wish to use, it might pick the highest supported one in the list. This will give you a login screen that scrolls when you move your mouse around.

The only way I have found to fix this is to edit the /etc/X11/xorg.conf and remove any resolution higher then you desired (1440x900 for me) by you. This quick edit will correct that problem.

Final Thoughts
This concept seems to work. I have not read anything that says that this is dangerous or damaging. Still, do your research to ensure your hardware is safe.

If you use UBUNTU, check out this link for a good overview. Much of my information came from there.
http://www.ubuntuforums.org/showthread.php?p=1808047


- - -