My Photo

Recent Comments

Powered by TypePad

May 01, 2007

MSJVM... Going Going Gone

Many of you are probably already aware that Microsoft's JVM will soon be obsolete. In fact, it even has an expiration date, December 31 2007. Happy New Year...out with the old and in with the better. This is not to say that Java applications such as Snowbound's FlexSnap family of viewers and imaging technology will just cease to function. It does however mean that the MSJVM will no longer be supported. Users should not only be aware of this but take the proper steps to stay informed about this obsolete software and move away from the MSJVM before December 31, 2007. This includes identifying both internal and licensed applications that depend on the MSJVM. Businesses that plan their transition ahead of time will be at an advantage and have adequate time to identify their MSJVM dependencies and applications, and then establish a migration plan to test and deploy other solutions.

From the Microsoft Website: "The MSJVM is obsolete code that is no longer enhanced or developed. Microsoft recommends that consumers who are using MSJVM-dependent programs consult their software vendors' Web sites for any information on action they might need to take in the future. For instance, users might be advised to update or replace their current versions before December 31, 2007."

Sun Microsystems, providers of the popular Sun JVM, have an existing agreement with Microsoft enabling them to use Sun's source code and compatibility test suites, thus allowing Microsoft to extend support for the MSJVM until the end of this year. Does this mean that Sun's JVM is the logical replacement for the MSJVM? It seems to be the most popular, and from what most users will say, the most reliable and compatible. But if you want to play it safe you are best off contacting your Java solutions provider and seeing what they recommend. It never hurts to be in touch with your partners and vendors during a transition like this.

- Ed


			

December 12, 2006

Another Neat Trick with the Ant

Even though the Ant has plenty of available tasks out of the box and a wealth of 3rd party tasks already defined, you still may wish to improve your build process by creating your own custom tasks. This is an especially useful approach to tackling some of the unique quirks you may encounter with regards to your specific build process, and at the very least, this approach can yield a much cleaner build script— after all, doesn't everyone get a headache when pawing through XML code?

So, say you’ve got a class which performs some functionality and you wish to create an Ant task with the same functionality. Take this class below, as an example:

public class QuickTIFFConvert {

    public static void main( String args[] ) {

        if( args.length == 2 ) {

            String input = args[0];

            String output = args[1];

            Snowbnd s = new Snowbnd();

            int pageCount = s.IMGLOW_get_pages( input );

            for( int i = 0 ; i < pageCount ; i++ ) {

                s.IMG_decompress_bitmap( input, i );

                s.IMG_save_bitmap( output, Defines.TIFF_G4_FAX );

            }

        else

            System.out.println("Invalid arguments!");

    }

}            

QuickTIFFConvert takes in an input and output file name, converts each page of the input file to TIFF Group4 using three simple calls to Snowbound Software’s RasterMaster SDK, and then saves the result as the output file. This class can easily be turned into an Ant task by creating a new class which extends org.apache.tools.Ant.Task and implementing your own execute() methods along with setters for your input parameters, which in this case would be setInput() and setOutput().

public class QuickTIFFConvert extends Task {

    private String input, output;

    public void execute() throws BuildException {

        Snowbnd s = new Snowbnd();

        int pageCount = s.IMGLOW_get_pages( input );

        for( int i = 0 ; i <  pageCount ; i++ ) {

            s.IMG_decompress_bitmap( input , i );

            s.IMG_save_bitmap( output , Defines.TIFF_G4_FAX );

        }

    }

    public void setInput( String input ) {

        this.input = input;

    }

