Showing posts with label jroller. Show all posts
Showing posts with label jroller. Show all posts

Thursday, June 25, 2026

Java: Format Date with java time

 This article was originally published on JRoller on March 11, 2017

An advantage of the DateTimeFormatter class from the java time package over the old DateFormat is that it is thread-safe. But if the only thing I have is a Date, how can I proceed?

The DateTimeFormatter's format method takes a TemporalAccessor as a parameter. Date has a toInstant() method that converts the Date to an Instant object that implements the TemporalAccessor interface. All that sounds pretty easy:

  Date date = new Date();
  DateTimeFormatter df = DateTimeFormatter.ISO_DATE_TIME;
  System.out.println(df.format(date.toInstant()));

Unfortunately, that does not work. You en up with the following error:

Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: Year
	at java.time.Instant.getLong(Unknown Source)
	at java.time.format.DateTimePrintContext$1.getLong(Unknown Source)
	at java.time.format.DateTimePrintContext.getValue(Unknown Source)
	at java.time.format.DateTimeFormatterBuilder$NumberPrinterParser.format(Unknown Source)

As it turns out, the only formatter that can be used with an Instant is DateTimeFormatter.ISO_INSTANT. And the output would be in UTC time zone and look like this: '2011-12-03T10:15:30Z'.

In fact, this is all very logical. The only information missing from a Date to know the correct time and date to print is the time zone. The old DateFormat class assumed you would want to use the current time zone. For java time, you have to explicitly sate it:

  Date date = new Date();
  DateTimeFormatter df = DateTimeFormatter.ISO_DATE_TIME;
  System.out.println(df.format(date.toInstant().atZone(ZoneId.systemDefault())));

Or you can also provide the time zone to the formatter:

  Date date = new Date();
  DateTimeFormatter df = DateTimeFormatter.ISO_DATE_TIME
    .withZone(ZoneId.systemDefault());
  System.out.println(df.format(date.toInstant()));

The toZone() method of Instant creates a ZonedDateTime object, from which you can easily convert to LocalDate, LocalTime or LocalDateTime. To convert back to a Date is always a matter of providing the missing information.

For instance, from a Localtime, you provide a date and a time zone:

  LocalTime now = LocalTime.now();
  Date date = Date.from(now.atDate(LocalDate.now()).atZone(ZoneId.systemDefault()).toInstant());

From a LocalDate, you need a time and a time zone:

  LocalDate now = LocalDate.now();
  Date date = Date.from(now.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant());

Java: Create Temporary Files with NIO 2 on Linux

This article was originally published on JRoller on October 18, 2006 

We have an application that had problems with memory consumption. One type of object that we were keeping in memory was kept there only in case a user would start an administration client and connect it to our app. So instead of having it constantly in memory, we decided to serialize it into a temporary file that would be destroyed when the application would stop. When an admin would connect, we would read back the data and send it before removing it from memory again.

The code that created the temporary file looked more or less like that:

  Path dir = Paths.get("myDir");
  Path tempFile = Files.createTempFile(dir, "MyApp", null);

  OutputStream outputStream = Files.newOutputStream(tempFile, StandardOpenOption.DELETE_ON_CLOSE);

As you see, the creation of a temporary file goes in two steps. First, the createTempFile() method would create a unique name with the given prefix. Then, the DELETE_ON_CLOSE option would delete the file when it was closed, that is in our case when the application would exit.

All our tests conducted in development on Windows platform would work fine. However, our test team ran all their tests on a Linux platform, which was actually the target platform for production. And guess what? It failed. The file would be created fine, and data was written without any problem. But when an admin would connect, the application would return a FileNotFoundException. When we checked, indeed, the files were not there.

After some investigation, it turned out that the DELETE_ON_CLOSE option on Linux platform would delete the file immediately from the file system, while keeping a reference to it in the Output Stream so that we could still write to it. How did we fix it? By turning to a good old non-NIO method:

  Path dir = Paths.get("myDir");
  Path tempFile = Files.createTempFile(dir, "MyApp", null);
  tempFile.toFile().deleteOnExit();
  OutputStream outputStream = Files.newOutputStream(tempFile);
I have the feeling that 10 years later, delete on exit is still not included in NIO.

