LSNED 26: Accessing java resources as files

I have a test web app that needs to process some files (they happen to be Microsoft Office documents, but that’s not really relevant).
The web app could be installed on a number of different machines, running Windows or Linux and needs to just work, so the files need to be stored within the war and accessed from there.

The structure of the source is:

  • [root]

    • src

      • main

        • resources

          • docs

            • Doc1.docx
            • Doc2.docx
            • Show1.ppt

This is all built using maven, so I don’t have to do anything more in order to include the resources in my war file.

The trick to accessing the resources as File objects is to use getResource to get a URL to the file, and then to construct the File object using the getFile method of the URL.

Once you’ve got access to the File object you can do all the usual operations with it, including loading the entire file into memory, which is also shown below (note that in normal cases you should check the size of a file before loading it into memory, but these files are resources, I created them and I know how big they are).

public class ClassWotDuzzStuff
{
    private static final Log log = LogFactory.getLog( ClassWotDuzzStuff.class );

    private static final String[] inputs = new String[] {
                "/docs/Show1.ppt",
                "/docs/Doc2.docx",
                "/docs/Doc1.docx"
                };

    public void doStuffWithResources()
    {
        for( String input : inputs )
        {
            URL currentFileUrl = this.getClass().getResource( input );
            File currentFile = new File( currentFileUrl.getFile() );
            byte[] contents = new byte[ (int)currentFile.length() ];
            try
            {
                FileInputStream currentInputStream = new FileInputStream( currentFile );
                currentInputStream.read( contents );
            }
            catch( FileNotFoundException ex )
            {
                log.warn( "The file \"" + input + "\" is listed as a resource, but doesn't seem to exist." );
                continue;
            }
            catch( IOException ex )
            {
                log.warn( "The file \"" + input + "\" could not be read." );
                continue;
            }
            doStuff( File, contents );
        }
    }

LSNED 25: Static array initialisers in java

I didn’t learn this for the first time today – I relearn it EVERY time I need a static array (typically an array of strings).

Hopefully by adding this here I won’t forget it in a hurry.

private static final String[] inputs = new String[] {
"/docs/Doc1.ppt",
"/docs/Doc2.docx",
"/docs/Doc3.docx"
};

LSNED 24: Netbeans has useful features on the document tab

How many times have I needlessly type CTRL-W for every document in that’s open (and typically ended up closing the Projects and Files windows by mistake)?

A rightclick on any of the document titles brings up a useful little menu:

I’d still like to see the ability to open the current file in Windows Explorer, or even just to copy its full path to the clipboard…

LSNED 23: According to Java, it is reasonable for abs() to return a negative number

I guess this is one that all the Java old-timers know well:

int i = Integer.MIN_VALUE;
System.out.println( "abs( " + i + " ) == " + Math.abs( i ) );
System.out.println( "abs( " + i + " ) == " + StrictMath.abs( i ) );
++i;
System.out.println( "abs( " + i + " ) == " + Math.abs( i ) );

Gives the following:

abs( -2147483648 ) == -2147483648
abs( -2147483648 ) == -2147483648
abs( -2147483647 ) == 2147483647

Frankly I think that’s nuts – either you know about it and have to right special case code in all your calls, or you don’t and it’s a bug waiting to happen.
I much prefer the C# approach:

try
{
    int i = System.Int32.MinValue;
    System.Console.WriteLine("abs( " + i + " ) == " + Math.Abs(i));
    ++i;
    System.Console.WriteLine("abs( " + i + " ) == " + Math.Abs(i));
}
catch (OverflowException ex)
{
    System.Console.WriteLine(ex);
}

Which gives:

System.OverflowException: Negating the minimum value of a twos complement number is invalid.
at System.Math.AbsHelper(Int32 value)
at System.Math.Abs(Int32 value)
at Playground.Program.Main(String[] args) in C:\Users\njt\Documents\Visual Studio 2008\Projects\Playground\Playground\Program.cs:line 15

There is little chance of the java implementation changing, because the behaviour is in the spec: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Math.html#abs%28int%29.

LSNED 22: Converting to/from Java Date and XMLGregorianCalender data types

The CXF web service framework represents XML dates using the XMLGregorianCalendar data type (it’s not alone in this, but I don’t know whether it’s laid down in law or not).

Unfortunately converting between the Java Date data type and the XMLGregorianCalendar data type is slightly non-trivial:

private Date dateFromXmlDate( XMLGregorianCalendar arg )
{
    return arg.toGregorianCalendar().getTime();
}

scheduledTime.toGregorianCalendar().getTime()

private XMLGregorianCalendar xmlDateFromDate( Date arg )
{
    GregorianCalendar gregorian = new GregorianCalendar();
    gregorian.setTime( arg );
    try
    {
        return DatatypeFactory.newInstance().newXMLGregorianCalendar( gregorian );
    }
    catch ( DatatypeConfigurationException ex )
    {
        log.error( ex );
        return null;
    }
}

LSNED 21: Exporting and importing formatting options in Netbeans

I don’t like eclipse – I find it cumbersome and awkward every time I use it.
If I’m honest, I think a dislike for eclipse put me off java for a long time.

I started using netbeans because I was evaluating Open ESB and I find it a far more intuititive IDE than eclipse.
This may simply be because of my Microsoft background and netbeans is closer to Visual Studio in feel.

There are fairly frequent releases for netbeans, and each time I installed it I’ve been reconfiguring it to my liking – mainly in the formatting options because I think open curly brackets ({) should nearly always be on a line by themselves (the exception being short if/elseif blocks).

Well, I’ve been wasting my time.
What I should have been doing is exporting my settings every time I make changes – and then importaing them every time I reinstall.

Doh.

The export and import feature is easy to find in the bottom left-hand corner of the Options dialog:
Netbeans Options dialog showing the import and export buttons in the bottom left-hand corner.

LSNED 20: jQuery plugin for Struts 2

Back in LSNED 15 I worked out how to get the dojo datetimepicker working with Struts 2.1.

Well, it turns out that that was a mistake.

There are bugs in the dojo datetimepicker that won’t be fixed because the dojo plugin is deprecated.

So what’s the alternative?
Well, it’s not ideal because it’s not in the main struts 2 official distribution yet, but it soon will be: http://code.google.com/p/struts2-jquery/

The jQuery plugin means that by doing the following I can get a jQuery datepicker onto my form alongside my normal struts components:

<%@taglib prefix="sj" uri="/struts-jquery-tags"%>

<html>
    <head>
        <s:head />
        <sj:head jqueryui="true"/>
    </head>
    <body>
        <s:form action="user-update" namespace="/admin" validate="true" theme="css_xhtml">
            <s:hidden name="userId" value="%{id}" />
            <s:if test="#request.user.username == username">
                <s:textfield label="Username" name="username" labelSeparator="" labelposition="left" disabled="true" />
            </s:if>
            <s:else>
                <s:textfield label="Username" name="username" labelSeparator="" labelposition="left" disabled="false" />
            </s:else>
            <sj:datepicker label="Expiry date" labelSeparator="" labelposition="left" name="expiryDate" displayFormat="yy-mm-dd" showButtonPanel="false" />
            <s:checkbox label="Locked" name="locked" labelSeparator="" labelposition="left" />
            <s:checkbox label="Enabled" name="enabled" labelSeparator="" labelposition="left" />
            <s:submit theme="local" value="Save" labelSeparator="" labelposition="left" />
            &nbsp;
            <s:a action="user-delete" namespace="/admin" ><s:param name="userId" value="id"/>Delete This User</s:a>
            &nbsp;
            <a href="<s:url action='users-list' namespace='/admin' />">Cancel</a>
        </s:form>
    </body>
</html>

Because the jQuery plugin is not yet in the official distribution to get this to work you’ll need to drop the plugin’s jar into WEB-INF/libs: src\main\webapp\WEB-INF\lib\struts2-jquery-plugin-1.7.3.jar

The jQuery datepicker isn’t as pretty as the dojo plugin one, but for business oriented sites I think that’s a bonus:

Unfortunately, the release version of the jQuery plugin assumes that you are using the xhtml struts theme.
There are two consequences to this if you are not using the xhtml theme: it will insert table elements into your html, which will royally mess up any tables that you are actually using; and it will draw its button in the wrong place.
The first problem is a show-stopper in one of my systems because I need to use the date picker in a horizontal table.
But at least there is a simple way around the second problem, just don’t display the button by adding some CSS:

button.ui-datepicker-trigger {
  display:none;
}

Fortunately the jQuery team seem to respond quickly to bug reports and by the time you read this the latest release might have the correct support for the parentTheme attribute.
I’ll blog again when I learn that it has.

LSNED 19: Zooming in Outlook

If you use Outlook 2007 you will one day find that you have pressed a nasty keyboard shortcut by mistake and the email message that you are writting has been zoomed.
After fiddling for a while to fit it you will discard that email and try to write a new one – but the new email starts off zoomed.

The solution is on the Format Text ribbon, over on the right is a zoom control.

The real question is how we end up in this situation in the first place.
There doesn’t seem to be a keyboard shortcut for zoom, but if you hold down the CTRL key and wiggle the mouse wheel it will zoom, so I’m guessing Iyou did that.

LSNED 18: What software is installed on this PC?

There are lots of very expensive tools for finding out what software is installed on a PC, in many cases they go to extraordinary lengths to establish this and still get it wrong.
Well, here’s an incredibly quick and simple way to find out:

reg query "HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall" /v "DisplayName" /s | find "Display"

This will only report the things found in the Add/Remove programs dialog (sometimes in more detail than they are listed there), but I’ve seen commercial tools miss stuff that this finds (which is says more about those tools than anything else).

Being a standard registry command, if you have the rights you can run it on all the machines in your domain without moving.
And if typing that in is too hard let me know and I’ll post the tool I wrote before I learned this.

LSNED 17: Searching the registry

In the old days (Windows 2000, I think) Microsoft used to have a command line tool called regfind (I think) that would search the entire registry and print out any key or value that contained a search term in each the name or the data.
It was very useful, and then they replaced it with the much less useful “reg.exe”.

I don’t know whether reg.exe has become more capable, or I just didn’t look hard enough, but reg.exe does have similar functionality to regfind.exe.
The magic incantation is:
reg query HKLM /s /f

Where reg.exe is still deficient is that you have to specify a root key, so searching the entire registry requires multiple runs.