    public void setOutput( String output ) {

        this.output = output;

    }

}

After you’ve built your newly defined task with the required dependencies, created a JARchive and included it on the classpath in your build script, you can then define a target like so:

<property name="input.file" value="/tmp/imgs/document.pdf"/>
<property name="output.file" value="${input.file}.tiff"/>
<taskdef name="convertTIFF" classname="org.custom.QuickTIFFConvert"/>
<target name="convert">
    <convertTIFF input="${input.file}" output="${output.file}"/>
</target>

Keep in mind that the Ant expects parameters defined in build scripts identical to how they are defined in the corresponding task.

Now, even if it is unlikely that your build process would include any image conversion, you can still leverage the flexibility of custom tasks and once you get the hang out of it, creating your own tasks can be essential to your build process. Custom tasks could range from regex processing of strings in your source code to advanced testing routines or to custom error handling. Think twice before spawning an <exec> and instead consider leveraging the flexibility built into Ant using it to improve your build process. And remember, if you can create a Java class to do it, then you can create an Ant task to do it.

-Andy

 
Additional references:
http://ant.apache.org/manual/develop.html
http://www.onjava.com/pub/a/onjava/2004/06/02/anttask.html

September 28, 2006

Cloning Using Serialization

We recently encountered a bug in our software where we were copying annotations. Changes made to the copy of the annotations would also be made on the original documents. This is because we were simply moving around the references of the object rather than making actual copies. When I looked into the code, it looked like it would be somewhat tedious to clone the object at its full depth. I then wondered if I could use Serialization to perform a deep copy. After some searching I found the exact article I was looking for. You can indeed use Serialization for this purpose and it works beautifully.

- Alex

September 26, 2006

Proposed Changes in DST Cause Java Runtime Environment Security Concerns

On August 8, 2005, President George W. Bush signed the Energy Policy Act of 2005. This Act changed the time change dates for Daylight Saving Time (DST) in the U.S. Beginning in 2007, DST will begin on the second Sunday of March and end the first Sunday of November. The Secretary of Energy will report the impact of this change to Congress.Congress retains the right to revert the Daylight Saving Time back to the 2005 time schedule once the Department of Energy study is complete.

The effect of this on Java is significant. Time zone information is obtained from a set of files stored internally by the Java Virtual Machine (JVM) and applied to dates as required. Since this information is statically stored in the Java Runtime Environment, older versions of Java do not know about the changes and will display the wrong time for the USA throughout most of March 2007. Forward date information will already be wrong if it refers to dates in that period.

IMPACTED VERSIONS:

Java 5 update 5 and earlier

Java 1.4.2_10 and earlier

Java 1.3.x

NON IMPACTED VERSIONS:

Java 5 update 6 or later

Java 1.4.2_11 or later

Prior to Java Plug-in 5.0 Update 6 and later for Windows,an applet could specify the version of the JRE on which it would run. With 5.0 Update 6 and later installed on the Windows platform, all applets are executed with the latest version of the JRE. See Sun Alert ID: 102557. The 1.5_08 JRE will force applets to run using the new version regardless of previous specification.

The Sun Java 1.5_08 pilot package was released and made available September 2006. Pilot testing and code remediation will continue until January 2007 and product distribution to workstations will begin in February 2007.

- Ed

September 08, 2006

Serialization: Avoiding a NotSerializableException with the Transient keyword

When you are writing client-server software with Java, it's often convenient to pass Java objects from the client to the server. Java Serialization allows classes to be converted to a string format, allowing for easy network transmission. In most cases, it is very easy to make a class Serializable. You simply have your class implement the java.io.Serializable interface. Unlike most interfaces, there are no methods for you to implement, it is simply a "marking interface".

public class Person
    implements Serializable
{

private Date mBirthday
private String mName

public Person (String pName, Date pBirthday)
{
    mBirthday = new Date (pBirthday);
    mName = pName;
}

/* add some setters / getters etc... */

}

Once you have a Serializable class, you can then create an ObjectOutputStream and use the writeObject method to send your object. If you try to write an object that is not Serializable, you will get a NotSerializableException.

There are some classes that just can not be serialized. Often these are AWT components, or Threads, or the like. But what if you have a class that you want to "make Serializable" but once of it's member variables is a Thread object. This is where the transient keyword comes in.  By marking a member variable transient. You tell the Serialization engine not to include that member in the serialization process. You are now able to send down that complex object without getting a NotSerializableException. For example:

...
private Date mBirthday
private String mName
private transient Thread personThread
...

When a Person object gets deserialized, the personThread Thread will be null, but most likely, you won't care, especially in the case, where you just want to store the birthday and the name of the person.

For further reading, check out the discussion on Serialziation at the Sun Developer Network

-Alex

August 29, 2006

Zipping and Unzipping .jars, .wars, and .ears

Most people familiar with Java Applets and Java class libraries are familiar with the concept of .jar files.Most of the time, Java libraries are distributed in jar files. For example: the JDOM XML library is distributed in a file named jdom.jar. Snowbound's FlexSnapSI Applet is packaged in a file named FlexSnapSI.jar.

JAR is short for "Java Archive" and it is a cute name, but perhaps an unfortunate one, because jar files are really just renamed zip files. I've had people ask if I could make a jar file for them from their class folders. All you really need is Winzip or a similar program. More on the basics of Jar Files can be found in this Java tutorial. You can easily unzip the contents of a jar file to see the classes that are included in a library or applet package.

EARs and WARs:

J2EE Servlet based web applications that run in Tomcat or Websphere are usually distributed as .war files. In this case, WAR stands for "Web Application Archive". Like jar files, they are in .zip format. To create one, you can use a zip program to create a file called myapp.zip and then simply rename it to myapp.war. Depending on your application server, they are often expanded at deployment time and converted to a folder structure.

Ear files take this one step further. In my experience,. an .ear file is just a zipped up .war, which is already a zip to begin with. So now we have a zip within a zip. I usually drive myself crazy when I'm trying to package up an .ear file for use in Websphere. A good discussion on the topic is found in this SearchWebServices.com Q&A.

-Alex

May 23, 2006

The Value of Open-Source Java Code and Commercial Java Products

The Java language has created a large, devoted community since its release by Sun Microsystems in the mid-1990s. The flexibility offered by its object-oriented approach and cross-platform compatibility has been a major draw for software developers.

The community also actively works to move Java forward through constant innovation — including major open-source projects like the plug-in based application framework Eclipse Platform — that allows Java to compete with native platforms — such as Windows. However, on a small scale, individual developers that freely distribute their solutions to specific problems can create unnecessary noise that makes searching for credible open-source or commercial solutions more time-consuming.

Free tools can often point you in the right direction, or offer a partial solution to your task. However, if you need help or additional functionality, you may or may not be able to find the answer on an internet forum. A commercial solution is often the most complete, and offers professional support.

Most corporate projects take advantage of both open-source code (either using it under an open license or as a research tool) and commercial products to increase productivity and reduce development time. Clearly defining what you will need from third-party code before beginning your search will help you determine which will fit your needs. Some major considerations are:

  • Scalability of tools to meet current and future development requirements
  • Areas of development difficulty that could be simplified by third-party libraries
  • Need to support backwards compatibility in your application

Once your project requirements are clear, knowing the strengths and limitations of open-source code and commercial products will enable you to make the best decision for your project. Here is a concise list that outlines some of the major pros and cons of open-source Java code versus commercial Java code.

-Javier

March 21, 2006

An Object-Oriented Approach to Copying and Reordering Pages in a Document

If you have a requirement to reorder pages within a document, or to create a new document containing pages from multiple existing documents, here’s an easy approach.

The first step is to create a class that represents each source page. I’ve called it com.snowbound.sample.PageReference. It only needs to store the name of the source document, and the page Index of the desired page.

package com.snowbound.sample;

public class PageReference
  {
      private int pageIndex;
      private String fileName;

    public PageReference (String file, int index)
      {
         pageIndex = index;
         fileName = file;
      }

    /**
       * @return Returns the fileName.
       */
      public String getFileName()
      {
         return fileName;
      }

   /**
      * @return Returns the pageIndex.
      */
      public int getPageIndex()
      {
         return pageIndex;
      }

}

The next class to create is an extension of java.util.Vector. I’ve named it com.snowbound.sample.DocumentModel, since it models the layout of the document that we are creating. This class only has one method, writeDocument, in addition to the inherited methods of Vector. It uses a RasterMaster for Java Snow.Snowbnd object to handle the image processing and output.

package com.snowbound.sample; 

import java.util.Vector;
  import Snow.Snowbnd;

public class DocumentModel extends Vector
  {
      public void writeDocument(String filePath, int imageFormat)
      {
          Snowbnd snow = new Snowbnd();
         for
(int i = 0; i < size(); i++)
          {
              PageReference pageRef = (PageReference) elementAt(i);
              snow.IMG_decompress_bitmap(pageRef.getFileName(),
              pageRef.getPageIndex());
              snow.IMG_save_bitmap(filePath, imageFormat);
          }
      }
  }

Here’s a sample app that uses these two classes to create a new document made from pages of existing documents. In practice, the DocumentModel could be created using UI components and FileDialogs to define the input files, and the order of pages for the new document.

package com.snowbound.sample;

import Snow.Defines;

public class PageManipulationApp
  {