Java: Negating a Predicate

 This article was originally publixhed on JRoller on September 12, 2016

Often, when using Java streams, I try to replace my lambdas with Method References. For instance, when I have this code:

    mystream.filter(mystring -> mystring.isEmpty()) ...

I tend to replace it with that one:

    mystream.filter(String::isEmpty) ...

Except that this code is not really useful. I rarely filter my stream with empty Strings. Usually, I do quite the opposite:

    mystream.filter(mystring -> !mystring.isEmpty()) ...

Now with that one small symbol, I managed to make my day more difficult. What to do if I really want to use Method References? I can create a isNotEmpty() method, but I don't want to do that for all my methods that return a boolean. If I really insist, I can end up with this ugly code:

    mystream.filter(((Predicate<String>)String::isEmpty).negate()) ...

One way to make things nice again, is to create a helper method, like this one:

    public static <T> Predicate<T> not(Predicate<T> p) {
        return p.negate();
    }

Now, I can simply use it like this:

    mystream.filter(not(String::isEmpty)) ...

I heard that such a method might find its way into JDK 9. Someone heard anything more concrete?

It turned out that Predicate.not() was introduced in Java 11.

Saturday, October 25, 2025

Thou Shall Close Thy Streams

 This article was originally posted on JRoller on March 12, 2015

You should always close your IO streams. Said like this, it sounds obvious. But in the light of some new Java 8 features, it took me some time to get around it.

I needed to write a small method for modifying a CSV file, basically change the last 1 of each line into a 0. Not really difficult. I would create a temporary file where I'll copy the original lines with the needed modification, then overwrite the original file with the one I created. Since I could use Java 8, I thought I would use a stream and lambdas. The code looked like this:

try (PrintWriter writer = new PrintWriter(Files.newBufferedWriter(tempFile))) {
	Files.lines(toConvert)
		.map(line -> line.replace(";1", ";0"))
		.forEach(line -> writer.println(line));
} 

Files.move(tempFile, toConvert, StandardCopyOption.ATOMIC_MOVE,
	StandardCopyOption.REPLACE_EXISTING);

Looks nice, except I had this weird java.nio.file.FileSystemException with the message "The process cannot access the file because it is being used by another process.". I was pretty sure that the only process using my file was my small program. So the problem was that the Files.lines() does not close the file. I found other references on the net to comfort my idea. So yes, I know, you can find it in the javadocs, and yes, the stream is autocloseable. So the way to go is the following:

try (Stream<String> reader = Files.lines(toConvert)) {
	reader.map(line -> line.replace(";1", ";0"))
		.forEach(line -> writer.println(line));
}

But to my defense, I'm not the only one having problems with the javadocs: https://bugs.openjdk.java.net/browse/JDK-8073923

Autoclose Lock

 This article was originally posted on JRoller on October 21, 2014

I was just wondering if there is a difference between the classic:

	lock.lock();
	try {
		 //I have the lock!
	}  finally {
		lock.unlock();
	} 

And the Autocloseable version:

	lock.lock();
	try (AutoCloseable auto = lock::unlock) {
		 //I have the lock!
	} 

Sunday, September 21, 2025

Capital Date Mistake

 This article was originally pusblished on JRoller on April 10, 2014

Here is a small piece of code. Can you tell what it prints?

  SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd");
  Calendar cal = Calendar.getInstance();
  cal.set(Calendar.YEAR, 2014);
  cal.set(Calendar.MONTH, Calendar.DECEMBER);
  cal.set(Calendar.DAY_OF_MONTH, 31);
  Date d = cal.getTime();
  System.out.println(sdf.format(d));

If you naively answered "2014-12-31", then I would tell you just this: you are really naive.

If you run this code under Java 6, you will get back an IllegalArgumentException, with the message "Illegal pattern character 'Y'". Now it might hit you that, indeed, the character for Year in a DateFormat is the lower case 'y'.

However, this code runs under Java 7, because the capital 'Y' was added to the DateFormat. But it does not stant for Year, but for Week Year. If, like me, you do not know what a Week Year is, here is the JavaDoc explanation:

