« In Private | Main | JavaScript »

Tue, Feb 24, 2009

New Java Blog

There haven't been too many updates in this blog during the last few months...

I've started a new Java blog recently, JavaBarista (in German), which is easier to maintain (and swifter to write for me). I'll mostly talk about Java EE frontend and backend technologies.

Thank you for reading this blog (I'll see if I can keep it alive) - and enjoy the new one :-)

Posted by Thomas Much at 14:57
Categories: Java

Fri, May 02, 2008

finally { apple.releases( java6ForMacOSX ); }

Only one and a half years after Sun released Java SE 6 for Windows, Linux and Solaris, Apple released the Mac OS X version (called Java for Mac OS X 10.5 Update 1) this Tuesday. Phew. Thanks to the engineers for their effort to get this release out finally, no thanks at all to Apple's management for delaying the release. Anyway, you'll find the release notes here.

And regarding this blog post's title: There is no catch? Unfortunately, there is... There are some exceptions (and you shouldn't throw exceptions within the finally block, right?).
First, Apple's Java 6 implementation requires Mac OS X 10.5.2 or newer, but this was to be expected. Second (and more important), the release is for 64-bit Intel Macs only (i.e. Core2Duo or newer). No Java 6 for PPC Macs or even 32-bit Intel Macs (CoreDuo). Bummer.

If you've installed a developer preview version of Java SE 6, the Java update probably won't show up in your Software Updates. Deleting the preview installation should fix this:


  sudo rm /System/Library/Frameworks/JavaVM.framework/Versions/1.6
  sudo rm -R /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0

If you want to change the system's default Java version, do not mess with certain symlinks in the system's directories but use /Applications/Utilities/Java/Java Preferences instead (you have been warned).

And if your Mac or your operating system does not meet the requirements, there's always the possibility to use the Open Source Java 6 implementation called "SoyLatte".

Posted by Thomas Much at 19:51
Edited on: Sun, May 04, 2008 11:04
Categories: Apple & Mac OS X, Java

Sat, Mar 08, 2008

Java on the iPhone

With Apple showing no interest in keeping Mac OS X 10.5 up to date with current Java versions (they are 14 months behind the final release of Java SE 6 for other systems now, despite some beta versions for certain Mac OS X versions and Intel chip sets) or in providing Java on the iPhone at all, it seems it's up to Sun or the Open Source community now.

And it actually seems Apple has become irrelevant for the future of Java on Mac OS X systems (including the iPhone) by now! While a port of Java SE 6 for Mac OS X 10.4 and 10.5, called SoyLatte, has been around for some time now, Sun announced yesterday that they intend to put Java on the iPhone!

They'll start with Java ME (a reasonable decision for a mobile phone platform), though it won't be released before middle of this year. Java SE and JavaFX might be following later on.

So, let's wish them good luck and let's hope Apple won't put too many obstacles in their way...

Posted by Thomas Much at 21:49
Categories: Apple & Mac OS X, Java

Thu, Jan 17, 2008

Parsing 2-Digit Years with Java's SimpleDateFormat

If you have to format and parse date strings like "17.01.2008" (in this case, the German date format) with Java, you'd probably use a java.text.SimpleDateFormat:

SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
Date now = new Date();
System.out.println( sdf.format(now) );  // something like "17.01.2008"
Date then = sdf.parse( "17.01.1908" );
System.out.println( sdf.format(then) );  // "17.01.1908"

This works as expected. But now some fancy user dares to input the year with only two digits:

SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
Date fancy = sdf.parse( "17.01.08" );
System.out.println( sdf.format(fancy) );  // "17.01.0008" - oops!

This is a feature that one easily fails to see in the API: If the year pattern is not "y" or "yy", year numbers are parsed literally and not relatively to some century. Using the short pattern works fine for parsing, but you'll need a second pattern for output:

SimpleDateFormat input  = new SimpleDateFormat("dd.MM.yy");
SimpleDateFormat output = new SimpleDateFormat("dd.MM.yyyy");
Date ok1 = input.parse( "17.01.08" );
Date ok2 = input.parse( "17.01.2008" );
System.out.println( output.format(ok1) );  // "17.01.2008"
System.out.println( output.format(ok2) );  // "17.01.2008"

You can read (and set) the century offset using the property 2DigitYearStart.

And while we're at it: If you want to prevent SimpleDateFormat from parsing an illegal date like "32.01.2008", you'll have to switch off the lenient mode:

SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yy");
sdf.setLenient( false );
Date illegal = sdf.parse( "32.01.1908" );  // ParseException
Posted by Thomas Much at 18:05
Categories: Java

Tue, Nov 13, 2007

13949712720901ForOSX

As posted before, there's no Java SE 6 runtime environment included in Mac OS X 10.5 (Leopard). There is a quite nice Java 5.0 implementation, however, and you can even tune its GUIs better than before for special Mac OS X integration - which is really cool! But this doesn't help you much if you have to develop applications using the latest Java APIs.

To request an important enhancement like this, there is an official way: File a bug report (I did so, my report got number #5575846). This won't help a lot, either, because bug reports requesting Java 6 will be marked as duplicate... and then Apple falls silent again :-(

So, to draw some attention to this problem, someone suggested that all bloggers should use a common marker as a "public request" to Apple, and here it is:

13949712720901ForOSX

Now, the management at Apple can simply google for this string and see how many bloggers (let alone the non-blogging people) are waiting for Java 6 on Mac OS X 10.5 (or at least a statement about the future of Java on OS X).

In the meantime, someone else has ported the FreeBSD JDK 1.6 to Mac OS X (10.4 and 10.5). The port still has some problems and currently relies on X11, but this is a cool project for sure. Nonetheless, I'd still like Apple to officially release their port of Java SE 6 with proper GUI integration, as this would be the best statement about the Mac as a serious platform for Java development.

Posted by Thomas Much at 20:04
Categories: Apple & Mac OS X, Java

Tue, Oct 30, 2007

Does Apple hate Java?

So, Leopard (Mac OS X 10.5) is there and Java SE 6 for the Mac is not. Which is a pity, because the latest Java version (available for many other platforms for over 10 months now) offers massive improvements concerning desktop integration and performance.

While there always has been a delay between Sun's Java releases and Apple's own implementations, leaving this gap open for too long time can urge developers - such as James Gosling, inventor of the Java technology - to abandon the Mac platform. Of cause you can use Parallels/VMWare/BootCamp and run Windows/Linux/Solaris for Java 6 development. But why would you want to buy a Mac then?

Does Apple hate Java? It almost seems so. At least Java obviously isn't a priority at Apple. Or maybe it's just that Apple found a bug in their Java 6 implementation that prevented the release with Max OS X 10.5.0? We don't know for sure.

And this actually is the biggest problem: Apple's silence. There's still some hope, yet, and if you read between the lines (there had been a developer preview of Java 6 for Mac OS X 10.4), I expect the release of Java 6 for Mac OS X within the next few days or weeks.

But if you run a company and do serious software development, you need a reliable roadmap for your platform of choice. And if that isn't available for whatever reason, you need at least some kind of commitment to release certain products within a certain time frame. Omitting both means "we don't care about your needs". Which might easily lead to developers ignoring the platform. Which would really be a pity, because the Mac not only deserves great Cocoa applications, but great Java applications as well.

So, come on Apple, even if you cannot release Java 6 right now, at least let us know your commitment to still provide the best Java experience with the latest Java version - and when to expect the release eventually.

Posted by Thomas Much at 17:46
Edited on: Wed, Oct 31, 2007 12:00
Categories: Apple & Mac OS X, Java

Tue, Jul 24, 2007

Exclude Certain Message-Resource Keys From Struts Localization

While Struts isn't the latest, coolest Java web framework, it certainly is one of the most widely used ones. And it has proven to be solid and reliable in many, many projects. However, once in a while you need some feature that even a framework with some years of history does not offer out-of-the-box. Fortunately, Struts can be extended easily.

For a Struts & Common Controls project I needed the possibility to exclude some message-resource keys from localization, because the "key" strings were loaded from a database and had to be used literally. Most of the keys had to be looked up (i.e. localized) from the resource bundle, still.

In the end I decided to write my own, small MessageResourcesFactory that simply does not localize keys that start with the prefix "nokey!". Instead, such key strings are returned literally (without the "nokey!" prefix).

If you happen to need something similar, download the small archive here (provided "as is" without any warranties, use it at your own risk!) and activate the new MessageResourcesFactory in your struts-config.xml as follows:

<message-resources factory="de.snailshell.struts.MessageResourcesFactory" parameter="MyResources" null="false" />

[Update] Not really well documented... But from Common Controls 1.6 on you can exclude any resource key from localization by simply adding a "#" prefix. I'm not sure if I like the "#", though, because it might get in conflict with EL variables from the Unified Expression Language. So I think I'll stick with the "nokey!" prefix.

Posted by Thomas Much at 15:28
Edited on: Thu, Jul 26, 2007 17:22
Categories: Java

Fri, Jun 08, 2007

Java String Concatenation

Recently I found another blog posting about how Java concatenates strings. While the author is absolutely right that you should use java.util.StringBuffer or StringBuilder in loops, the very first example is not quite correct.

If you use a line like

String str = "foo" + "bar" + "Oh my, there must be a more efficient way...";
 

i.e. if you concatenate only String literals and constant expressions (and no variables) the Java compiler uses no StringBuffer/StringBuilder at all, but compiles the String values into a single string. Here's proof. Consider this simple class:

public class StringTest {
    public static final String STR = "ABC" + "DEF";

    public static void main(String[] args) {
        final String str = "abc" + "def";
        System.out.println( STR );
        System.out.println( str );
    }
}

Compile it into bytecode and disassemble it with javap -c StringTest:

public class StringTest extends java.lang.Object{
public static final java.lang.String STR;

public StringTest();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   0:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #3; //String ABCDEF
   5:   invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   getstatic       #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   11:  ldc     #5; //String abcdef
   13:  invokevirtual   #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   16:  return
}

As you can see, at runtime there's no String concatenation any more, but only pre-concatenated String constants (bold lines). So, it's definitely absolutely ok to break down long String values into smaller, concatenated chunks without any runtime performance penalty at all.

Posted by Thomas Much at 13:54
Edited on: Sun, Jun 17, 2007 15:09
Categories: Java

Mon, Jun 04, 2007

Setting JAVA_HOME on Mac OS X

Once in a while the question arises how to set environment variables on Mac OS X in a way that GUI processes can access them, too. In particular, some Java applications require a properly configured JAVA_HOME value.

Answer, part one: Download the preference pane RCEnvironment, install it with a double click and set your variables (they're available after your next login). Yes, it's that easy:

Answer, part two: Use a correct value for JAVA_HOME, which is usually

/Library/Java/Home

This alias (link) defaults to the Java version Apple wants most users to use (currently Java 5.0). Only if you have good reason to do so (for example, if you are a developer), you can set this variable to point at a specific version, e.g.

  • /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home
    (latest Java 6 release) or
  • /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home
    (only Java 6.0, no later 6.x release)
Posted by Thomas Much at 13:27
Categories: Apple & Mac OS X, Java

Fri, Jun 01, 2007

Informix and Hibernate

While working on a Java web application that uses Hibernate as the persistence layer and Informix 10 as the database backend we discovered that Hibernate's built-in Informix dialect does not support BLOB and CLOB types.

Since Informix 10 supports these LOB types, it was easy to derive a new dialect from the existing one by simply adding the missing mappings:

  public class Informix10Dialect extends InformixDialect {
     public Informix10Dialect() {
        super();
        registerColumnType( Types.BLOB, "blob" );
        registerColumnType( Types.CLOB, "clob" );
     }
  }

This extended dialect works fine for us, and if you don't want to write it yourself, you can download a small archive here (provided "as is" without any warranties, use it at your own risk). Put the included JAR on your application's classpath and set the dialect in hibernate.properties as follows:

hibernate.dialect=de.snailshell.hibernate.Informix10Dialect

I've also posted a bug report for this issue, and once this is fixed, you won't need the extra dialect JAR any more.

Posted by Thomas Much at 13:43
Categories: Java

Tue, Jan 16, 2007

Constructor Keyword?

In addition to my Java wish post two weeks ago, here's another idea for an extension of the current Java syntax. Beginners often have difficulties in finding the constructors of a class. Both you and I know that a constructor has no return type and uses the name of the class, but why not make this special code easier to find?

public class Example {
  public constructor Example() { ... }
}

This new constructor keyword could either be a new modifier that would be allowed only on "methods" without return type and with the same name as the class. Or it could be a special return type (like void) allowed only on methods with the same name as the class. The latter solution would have a second benefit: You cannot accidentally add the void return type to a constructor any more (which makes the intended constructor a plain method) - an error that is hard to track down especially by beginners.

Of course this could also be realized using annotations (e.g. "@Constructor"), but IMHO the coding of a constructor should be part of the syntax and not of the meta data.

Hey, maybe it's time to go to the Kitchen Sink and toy around with the Java syntax? :-)

Posted by Thomas Much at 12:20
Categories: Java

Wed, Jan 03, 2007

Explicit Package Visibility?

Happy New Year to all readers of this blog! With 2007 being two and a half days old already, it's about time to express one's wishes for the months to come. So here's my wish for upcoming Java (200)7 beta versions: Add the possibility to explicitely declare package visibiliy. Why?

I'm teaching Java (and related technologies/frameworks) to many different people, beginners as well as Java programmers with years of experience. There's one misunderstanding I encounter regularly: The meaning of the implicit access modifier for default (package) visibility. Consider the following class:

public class Example {
  int value;
  int getValue() { return this.value; }
}

Here, both the variable value and the method getValue() have package visibility since no access modifier is declared explicitely. Currently this is the only way to use the package access level. This often is a problem since many people expect Java to choose the "best" visibility as default, i.e. private for variables. Some even expect methods to be public by default. (You don't think that default public methods are a reasonable assumption? Well, think of interfaces, where all methods are implicitely public and the public access modifier is completely redundant... This absolutely makes sense - but does not make Java easier to use.)

Changing the "default" (implicit) visibility from package to private for variables and from package to public for methods isn't an option since it would break compatibility of existing source code. But there's an elegant solution IMHO that requires only a slight extension of the Java syntax and does not need a new keyword as we can reuse one already existing:

package de.snailshell.wishes;
public class Example {
  private int value;
  package int getValue() { return this.value; }
}

IMHO this source code is easier to understand for beginners and even offers better readability for experienced Java programmers. The access modifier could still be omitted and would still default to package visibility, i.e. source code compatibility remains preserved. Later on, omitting the access modifier could be deprecated for class members (leading to a compiler warning).

Any thoughts on this proposal? Let me know!

[Update] I'm not sure if readability is maintained if the class itself is package visible:

package de.snailshell.wishes;
import ...;
package class Example { ... }

On the other hand, this notation makes it clear that the class is visible in its package only. Because two different lines can start with the same token now, the compiler's parser needs a lookahead of two tokens. I don't know if this would be a problem with the current compiler (maybe it uses a two tokens lookahead already).

Posted by Thomas Much at 12:35
Edited on: Tue, Jan 16, 2007 11:15
Categories: Java

Mon, Jan 23, 2006

JavaApplicationStub

Java applications can be launched like native Mac OS X applications if their bytecode (usually a JAR archive) is packaged as a Mac OS X application bundle. The actual launch code is a native executable, usually called JavaApplicationStub, that's placed in Your.app/Contents/MacOS/ (if you want to use a different name for the stub file, you'll have to change the value of the CFBundleExecutable key in Info.plist, too).

The stub file changed from Java release to Java release, and unfortunately some stub versions have been more capable of launching Java applications on various system versions than others. Just recently, after updating to QuickTime 7.0.4 on Mac OS X 10.3.9, certain old stub files refused to launch Java applications any more (the fix is easy: just copy a current stub file from /System/Library/Frameworks/JavaVM.framework/Resources/MacOS/ to your affected application bundles).

These problems led to a discussion on Apple's Java developer mailing list on how to ensure that always the latest stub version is used. We came up with the following solution: Don't use a copy of the stub file in your application bundle, but a symlink (not a Finder alias!) to the system's current stub instead:

ln -s /System/Library/Frameworks/JavaVM.framework/Resources/MacOS/JavaApplicationStub PathToYour.app/Contents/MacOS/JavaApplicationStub

The solution has a little drawback: You cannot use a different name than JavaApplicationStub, which makes it hard to tell different Java processes apart in a Unix shell (the Finder uses the bundle name from Info.plist, which can still be whatever you want, so this seems acceptable in most cases). And of course, the symlink will break if Apple decides to change the framework structure some time. But until now, the framework structure has proven to be more stable than a copy of the stub file itself, so the symlink is likely the most elegant solution to always use the latest stub in your Java application bundles.

[Update] There have been reports that this approach does not work as expected - you cannot use more than one Java application that uses the linked stub at the same time... So it seems we'll have to wait for Apple to provide a reliable solution.

Posted by Thomas Much at 24:09
Edited on: Sun, May 21, 2006 21:14
Categories: Apple & Mac OS X, Java

Sun, Oct 09, 2005

Java für Mac OS X

Book Cover Just in case you did not notice yet - nearly one year ago I published a German book on Java for Mac OS X: Java für Mac OS X . It was released when Mac OS X 10.3 and Java 1.4 where the most up to date versions, but actually (or unfortunately?) there hasn't changed much with Mac OS X 10.4 and Java 5.0.

Posted by Thomas Much at 18:34
Edited on: Fri, Jun 01, 2007 13:38
Categories: Java