 public static void main (String args[])
  {
       DocumentModel model = new DocumentModel();
       model.addElement( new PageReference ("c:/imgs/splash.png", 0));
       model.add( new PageReference ("c:/imgs/snowbound.tif", 0));
       model.add( new PageReference ("c:/imgs/snowbound.tif", 1));
       model.add( new PageReference ("c:/imgs/photo.jpg", 0));
       model.add( new PageReference ("c:/imgs/.tif", 1));
    
model.writeDocument("c:/imgs/new.tif", Defines.TIFF_LZW);
  }
  }

-Alex

February 15, 2006

Using AWT Dependent Imaging Routines in SWT

For many years, Java programmers have been building GUI's with AWT, the "Abstract Window Toolkit". This was Java's first stab at creating a widget library for buttons, windows, text fields etc. AWT has it's many shortcomings, since it generally relies on every operating system having a corresponding native component. Sun soon came out with Swing, which many people saw as being far more flexible, since it did not rely on native OS components for its implementation.

More recently, a newer component toolkit has gained popularity. SWT, the "Standard Widget Toolkit", is the fundamental component library upon which Eclipse is built. More and more developers are adopting SWT, as Eclipse is becoming the universal standard for Java development environments.

I recently faced a challenge. If I had code that relied heavily on its interaction with the AWT-based Java2D drawing routines, how could I port that over to a new SWT-based program?

After some searching, I found an excellent article and some sample code at IBM's DeveloperWorks site. The author provides source for a small utility class, Graphics2DRenderer, that essentially allows you to convert an SWT-based graphics context to a java.awt.Graphics object.

I put this code to work in a very basic sample in an attempt to use Snowbound's RasterMaster for Java in an SWT program. Since Snowbound's painting routines rely on a java.awt.Graphics object, I needed to use the Graphics2DRenderer to generate an instance.

import java.awt.Graphics2D;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import swtgraphics2d.Graphics2DRenderer;
import Snow.Snowbnd;

public class SWTExample
{

    Snowbnd simage ;

    public SWTExample()
    {
        simage = new Snowbnd();
        simage.IMG_decompress_bitmap("c:/imgs/rollsroy.png",0);
        Display display = new Display();
        final Shell shell = new Shell(display);
        FillLayout layout = new FillLayout();
        shell.setLayout(layout);

        Canvas canvas = new Canvas(shell, SWT.CENTER);
        final Graphics2DRenderer renderer = new Graphics2DRenderer();

        canvas.addPaintListener(new PaintListener() {
          public void paintControl(PaintEvent e) {
            Point controlSize = ((Control) e.getSource()).getSize();

            GC gc = e.gc; // gets the SWT graphics context from the event

            renderer.prepareRendering(gc); // prepares the Graphics2D renderer                

            // gets the Graphics2D context
            Graphics2D g2d = renderer.getGraphics2D();

            /*
             * Perform actions on g2d
             */          

            simage.IMG_display_bitmap(g2d, 0,0,controlSize.x, controlSize.y);            

            /*
             * Done with the g2d object
             */

            // now that we are done with Java 2D, renders Graphics2D operation
            // on the SWT graphics context
            renderer.render(gc);

            // now we can continue with pure SWT paint operations
            gc.drawOval(0, 0, controlSize.x, controlSize.y);
          }
        });

        shell.pack();
        shell.open();
        while (!shell.isDisposed())
        {
            if (!display.readAndDispatch())
                display.sleep();
        }
        display.dispose();
    }