A week year is in sync with a WEEK_OF_YEAR cycle. All weeks between the first and last weeks (inclusive) have the same week year value. Therefore, the first and last days of a week year may have different calendar year values.
For example, January 1, 1998 is a Thursday. If getFirstDayOfWeek() is MONDAY and getMinimalDaysInFirstWeek() is 4 (ISO 8601 standard compatible setting), then week 1 of 1998 starts on December 29, 1997, and ends on January 4, 1998. The week year is 1998 for the last three days of calendar year 1997. If, however, getFirstDayOfWeek() is SUNDAY, then week 1 of 1998 starts on January 4, 1998, and ends on January 10, 1998; the first three days of 1998 then are part of week 53 of 1997 and their week year is 1997.

In short, my exemple code will print "2015-12-31", because the last days of the year belong to a week of the following year.

Why don't I know my disk is full?

This article was originally posted on JRoller on March 14, 2014

We had this interesting problem lately, that an application had a corrupted file after a disk got full. The strange thing was that the app did not know that the disk was full. We were expecting an IOException, but no trace of it nowhere. Moreover, the app went on running, and resumed writing in the file when someone deleted a big file from the disk.

While looking on the net for how to know when a disk is full, we got this code strip on StackOverflow:

  FileOutputStream fos = ...;
  fos.write("hello".getBytes());
  fos.getFD().sync();
  fos.close();

This forces the OS to force synchronization of the file with its internal buffer, and throws a SyncFailedException when the disk is full. However, this has horrible performance. So we kept looking for our IOException. After a bit of investigation, we found out the culprit: PrintWriter.

The PrintWriter class can be very useful, since it wraps common print methods around a stream. Also, it automatically creates a BufferedWriter, as you can see in this constructor:

    public PrintWriter(File file) throws FileNotFoundException {
        this(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))),
             false);
    }

Another features of the PrintWriter, and now we get to the problem, is that most of its methods do not throw any Exception. Here is an example of a typical PrintWriter method:

    public void write(char buf[], int off, int len) {
        try {
            synchronized (lock) {
                ensureOpen();
                out.write(buf, off, len);
            } 
        } 
        catch (InterruptedIOException x) {
            Thread.currentThread().interrupt();
        }
        catch (IOException x) {
            trouble = true;
        } 
    } 

You can see that all IOExceptions are caught, and a boolean is set to true. The only way to know that something went wrong is to call the method checkError(). This only tells you that something went amiss, but not what, since you lost the exception.

    public boolean checkError() {
        if (out != null) {
            flush();
        } 
        if (out instanceof java.io.PrintWriter) {
            PrintWriter pw = (PrintWriter) out;
            return pw.checkError();
        }  else if (psOut != null) {
            return psOut.checkError();
        } 
        return trouble;
    } 

Notice how it checks if it wraps another PrintWriter or a PrintOutputStream, because it knows that they swallow the Exception.

At the end, we replaced the PrintWriter with a simple FileWriter, because we did not need the PrintWriter in our case. We only needed a Writer to give to our CSV exporter library, which already wrapped it in a BufferedWriter. Now, IOExceptions are nicely bubbling up, and we know when our disk is full. 

AutoCloseable when not available

 This article was originally posted on JRoller on January 14, 2014

On his blog, Brian Oxley shows a neat way in JDK 8 to use non AutoCloseable object having a close-like method in a try with resources construct, using the new method references. For those of us who are still stuck with JDK 7 for some time, here is the (uglier) equivalent code:


	final Foo foo = new Foo();
	try (AutoCloseable ignore = new AutoCloseable() {
		@Override
		public void close() {
			foo.close();
		} 
	}) {
		foo.doFoo();
	} 

Permutations and Combinations

 This article was originally posted on JRoller on October 22, 2013

A simple piece of code for calculating all permutations of a given word:

    public static List permutations(String s) {
        List list = new ArrayList<>();
        permutations(list, s, "");
        return list;
    }

    private static void permutations(List list, String from, String to) {
        if (from.isEmpty()) {
            list.add(to);
        }
        else {
            for (int i = 0; i < from.length(); i++) {
                permutations(list,
                        new StringBuilder(from).deleteCharAt(i).toString(),
                        to + from.charAt(i));
            }
        }
    }