    public static void main(String[] args)
    {
        SWTExample swt = new SWTExample();
    }

}

-Alex

October 28, 2005

Adding Configurable Keyboard Shortcuts to your Java Application

In the last entry, I wrote a very basic menu-driven Java program, which allows the user to change the background of the Frame. In this entry, I'll go over how to add keyboard shortcuts to this app. 

We'll just have ShortcutFrame implement KeyListener and add a keyPressed(KeyEvent) method.

Our class declaration is now as follows:

public class ShortcutFrame extends Frame
    implements KeyListener

in the first line of the constructor we add

   addKeyListener(this);

Then we need to implement the three methods for KeyListener.

To get started, I'll use the Source -> Implement Methods feature of Eclipse, which is really useful in these cases. This takes care of a lot of busy work.

I'll leave keyTyped() and keyReleased() methods empty. I'll only flesh-out the keyPressed method.

public void keyPressed (KeyEvent event)
    {
        char eventChar = event.getKeyChar();
        int eventCode = event.getKeyCode();
        if (eventChar == 'r')
        {
            performCommandRed();
        }
        else if (eventChar == 'b')
        {
            performCommandBlue();
        }
        else if (eventCode == KeyEvent.VK_PAGE_DOWN)
        {
            performCommandSwitch();
        }
    }   

Now imagine that a new customer wants this exact same program. But, they want the keyboard shortcuts to be as follows:

  Hit the '1' key for Red
  Hit the '2' key for Blue
  Hit ctrl PAGE_DOWN to cycle.
 
You need to keep the one code base, but you need multiple keystroke sets.

I had to solve this same problem. The first thing I thought of was, how to come up with a language to define key strokes. Something like this:

param name="redKey" value="R"
param name="blueKey" value="1"
param name="switchKey" value="CTRL-PAGE_DOWN"

I thought about the best way to define most of the key combinations. Then I figured someone must have already solved this problem, so I did some searching and got a hit on the Javadoc page for javax.swing.KeyStroke. The method that interested me most was getKeyStroke(String s)

There is a language to define keystrokes:

getKeyStroke (String s):

Parses a string and returns a KeyStroke. The string must have the following syntax:
    <modifiers>* (<typedID> | <pressedReleasedID>)

    modifiers := shift | control | ctrl | meta | alt | button1 | button2 | button3
    typedID := typed <typedKey>
    typedKey := string of length 1 giving Unicode character.
    pressedReleasedID := (pressed | released) key
    key := KeyEvent key code name, i.e. the name following "VK_".
   
If typed, pressed or released is not specified, pressed is assumed. Here are some examples:
     "INSERT" => getKeyStroke(KeyEvent.VK_INSERT, 0);
     "control DELETE" => getKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
     "alt shift X" => getKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);
     "alt shift released X" => getKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);
     "typed a" => getKeyStroke('a');

So now I'll define three static constants for my three key strokes;

    private static KeyStroke gKeystrokeRed = KeyStroke.getKeyStroke("pressed R");
    private static KeyStroke gKeystrokeBlue = KeyStroke.getKeyStroke("pressed B");
    private static KeyStroke gKeystrokeSwitch = KeyStroke.getKeyStroke("PAGE_DOWN");

my keyPressed method looks like this:

  public void keyPressed(KeyEvent event)
    {
        KeyStroke myKeyStroke = KeyStroke.getKeyStrokeForEvent(event);
        if (myKeyStroke.equals(gKeystrokeRed))
        {
            performCommandRed();
        }
        else if (myKeyStroke.equals(gKeystrokeBlue))
        {
            performCommandBlue();
        }
        else if (myKeyStroke.equals(gKeystrokeSwitch))
        {
            performCommandSwitch();
        }
    }

Now if I want to change any of these, I can read in an Applet parameter.

        ...
        getKeyStrokeParameter(applet, "keyStrokeRed", gKeystrokeRed);
        getKeyStrokeParameter(applet, "keyStrokeBlue", gKeystrokeBlue);
        getKeyStrokeParameter(applet, "keyStrokeSwitch", gKeystrokeSwitch);
        ...   
      
   
  public static void getKeyStrokeParameter(Applet applet,
                                             String param,
                                             KeyStroke shortcut)
    {
        String paramValue = applet.getParameter(param);
        if (paramValue != null)
        {
            shortcut = KeyStroke.getKeyStroke(paramValue);
        }
    }
   
   
Now anyone can override the keyboard shortcuts with whatever they like, via applet parameters.

-Alex

October 26, 2005

Colors, Events, and System.out.println

Let's say you are given the following task

Develop a Java Applet that brings up an empty window. Allow the user to change the background color of the window by using a Menu.

If the user chooses Menu -> Color -> Blue,
* Change the background to HTML color "071aaa".
* Print the String "Blue" in the Java Console

If the user chooses Menu -> Color -> Red,
* Change the background to HTML color "ff1a00".
* Print the String "Red" in the Java Console

OK. Sounds pretty easy. Lets make our Frame class.

The first thing I want to do is define constants for those Colors. A few years ago, I was only really familiar with the java.awt.Color constructor that took three integer values: one each for red, green and blue. If I was given an HTML color to display, like our blue "071aaa" I would have had to translate that HTML hex string to the three integers. I would have used Photoshop or a color web site like this. Recently I learned how to directly pass the hex value to the Color constructor that takes in a single integer value. All you have to do is pass in an integer in hex format like this

  private static final Color BLUE_COLOR = new Color (0x071aaa);
 
That's much easier than translating to RGB. The reason I use a static Color constant is so that we don't go reconstructing a new Color object every time the menu item is selected. I've seen a lot of code out there where the programmer calls "new Color(r,g,b)" every time they need that Color. That's a lot of excess object construction.

The ShortcutFrame code:

public class ShortcutFrame extends Frame
{
    private static final Color RED_COLOR = new Color (0xff1a00);
    private static final Color BLUE_COLOR = new Color (0x071aaa);
    MenuItem miBlue;
    MenuItem miRed;

    public ShortcutFrame(Applet parentApplet)
    {      
        MenuBar menuBar = new MenuBar();
        Menu colorMenu = new Menu("Color");
        miBlue = new MenuItem("Blue");
        miBlue.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                performCommandBlue();
            };
        });
        colorMenu.add(miBlue);
        miRed = new MenuItem("Red");
        miRed.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                performCommandRed();
            };
        });
        colorMenu.add(miRed);
        menuBar.add((colorMenu));
        setMenuBar(menuBar);
    }

    private void performCommandRed()
    {
        setBackground (RED_COLOR);
        log ("Red");
    }

    private void performCommandBlue()
    {
        setBackground (BLUE_COLOR);
        log ("Blue");
    }

    public void log (String output)
    {
        System.out.println (output);
    }

}

A few notes here.

  • I'm using "anonymous inner classes" to perform the action listening for the menus. A lot of programmers will use the old paradigm of having one global listener for all of their buttons and menu items. This makes for one pretty ugly actionPerformed() method with a whole bunch of if / elses. The inner-classes allow one listener per UI element, no more if / else trees. These anonymous classes will show up as ShortcutFrame$1.class and ShortcutFrame$2.class at compile time.
  • Within the anonymous listener classes, I'm not performing the actual menu commands, I'm simply dispatching a method call which does the actual work, i.e. performCommandBlue. This makes the anonymous listener classes a lot cleaner, and also allows these commands to be called by keyboard shortcuts!
  • I'm not calling System.out.println directly in my performCommand methods. Instead, I'm calling a log method which does the printing. This way later on, when I want to redirect the output somewhere else, I only have one place to change this. Also if I want to turn off printing, I only have one line to comment out. An even better implementation would be to use the java.util.logging.Logger class. But that's for another blog entry.

In my next entry, we'll look at how to add configurable keyboard to our application.

-Alex