The code for permutations of N elements out of a word is a simple modification of the previous program:

    public static List permutationsN(String s, int n) {
        List list = new ArrayList<>();
        permutationsN(list, s, "", n);
        return list;
    }

    private static void permutationsN(List list, String from, String to, int n) {
        if (to.length() == n) {
            list.add(to);
        }
        else {
            for (int i = 0; i < from.length(); i++) {
                permutationsN(list,
                        new StringBuilder(from).deleteCharAt(i).toString(),
                        to + from.charAt(i),
                        n);
            }
        }
    }

For Combinations, that is when order is not important, another small modification does the trick:

    public static List combination(String s, int n) {
        List list = new ArrayList<>();
        combination(list, s, "", 0, n);
        return list;
    }

    private static void combination(List list, String from, String to, int index, int n) {
        if (to.length() == n) {
            list.add(to);
        }
        else {
            for (int i = index; i < from.length(); i++) {
                combination(list,
                        new StringBuilder(from).deleteCharAt(i).toString(),
                        to + from.charAt(i),
                        i,
                        n);
            }
        }
    }

Modal vs Always on Top

This article was originally posted on JRoller on Auguts 2, 2013

Here is an interesting piece of code:

      public static void main(String[] args) throws Exception {
          JFrame alwaysOnTopFrame = new JFrame(\"Always on top Frame\");
          alwaysOnTopFrame.setAlwaysOnTop(true);
          alwaysOnTopFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
          alwaysOnTopFrame.setSize(500, 500);
          alwaysOnTopFrame.setVisible(true);
          alwaysOnTopFrame.setLocationRelativeTo(null);

          JOptionPane.showConfirmDialog(null, \"coucou\");
      }

It displays a simple frame, with the "Always on Top" activated, then opens a modal dialog. What will happen? Which one will prevail and be in front of the other?

As it turns out, if you try to run this code, you will see the Frame hiding the modal dialog box, although the application waits for you to answer the dialog first. What will appear to the average user is that there is a frozen window which does not react to anything. Impossible to move it or close it, until you guess that there is a dialog box behind it.

Of course, if you know it, you can discard the dialog box using Enter or Escape key, or the Alt+F4 combination, or access the dialog box menu through Alt+Space and move it around using the arrow keys. But the average user won't know it.

What is the solution? There is actually an option that you can set on the Frame, so that it will still respond to user actions even though there are modal dialogs on the screen. It is called Modal Exclusion Type. Try adding the following line:

  alwaysOnTopFrame.setModalExclusionType(ModalExclusionType.APPLICATION_EXCLUDE);

When is a SwingWorker really done?

This article was originally posted on JRoller on April 25, 2013

Imagine you have a SwingWorker running, and you would like to know if it has terminated its job. You notice that it has a isDone() method, and say to yourself: "great! I can use it!". But are you sure you know what it is really doing? Are you sure that all your work will be over when it returns 'true'? You would say: "of course, it is called isDone". Well, let's have a closer look.

When you create a SwingWorker, it creates a Callable, and wraps it in a Future:

        Callable callable =
                new Callable() {
                    public T call() throws Exception {
                        setState(StateValue.STARTED);
                        return doInBackground();
                    }
                };

        future = new FutureTask(callable) {
                       @Override
                       protected void done() {
                           doneEDT();
                           setState(StateValue.DONE);
                       }
                   };

The Future will be executed by a ThreadPool (of maximum 10 threads). The doInBakground() is called, returning a value that will be used by the Future for its set() method. From this point onwards, calling the isDone() method will yield true. And this is even before the Future's done() method is called. So isDone() only means that doInBackground() terminated. Not what I was thinking.

OK, so why not use the getState() method. I see clearly that it is called by the Future right after the call to doneEDT(). But let's have a look at the doneEDT() method:

    private void doneEDT() {
        Runnable doDone =
            new Runnable() {
                public void run() {
                    done();
                }
            };
        if (SwingUtilities.isEventDispatchThread()) {
            doDone.run();
        } else {
            doSubmit.add(doDone);
        }
    }

As you can see, if we are already in the EDT, we execute immediately the method. But we know that we are started from a ThreadPool, so this is not the case. The doSubmit, surprisingly, uses a Timer and schedules the task in 30ms. Not a SwingUtilities.invokeLater() as I expected, but the result is the same: the getState() will return DONE before we even start the done() method. The PropertyChange are notifying you of the state change. So basically, you are left to yourself.

Monday, April 21, 2025

EDT Freeze Detector

 This article was originally posted on Jroller on April 2, 2013

It is always the same scenario: the support team contacts us with a problem of a "frozen GUI". They send us the logs so that we can investigate, but of course the logs do not show anything. The user already restarted its GUI, so when we ask the support to perform a jstack, it is already too late. Quite often, it is not even due to a deadlock, but to a long operation that should not be done in the EDT. Since the only thing we have to investigate is the logs, I decided to write an EDT Freeze Detector that would log any operation monopolizing the EDT for more than 10 seconds. Here is the code:

import java.awt.AWTEvent;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.util.Timer;
import java.util.TimerTask;

public class FreezeDetector extends EventQueue{
    private static final long FREEZE_TIMER_PERIOD = 10000L;

    private volatile AWTEvent currentEvent;
    private volatile Thread eventDispatchThread;

    private FreezeDetector() {
        Timer timer = new Timer("Freeze Detector"true);
        timer.schedule(new FreezeTimerTask(), FREEZE_TIMER_PERIOD, FREEZE_TIMER_PERIOD);
    }

    public static void installFreezeDetector() {
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(new FreezeDetector());
    }

    @Override
    protected void dispatchEvent(AWTEvent event) {
        eventDispatchThread = Thread.currentThread();
        currentEvent = event;

        try {
            super.dispatchEvent(event);
        }
        finally {
            currentEvent = null;
        }
    }

    private class FreezeTimerTask extends TimerTask {
        private AWTEvent lastEvent;

        @Override
        public void run() {
            if (lastEvent != null && lastEvent == currentEvent) {
                printStack();
            }

            lastEvent = currentEvent;
        }

        private void printStack() {
            StackTraceElement[] stackTrace = eventDispatchThread.getStackTrace();
            StringBuilder sb = new StringBuilder();
            sb.append("Freeze detected on EDT:");

            for (StackTraceElement stackElement : stackTrace) {
                sb.append(stackElement.toString()).append('\n');
            }

            //use your favorite logger
            System.out.println(sb);
        }
    }
}

Sunday, March 3, 2024

JFileChooser and the Lost Folder Selection

This article was originally posted on JRoller on July 7, 2005

It might sound like an Indiana Jones movie title, but it is an interesting problem we came across. We have a third party product which at some point displays a JFileChooser, in which you must select a directory. In old Java 1.4, this dialog box was working properly. Now that we switched to brand new 5.0, when we select a folder and click on open, it does not come back with the folder as a selected value, but instead goes into the folder. The main difference in the behavior comes from the fact that when we selected a folder, its name was visible in the selected file textfield, and now it is not.

The colleague who had to solve the problem tried to execute the program by copying the 1.4 version of JFileChooser into the bootclasspath. It did not help, so I suggested him to try with the UI class instead. And oh suprise, it works as in the old days. So he started to compare the source code of both versions, and in the ListSelectionListener, he found an interesting difference. A property which was always true before is now set to false by default. So to solve the problem, he inserted the following line in the main method:

UIManager.put("FileChooser.usesSingleFilePane"new Boolean(true));

I wonder if these properties are documented somewhere. There seems to be so many of them...

I checked in my more recent version of Java. This parameter still exists, and still does not seem to be documented.

Wednesday, November 22, 2023

Dynamic Class Loading

 This article was originally posted on JRoller on June 30, 2005.

The other day, I wanted to write an Eclipse plugin (maybe more about that in a different post), in which I need to read a selected class file from the project I am working on and execute a method in it. Since I can not have my project in the classpath, I found out that the only solution is to have the class loaded dynamically. If there is a better solution in Eclipse, please somebody tell me.

Before starting to write my plugin, I decided to write a small test application, because I never used class loading before. So here is the class I want to load:

package hello;

public class HelloWorld
{
  public void run()
  {
    System.out.println ("Hello World!");
  }
}

To load it and execute the run method, you can then use the following lines of code:

        ClassLoader loader = new ClassLoader(getClass().getClassLoader())
        {
            public Class findClass(String name) {
                try
                {
                    String path = "C:\\mypath\\hello";
                    File file = new File(path, name + ".class");
                    RandomAccessFile raf = new RandomAccessFile(file, "r");
                    byte[] content = new byte[(int)file.length()];
                    raf.readFully(content);

                    return defineClass("hello." + name, content, 0, content.length);
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
                
                return null;
            }
        };
        
        try
        {
            Class helloClass = loader.loadClass("HelloWorld");
            Object hello = helloClass.newInstance();
            Method m = helloClass.getMethod("run"new Class[0]);
            m.invoke(hello);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

 I did not try the code on more recent java, but since the whole Class Loader API was in the process of being removed, I guess there are other ways to perform this nowadays. I tried asking ChatGPT to produce this code, and the result is quite similar, except it was using the URLClassLoader object which handles reading the file content for us.

Friday, November 3, 2023

JComboBox Editor Listening

This article was posted originally on JRoller June 3, 2005

To listen to edition event in the editor component of a JComboBox:

((JTextComponent)comboBox.getEditor().getEditorComponent()).getDocument().addDocumentListener(listener);


Wednesday, August 23, 2023

Other Comment Stories

 The following articles were originally posted on JRoller, and have as a common theme the code comments.

This first article was posted on August 24, 2005, with the title "Successful comment"

Yesterday, I was looking at some method, trying to understand what it was doing. I decided to look at the comments above the method signature, which might hopefully be of help. What I found was the following line:

// Returns true if successful

Well, that was the only information that I could have found without this help by just looking quickly through the code. Then I asked myself: does it mean that it returns false if the method fails? It reminds me of this story about two mathematicians trying to find out the color of a cow by looking at it grazing the grass from one of its side. If the side they see is white, does it mean that the whole cow is white? Then they agree that the cow is white on its left side.

This second article was posted on March 29, 2006, with the title "When is refactoring needed?"

When you see comments like this one, you know that a refactoring is not too far away:

  //Does anything, except storing
  registry->StoreNetwork();

This last article was posted on October 18, 2006, with the title "Find the root cause"

After eight years in Hungary, I am back to France. I have lots of new code to learn, so hopefully lots of new material for this blog.

Now something about bugfixing. You probably know that if you have to fix a bug, you should look for the root cause, and fix the bug at the root. That's the theory, but there are cases when you just can't do that, and the comment I found in this code is a good example:

if (cd == null) // It can happen. I submit 30 mn before the deadline!

Well, it's OK if you go back later and make a real fix.

Incomplete Class in Java 5.0 Released Version?

 This article was posted originally on JRoller July 22, 2005

I just found this comment in the WindowsFileChooserUI class, in the Java 5.0 source code:

    // The following are private because the implementation of the
    // Windows FileChooser L&F is not complete yet.

Did they forget to remove those lines? Or is the class really not complete? Did they lack time before the release? Did they have time to test it at all? Would we expect to have a complete version by Mustang? or Dolphin?

Following this comment is a list of private constants about Windows version. I would have expected to have them in a package private class, probably in the form of an enum. So I guess the class is really not complete, and this constants might be duplicated in some other places. Or is the FileChooser the only place in the whole Windows L&F where they have to make a difference between Windows versions?

Funny thing, I checked the implementation of the com.sun.java.swing.plaf.windows.WindowsFileChooserUI class in my Java 17, and the comment is still there. However, the constants disappeared. So on one side, there are no more differences in the L&F between windows versions. On the other side, nobody dared to remove the comment.

Monday, July 24, 2023

Comment Stories

 This article was posted originally on JRoller on April 27, 2005.

Comments are meant to be read. Sometime, they tell a story. The story of the code that follows them. Using Version Control tool, you can even retrieve the main characters.

Comment Story 1: John and Eduard

During a design meeting, John explains to Eduard how to modify the code he wrote, to include a new feature. They agree that some switch statement would be needed at some point in the class. But Eduard does not like switch statements. Eduard prefers the long list of if/else statements. He is a fervent Conditional Spaghetti adept. So he writes the code his own way, and include the following comment at the top of its code:

// sorry John, I hate the case structure...

Comment Story 2: Robi and Andras

Robi likes complex code. He likes long methods and overusing design patterns. His pride is a 400 lines long method, introduced by the following comment:

//the fair dinkum! select appropriate editor, handle selections, wash, iron, f*ck etc.

Robi leaves the project, and his code is handed over to Andras for maintenance. Andras has to fix bugs in Robi's code, and he doesn't like it. He has several sleepless nights, dreaming about monster methods managing everything in his house, ranging from dish washing to bringing down the garbage. For fear of breaking anything, Andras will try to change as less code as possible in Robi's piece of art. On one inspired day, he will add the following comment at the beginning of a 2500 lines of code long class:

/**
 * @author  K. Robi
 * ^^^^^^^^^^^^^^^^ you can tell ;-)
 */

Comment Story 3: Robi is angry
Robi works with JTables. He is trying to make something not really easy: the table should sort if you click on a column, and an arrow should show on the table header on which column and in which direction it is sorting. Being a big Design Pattern fan, he is putting quite some of them, and of course over-complicating the whole design. But this is not the point here. The point is that for some reason, something does not work when the reordering of columns is not allowed. Was it a Java bug? Or is it a misunderstood feature of JTable? I don't know, but what I know is that Robi spent some time on it. You can tell because he left several lines of code commented out:

//                    getTableHeader().invalidate();
//                    validateTree();
//                    invalidate();
//                    revalidate();
//                    repaint();

And then he got angry. REALLY angry. So angry that he felt he has to put the following comment in his code:

    //some fucking ugly workaround for the case when fucking column reordering is not allowed.
    //damn fucking strange, but none of these fucks above work and i'm fucking tired of fucking around
    //with these fucked-up tables! JTable fucks!
    //fuck that!
                

All this followed by those mysterious lines of code that I would be too scared to remove:

                    if(!getTableHeader().getReorderingAllowed())
                    {
                        TableColumn col1 = getColumnModel().getColumn(0);
                        int w = col1.getWidth();
                        col1.setWidth(w-1);
                        col1.setWidth(w+1);
                    }

Comment Story 4: Gabor and Peti
Gabor is new to the project. At some point during his learning curve, he has to fix quite a complex bit of code, a method of over 100 lines checking that some value fulfills all requirements before being submitted to the data store. It's quite a lot of tests, but still, he is not sure. Was everything tested? So in case someone comes up with another idea, he puts in the following comment in the code, at the end of the method:

    // ??? anything else?

Peti did read this comment, and found it funny. He actually felt the need to answer the question, and to show some positive and optimistic reaction to comfort Gabor that there would probably not be, but with the firm knowledge of experience that says "who knows...". He inserted the following comment:

    // Oh, no.

Comment Story 5: Baby come back
Sometimes, developers get bored, because the code they have to write does not present any challenge or fun. So they find way to have fun, and one way to do it is to put original comments in the code. That's probably what happened to Peti, who wrote some code which copies some value, use the original storage for some calculation, then restore the original value to its storage. In normal time, he would have put a comment like "Putting the original value back". But instead, he wrote the following:

  // Oh, baby come back

Comment Story 6: Peti talking to himself
It happens that comments are a mean of discussion between developpers, as it happened in Comment Story 4 between Gabor and Peti. I found such a comment spawned on three lines which seemed to be a dialog. But looking back into the version tree, it turned out that these three lines were written by the same person:

        // maybe only atm?
        // what do you think?
        // i'm not sure.

Probably still waiting for an answer...

Wednesday, July 5, 2023

Pascal Lover

 This article was originally posted on JRoller on June 11, 2004

I have a friend/colleague whose favorite language is Pascal. However, like half of my company, he had to learn Java, and of course had to use it as well. In his firt pieces of code, he tried to use some of the tricks he gathered from his Pascal experience. I think that most of us are doing the same. My first C program looked like Pascal, and my first Java program looked more like a direct translation from C++. It takes time to understand the philosophy of a language and use it the way it was meant to be used.

One of the trick he was using comes from the fact that Pascal is not efficient in String comparison. So my friend tried to avoid the following code:

    if (myString.equals("value1"))
    {
      //value1
    }
    else if (myString.equals("value2"))
    {
      //value2
    }

Instead, he rather used his own method, which was using a search of a substring within a String. Here is how it looks like:

    switch (Util.whichOne(myString,"@value1@value2@"))
     {
     case 0
       //value1
      break;
     case 1
       //value2
      break;
     }

Seeing this code during my code review, I ran a small speed test, and of course the Pascal way was slower (by a factor of 7) than the simple condition list. So not only the philosophy is different between languages, but the possible optimisations too.

Not only between languages, but also between versions of the same language. In the past, the String's equal() method looked something like that:

  public boolean equals(Object o)
  {
    if (!(instanceof String)) return false;
    return (compareTo((String)o== 0);
  }

Many programmers, including myself, were use to directly call the compareTo() method instead. However, in more recent versions of Java, the equals() method is an entity of its own, optimised for speed, and is faster on average than the compareTo() if what you are interested in is really the boolean return value. One of the optimisations is to check if the two Strings are of different size. In that case, equals() can directly return false while compareTo() still needs to calculate the difference between the two first non-equal characters.

All that comes back to the usual advice: if you really need to optimise something, check that what you are doing is really an optimisation.

The advice on using equals() for String is even more true today, when Java uses an inline C function to perform the operation.

Conditional Spaghetti

 This article was originally posted on JRoller on June 24, 2004

Often, having a lot of if/else structures one after the other in a code means that something is wrong with the design. It's what Kent Beck would call a Bad Smell. And usually, you can remove the conditions by using polymorphism. However, it is not always possible, or using inheritance would complicate the design too much.

Here, I want to speak about a certain kind of conditional spaghetti, where the list of if/else is quite long and the body is the same for each branch. This case can be viewed as a conversion between 2 values.

Here is a code that I've seen in one of the programs I had to review. It decides what icon to use for a given object type. There were something like 80 conditional branches.

  if (getType().compareTo("PSTNGateway"== 0)
    node.setIcon(new ImageIcon(
      RCMGR.getImage("Image.Gateway")));
  else if (getType().compareTo("PSTNNode"== 0)
    node.setIcon(new ImageIcon(
      RCMGR.getImage("Image. Node")));
  else ...

My solution for this kind of code is to use a static HashMap for converting the object's name to its icon. Here is the HashMap declaration:

  private static HashMap nodeTypes = new HashMap(50);
  static {
    nodeTypes.put("PSTNGateway", "Image.Gateway");
    nodeTypes.put("PSTNNode", "Image.Node");
    ...
  }  

Then, the 160 lines of conditional code becomes a simple two lines of code:

  node.setIcon(new ImageIcon(RCMGR.getImage((String)
    nodeTypes.get(getType()))));  

Not only it is easier to read and maintain, but the 40 String comparisons on average become a hash code calculation and a couple of comparisons. The same technique can be applied to a Factory. From the same program, the code that was creating the nodes according to some parameter String looked like this:

  if (cPar.getType().compareTo("BSC"== 0)
    newNode = new TDBSC(cPar.getName());
    else if (cPar.getType().compareTo("RNC"== 0)
    newNode = new TDRNC(cPar.getName());
    else ... 

Now using the HashMap to convert between the node's name and the corresponding class:

  private static HashMap nodeTypes = new HashMap(150);
  static {
    nodeTypes.put("BSC", TDBSC.class);
    nodeTypes.put("RNC", TDRNC.class); ...
  }

  Class nodeClass = (Class)nodeTypes.get(cPar.getType());
  Constructor init = nodeClass.getConstructor(new Class[] {String.class});
  newNode = (TDTreeNode)init.newInstance(new Object[] {cPar.getName()} );

As a final note, I want to mention that the HashMap can be totally avoided by using naming convention. Then, the node class for example can be inferred with a simple formula:

  Class nodeClass = Class.forName(PACKAGE_NAME + CLASS_PREFIX + nodeType);

This article was written in Java 1.4. Now, of course, using generics, you can avoid all those ugly castings. I used this pattern several times following this article. The gain in number of code lines is big, but it comes also with a notable gain in performance.