★ wanayoo — archive 1999 http://blogs.oracle.com/thejavatutorials/tags/jdk7Nouvelle recherche | Portail wanayoo

Friday Mar 18, 2011

St Patrick's Day Release of Java Tutorial

We have recently released two updates of the Java Tutorial. The February 21st update was designed to coincide with the JDK7 Developer Preview Release. The tutorial was updated again on St Patrick's Day, March 17th.

The updated content for both releases includes the following features:

The updated tutorial is available as a download from The Java Tutorials front page.

We hope you enjoy the updated content!

-- Sharon Zakhour

Thursday Feb 18, 2010

Getting Java Applets to Work on Mac OS

Are you having trouble viewing some Java applets on a Mac? Got next generation Java Plug-in? The next generation Java Plug-in (introduced in Java SE 6 update 10), needs to be enabled in order to view applets that leverage features of this Java Plug-in. The next generation Java Plug-in is not enabled by default on Mac OS systems. So here are a few tips to enable the plug-in.
  • Upgrade to a 6u17 based Java update. This support page from Apple might be helpful.
  • Open the Java Preferences application and toggle setting to "Run applets: in their own process".
  • Restart your browser and try viewing the applet.
When using Firefox 3.5 and above, in some cases the Java Preferences setting does not fully disable the default MRJPlugin and fully enable the next generation Java Plug-in. If after the performing the above steps you still have problems viewing some applets, you will need to go to the guts of the problem. :-)

Perform the following steps to disable the default MRJPlugin:

  • Go to the /Applications/Firefox.app/Contents/MacOS/plugins directory.
  • Move the following files to a temp directory or another location:
    • JavaEmbeddedPlugin.bundle
    • MRJPlugin.plugin
  • Restart your browser.
  • To check which plug-in is being used by your browser, view the about:plugins URL. An entry titled "JavaPlugin2_NPAPI.plugin" indicates that the next generation Java Plug-in is enabled in your browser.

You can now enjoy Java applets on MacOS!

- Sowmya

Wednesday Nov 25, 2009

Java Applets Quiz

Do you enjoy quizzes? Take a minute to answer this quiz about Java applets. Java Applets Quiz

Don't worry you wont be graded. ;-)

-- Sowmya Kannan

Tuesday Nov 24, 2009

Getting Applets To Talk To Each Other

Do you have more than one applet on a web page? Do you want the applets to share water cooler gossip? Ahem..ahem.. On a more serious note, do you want one applet to invoke methods or set variables of another applet?

Long long ago, you may have accomplished applet communication with the use of static variables. This method of sharing applet data is not fool proof. Different applets may run in different instances of the Java Virtual Machine software. This makes it impossible for an applet to see static variables set by another applet.

An applet can communicate with other applets by using JavaScript functions in the parent web page. JavaScript functions enable communication between applets by receiving messages from one applet and invoking methods of other applets. See the following topics for more information about the interaction between Java code and JavaScript code:

You should avoid using the following mechanisms to find other applets and share data between applets:

  • Avoid using static variables to share data between applets.
  • Do not use the getApplet and getApplets methods of the AppletContext class to find other applets. These methods only find applets that are running in the same instance of the Java Runtime Environment software.

Applets must originate from the same directory on the server in order to communicate with each other.

Consider two applets called Sender and Receiver. When a user clicks the button to increment the counter, the Sender applet invokes a JavaScript function to send a request to the Receiver applet. Upon receiving the request, the Receiver applet increments a counter variable and displays the value of the variable.

To enable communication with another applet, obtain a reference to an instance of the netscape.javascript.JSObject class. Use this instance to invoke JavaScript functions. The Sender applet uses an instance of the netscape.javascript.JSObject class to invoke a JavaScript function called sendMsgToIncrementCounter.

try {
    JSObject window = JSObject.getWindow(this);
    window.eval("sendMsgToIncrementCounter()");
} catch (JSException jse) {
    ...
}

Note: To compile Java code that has a reference to classes in the netscape.javascript package, include <your JDK path>/jre/lib/plugin.jar in your classpath. At runtime, the Java Plug-in software automatically makes these classes available to applets.

Write the JavaScript function that will receive requests from one applet and invoke methods of another applet on the web page. The sendMsgToIncrementCounter JavaScript function invokes the Receiver applet's incrementCounter method.

<script>
    function sendMsgToIncrementCounter() {            
        receiver.incrementCounter();
    }
<script>

Note that the JavaScript code uses the name receiver to obtain a reference to the Receiver applet on the web page. This name should be the same as the value of the id attribute that is specified when you deploy the Receiver applet.

The Receiver applet's incrementCounter method is shown next.

public void incrementCounter() {
    ctr++;
    String text = " Current Value Of Counter: " + (new Integer(ctr)).toString();
    ctrLbl.setText(text);
}

Deploy the applets on the web page as shown in the following code snippet. You can view the Sender and Receiver applets and associated JavaScript code in AppletPage.html in this example's source code..

<!-- Sender Applet -->
<script src="/old?u=http%3A%2F%2Fwww.java.com%2Fjs%2FdeployJava.js&y=1999"></script>
<script> 
    var attributes = { code:'Sender.class',
        archive:'examples/dist/applet_SenderReceiver/applet_SenderReceiver.jar',  width:300, height:50} ;
    var parameters = {};
    deployJava.runApplet(attributes, parameters, '1.6');
</script>

<!-- Receiver Applet -->
<script> 
    var attributes = { id:'receiver', code:'Receiver.class',
        archive:'examples/dist/applet_SenderReceiver/applet_SenderReceiver.jar',  width:300, height:50} ;
    var parameters = {};
    deployJava.runApplet(attributes, parameters, '1.6');

</script>

Download source code for the Sender Receiver Applets example to experiment further.

As always, please don't hesitate to send us your feedback!

-- Sowmya Kannan

Friday Nov 13, 2009

Re-spin Your Desktop Application Into A Java Web Start Application

Do you have a desktop application that you'd like to distribute to a wider audience? How about monetizing your application by showcasing it on the Java Store?

Check out the screencast for valuable information about how to accomplish this.

Download the source code for the Menu Application shown in the screencast.

See the following resources for more information:

We would be delighted to hear feedback about the screencast!

-- Sowmya Kannan

Monday Oct 12, 2009

Update -- Mixing Heavyweight and Lightweight Components article

On Sept 23rd, I posted about a new article that describes how you can easily mix heavyweight and lightweight components in 6u12 and JDK7. The calculator example included with the article tickled a known bug on some systems.

The example has now been updated with the recommended workaround. Also, the text of the article calls out the workaround (see the first bullet under the Requirements section).

Thanks, as always, for your feedback!

-- Sharon Zakhour

Tuesday Sep 22, 2009

Java Tutorial Update

We have just pushed an updated version of the Java Tutorial to the web. This update features:

Please let us know what you think!

- Sharon Zakhour

Thursday Aug 13, 2009

Translucent and Shaped Windows in JDK7

Here is another sneak peek at a page that was just completed for the JDK7 update of the Swing tutorial.

Let us know what you think.

-- Sharon Zakhour

How to Create Translucent and Shaped Windows

As of the Java SE 6 update 10 (6u10) release, you can add translucent and shaped windows to your Swing applications. This functionality, part of the public AWT package in JDK 7, takes three forms:
  • You can create a window with uniform translucency, where each pixel has the same translucency (or alpha) value. The following screen shot shows a window with 45% translucency:

    A translucent window

  • You can create a window with per-pixel translucency, where each pixel has its own alpha value. With this feature you can, for example, create a window that fades away to nothing by defining a gradient in the alpha values. The following screenshot shows a window with gradient translucency from the top (fully translucent) to the bottom (fully opaque):

    A window with per-pixel translucency.

  • You can create a window with any Shape that you can define. Shaped windows can be opaque, or can use uniform, or per-pixel translucency. The following screen shot shows an oval-shaped window with 30% translucency:

    A oval-shaped window.

This page covers the following topics:

Determining a Platform's Capabilities

Not all platforms support all of these capabilities. An UnsupportedOperationException exception is thrown when code attempts to invoke setShape or setOpacity on a platform that does not support these features. Therefore, it is best practice to first check that the platform supports the capability you want to implement. The GraphicsDevice class provides the isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency) method that you can use for this purpose. You pass one of three enum values, defined in GraphicsDevice.WindowTranslucency, to this method:
  • TRANSLUCENT – The underlying platform supports windows with uniform translucency, where each pixel has the same alpha value.
  • PERPIXEL_TRANSLUCENT – The underlying platform supports windows with per-pixel translucency. This capability is required to implement windows that fade away.
  • PERPIXEL_TRANSPARENT – The underlying platform supports shaped windows.
The GraphicsConfiguration class also provides the isTranslucencyCapable method to determine if PERPIXEL_TRANSLUCENT translucency is supported by the given GraphicsConfiguration object.

Version note: Translucent and shaped window API was first added to the JavaSE 6 update 10 release as a private API. This functionality was moved to the public AWT package in the JDK 7 release. This tutorial describes the API available in the JDK 7 release. See JavaSE Release 6 update 10 API for a mapping of the private API in 6u10 to the public API in the JDK 7 release.
The following code shows how to check for all three capabilities:
import static java.awt.GraphicsDevice.WindowTranslucency.\*;

// Determine what the default GraphicsDevice can support.
GraphicsEnvironment ge =
    GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice gd = ge.getDefaultScreenDevice();

boolean isUniformTranslucencySupported =
    gd.isWindowTranslucencySupported(TRANSLUCENT);
boolean isPerPixelTranslucencySupported =
    gd.isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT);
boolean isShapedWindowSupported =
    gd.isWindowTranslucencySupported(PERPIXEL_TRANSPARENT);

Note: None of these capabilities work on windows in full screen mode. Invoking any of the relevant methods while in full-screen mode causes an IllegalComponentStateException exception to be thrown.

How to Implement Uniform Translucency

You can easily create a window where each pixel has the same translucency by invoking the setOpacity(float) method in the Window class. The float argument passed to this method should be between 0 and 1, inclusive, and represents the translucency of the window. The smaller the number, the more transparent the window. There is also a corresponding getOpacity method.

The following example creates a window that is 55% opaque (45% translucent). If the underlying platform does not support translucent windows, the example exits. The code relating to opacity is shown in bold.

import java.awt.\*;
import javax.swing.\*;
import static java.awt.GraphicsDevice.WindowTranslucency.\*;

public class TranslucentWindow extends JFrame {
    public TranslucentWindow() {
        super("TranslucentWindow");
        setLayout(new GridBagLayout());

        setSize(300,200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Add a sample button.
        add(new JButton("I am a Button"));
    }

    public static void main(String[] args) {
        // Determine if the GraphicsDevice supports translucency.
        GraphicsEnvironment ge = 
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();

        //If translucent windows aren't supported, exit.
        if (!gd.isWindowTranslucencySupported(TRANSLUCENT)) {
            System.err.println(
                "Translucency is not supported");
                System.exit(0);
        }

        // Create the GUI on the event-dispatching thread
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                TranslucentWindow tw = new TranslucentWindow();

		// Set the window to 55% opaque (45% translucent).
                tw.setOpacity(0.55f);

		// Display the window.
		tw.setVisible(true);
	    }
        });
    }
}

Note that the button is also affected by the uniform translucency. Setting the opacity affects the whole window, including any components that the window contains.

How to Implement Per-Pixel Translucency

Creating a window that uses per-pixel translucency involves defining alpha values over the rectangular area that the window occupies. When a pixel's alpha is zero, that pixel is fully transparent. When a pixel's alpha is 255, that pixel is fully opaque. When a pixel's alpha is 128, that pixel is 50% translucent, and so on. An easy way to create a smooth interpolation between alpha values is to use the GradientPaint class. The included example uses this approach.

Invoking setBackground(new Color(0,0,0,0)) on the window causes the software to use the alpha values to render per-pixel translucency. In fact, invoking setBackground(new Color(0,0,0,alpha), where alpha is less than 255, installs per-pixel transparency. So, if you invoke setBackground(new Color(0,0,0,128)) and do nothing else, the window is rendered with 50% translucency for each background pixel. However, if you are creating your own range of alpha values, you most likely will want an alpha value of 0.

While not prohibited by the public API, you will generally want to enable per-pixel translucency on undecorated windows. In most cases, using per-pixel translucency on decorated windows does not make sense, and can disable the decorations, or cause other platform-dependent side effects.

To determine if a window is using per-pixel translucency, you can use the isOpaque method.

An example is included below. The steps required to implement the example are as follows:

  • Invoke setBackground(new Color(0,0,0,0)) on the window.
  • Create a JPanel instance that overrides the paintComponent method.
  • In the paintComponent method, create a GradientPaint instance. In the included example, the top of the rectangle has an alpha of 0 (the most transparent) and the bottom has an alpha of 255 (the most opaque). The GradientPaint class smoothly interpolates the alpha values from the top to the bottom of the rectangle.
  • Set the GradientPaint instance as the panel's paint method.

Here is the code for the GradientWindow example. If the underlying platform does not support per-pixel translucency, this example exits. The code specifically relating to creating the gradient window is shown in bold.

import java.awt.\*;
import javax.swing.\*;
import static java.awt.GraphicsDevice.WindowTranslucency.\*;

public class GradientTranslucentWindow extends JFrame {
    public GradientTranslucentWindow() {
        super("GradientTranslucentWindow");

        setBackground(new Color(0,0,0,0));
        setSize(new Dimension(300,200));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel() {
            @Override
            protected void paintComponent(Graphics g) {
                if (g instanceof Graphics2D) {
                    final int R = 240;
                    final int G = 240;
                    final int B = 240;

                    Paint p =
                        new GradientPaint(0.0f, 0.0f, new Color(R, G, B, 0),
                            0.0f, getHeight(), new Color(R, G, B, 255), true);
                    Graphics2D g2d = (Graphics2D)g;
                    g2d.setPaint(p);
                    g2d.fillRect(0, 0, getWidth(), getHeight());
                }
            }
        };
        setContentPane(panel);
        setLayout(new GridBagLayout());
        add(new JButton("I am a Button"));
    }

    public static void main(String[] args) {
        // Determine what the GraphicsDevice can support.
        GraphicsEnvironment ge = 
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();
        boolean isPerPixelTranslucencySupported = 
            gd.isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT);

        //If translucent windows aren't supported, exit.
        if (!isPerPixelTranslucencySupported) {
            System.out.println(
                "Per-pixel translucency is not supported");
                System.exit(0);
        }

        JFrame.setDefaultLookAndFeelDecorated(true);

        // Create the GUI on the event-dispatching thread
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                GradientTranslucentWindow gtw = new GradientTranslucentWindow();

		// Display the window.
		gtw.setVisible(true);
	    }
        });
    }
}

Note that the button is not affected by the per-pixel translucency. Setting the per-pixel translucency affects the background pixels only. If you want a window that has a uniformly translucent effect on the background pixels only, you can invoke setBackground(new Color(0,0,0,alpha)) where alpha specifies your desired translucency.

How to Implement a Shaped Window

You can easily create a shaped window by invoking the setShape(Shape) method in the Window class. The Shape passed to the method determines how the window is clipped. When setting a shape on a window, the window decorations are not re-formed to the new shape, so it works best on undecorated windows.

The best practice for setting the window's shape is to invoke setShape in the componentResized method of the component event listener. This will ensure that the shape is correctly calculated for the actual size of the window. The included example uses this approach.

The following example creates an oval-shaped window with 70% translucency. If the underlying platform does not support shaped windows, the example exits. If the underlying platform does not support translucency, the example uses an opaque window. You could modify this example to create a shaped window that also uses per-pixel translucency.

The code relating to shaping the window is shown in bold.

import java.awt.\*;
import java.awt.event.\*;
import javax.swing.\*;
import java.awt.geom.Ellipse2D;
import static java.awt.GraphicsDevice.WindowTranslucency.\*;

public class ShapedWindow extends JFrame {
    public ShapedWindow() {
        super("ShapedWindow");
        setLayout(new GridBagLayout());

        // It is best practice to set the window's shape in
        // the componentResized method.  Then, if the window
        // changes size, the shape will be correctly recalculated.
        addComponentListener(new ComponentAdapter() {

            // Give the window an elliptical shape.
            // If the window is resized, the shape is recalculated here.
            @Override
            public void componentResized(ComponentEvent e) {
	        setShape(new Ellipse2D.Double(0,0,getWidth(),getHeight()));
            }
        });

        setUndecorated(true);
        setSize(300,200);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        add(new JButton("I am a Button"));
    }

    public static void main(String[] args) {
        // Determine what the GraphicsDevice can support.
        GraphicsEnvironment ge = 
            GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();
        final boolean isTranslucencySupported = 
            gd.isWindowTranslucencySupported(TRANSLUCENT);

        //If shaped windows aren't supported, exit.
        if (!gd.isWindowTranslucencySupported(PERPIXEL_TRANSPARENT)) {
            System.err.println("Shaped windows are not supported");
            System.exit(0);
        }

        //If translucent windows aren't supported, 
        //create an opaque window.
        if (!isTranslucencySupported) {
            System.out.println(
                "Translucency is not supported, creating an opaque window");
        }

        // Create the GUI on the event-dispatching thread
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                ShapedWindow sw = new ShapedWindow();

		// Set the window to 70% translucency, if supported.
		if (isTranslucencySupported) {
		    sw.setOpacity(0.7f);
		}

		// Display the window.
		sw.setVisible(true);
	    }
        });
    }
}

JavaSE Release 6 Update 10 API

Changing public API in an update release is not allowed, so when the translucent and shaped windows capability was added to the JavaSE 6u10 release, it was implemented in the private com.sun.awt.AWTUtilities class. For the JDK7 release, this functionality was moved to the public AWT package. The following table shows how the private methods map to the public methods.

Method in JavaSE 6u10 JDK 7 Equivalent
AWTUtilities.isTranslucencySupported(Translucency) GraphicsDevice.isWindowTranslucencySupported(WindowTranslucency)
AWTUtilities.isTranslucencyCapable(GraphicsConfiguration) GraphicsConfiguration.isTranslucencyCapable()
AWTUtilities.setWindowOpacity(Window, float) Window.setOpacity(float)
AWTUtilities.setWindowShape(Window, Shape) Window.setShape(Shape)
AWTUtilities.setWindowOpaque(boolean) Window.setBackground(Color) – passing new Color(0,0,0,alpha) to this method, where alpha is less than 255, installs per-pixel translucency.

For More Information

Saturday Jul 25, 2009

NIO.2 Updates in JDK7

If you are already using the new file I/O API provided in JDK7, you should be aware that there are some minor API changes as of build 64. If you are using the JavaOne Preview release, the changes have not yet been integrated, but they are available now on java.net.

The API is changed as follows:

  • Path.delete(boolean) is now Path.deleteIfExists(). So, delete(true) is equivalent to delete(), and delete(false) is equivalent to deleteIfExists().
  • The time stamp methods in the Attribute class that took long, TimeUnit arguments now take an instance of the new FileTime class. Similarly, the BasicFileAttributes time stamp methods now return an instance of FileTime. The new method signatures are:
    • Attributes.setLastAccessTime(FileRef, FileTime)
    • Attributes.setLastModifiedTime(FileRef, FileTime)
    • FileTime creationTime() in BasicFileAttributes
    • FileTime lastAccessTime() in BasicFileAttributes
    • FileTime lastModifiedTime() in BasicFileAttributes
  • The BasicFileAttribute.linkCount() method has been removed.
  • The BasicFileAttribute.resolution() method has been removed.

The File I/O lesson in the Java Tutorials has been updated with the new API.

-- Sharon Zakhour

Tuesday Jun 02, 2009

Deploying Your Rich Internet Application Nice And Easy!

You've developed this cool web site with snazzy Java rich internet applications that are certain to wow the end user. Now, the million dollar question - will your rich internet applications (RIA - applet or Java Web Start application) start up quickly and run consistently across all browsers and operating systems?

Do you wish you could determine the end user's browser, or Java Runtime Environment (JRE) version and customize the user experience based on that? Wouldn't it be nice if you could deliver the same user experience irrespective of the user's environment?

Recent improvements in the browser's Java Plug-in, support for applet deployment with JNLP, and the Deployment Toolkit, can help you build a web site that is robust and has a custom, well thought out user experience for every end user environment.

The Java One presentation, "Deploying Java Technologies To The Masses" By Thomas Ng, provides valuable insight into how Java Deployment technology can be leveraged to easily deploy rich internet applications. This blog highlights some of the deployment tips using examples.

Consider this scenario - You have a web site called "Design Your Home" that lets end users design their home by creating a floor plan and picking various interior decoration options. You have developed some very cool applets that let users drag and drop widgets, make choices and see their dream home being built...virtually. :-)

You are of course, a wordly-wise developer who knows that folks have various versions of operating systems, browsers and JREs running on their computers. Your applets need at least JRE version 1.6.0_10 (Java SE 6 u 10) to run correctly. So you've built a couple of different versions of the functionality to accommodate older environments. And as far as possible, you want the user to have a smooth un-interrupted experience on your web site. You also want to applets to load up quickly so that users don't get frustrated by slow loading web pages.

Let's explore several ways to improve performance and user experience and see how deployment technologies can be used to accomplish this goal. See the Related Reading section for other deployment related information.

Reducing your RIA's download time

The time it takes to download a RIA, depends on the size of your RIA jar file (DynamicTreeDemo.jar is the RIA's jar file in this example). Deploy pack200 compressed jar files as shown below.

  • Compress the jar file using the pack200 tool
    // compresses DynamicTreeDemo.jar to produce DynamicTreeDemo.jar.pack.gz
    $ pack200 DynamicTreeDemo.jar.pack.gz DynamicTreeDemo.jar
      		
  • Set the jnlp.packEnabled property in the JNLP file
    // add the jnlp.packEnabled property in the JNLP file for the RIA
    <resources>
        <!-- Application Resources -->
    		<j2se version="1.6+"
    		    href=/old?u=http%3A%2F%2Fblogs.oracle.com%2Fthejavatutorials%2Ftags%2F%26quot%3Bhttp%3A%2Fjava.sun.com%2Fproducts%2Fautodl%2Fj2se%26quot&y=1999
    				max-heap-size="128m" />
    		<jar href=/old?u=http%3A%2F%2Fblogs.oracle.com%2Fthejavatutorials%2Ftags%2F%26quot%3BDynamicTreeDemo.jar%26quot%3B&y=1999 main="true"/>
    		<property name="jnlp.packEnabled" value="true"/>
    		...
    		...
    </resources>

    When the jnlp.packEnabled property is set, the Java Plug-in looks for the appropriate jar file with the .pack.gz extension (e.g. DynamicTreeDemo.jar.pack.gz). If found, the Java Plug-in automatically unpacks and loads the jar file. If a file with the .pack.gz extension is not found, then it attempts to load the jar file itself (e.g. DynamicTreeDemo.jar).

    If you plan to sign your RIA, pack first and then sign.

  • Remove unnecessary white space from the JNLP file and JavaScript files.
  • Optimize images and animation to reduce download time.

Note: You need to deploy your RIA on a web server to use / test this property

Improving start up time by avoiding unnecessary update checks

RIAs are cached locally to improve start up time. However, before launching the RIA, the Java Plug-in checks to make sure that every jar file referenced in the JNLP file is up-to-date. In other words, the Java Plug-in makes sure that you are running the latest version of the RIA and not an older cached copy. These update checks can take up to a few hundred milliseconds depending on the number of jar files and network speed.

You can leverage the version download protocol to eliminate unnecessary version checks. See the steps below to enable this protocol.

  • Rename the jar files to include a version number suffix
    naming convention - <jar file name> "__V" <version number> ".jar"
    example - DynamicTreeDemo__V1.0.jar		 		 
    		 
  • In the JNLP file, specify a version for every jar file. Set the jnlp.versionEnabled property to true.
    <resources>
        <!-- Application Resources -->
    		<j2se version="1.6+"
    		    href=/old?u=http%3A%2F%2Fblogs.oracle.com%2Fthejavatutorials%2Ftags%2F%26quot%3Bhttp%3A%2Fjava.sun.com%2Fproducts%2Fautodl%2Fj2se%26quot&y=1999
    				max-heap-size="128m" />
    		<jar href=/old?u=http%3A%2F%2Fblogs.oracle.com%2Fthejavatutorials%2Ftags%2F%26quot%3BDynamicTreeDemo.jar%26quot%3B&y=1999 main="true" version="1.0"/>
    		<jar href=/old?u=http%3A%2F%2Fblogs.oracle.com%2Fthejavatutorials%2Ftags%2F%26quot%3BSomeOther.jar%26quot%3B&y=1999 version="2.0"/>
    		<property name="jnlp.versionEnabled" value="true"/>
    		...
    		...
    </resources>

    When the jnlp.versionEnabled property is enabled, the Java Plug-in performs only one update check to make sure the JNLP file is up-to-date. It compares the version numbers specified in the JNLP file with the corresponding jar file versions (per the naming convention mentioned above) and updates only the outdated jar files. This is efficient because only the update check for the JNLP file happens over the network. All other version checks happen locally.

    If a file with the correct version number is not found, the Java Plug-in attempts to load the default jar file (e.g. DynamicTreeDemo.jar).

If it is not critical for the user to immediately run the latest version of your RIA, you may run the update check in the background. The newer version will be launched the next time the user uses your RIA. Add the following to your JNLP file:

<update check='background'/>

Note:

  • When using jnlp.versionEnabled and jnlp.packEnabled properties together, rename the packed jar file per the version protocol naming convention (e.g. DynamicTreeDemo__V1.0.jar.pack.gz)
  • You need to deploy your RIA on a web server to use / test this property

Signing RIAs only when necessary

Signed RIAs will display security warnings to the user. When trying to access a simple RIA, security dialogs may unnerve users and turn them away from the application. So, sign only if you need to (for example, when accessing native libraries)

Recent enhancements to RIA security model eliminate the need to sign your RIA in the following cases:

  • Accessing services on web sites other than the RIA's own domain - The Java Plug-in has support for cross domain policy files. This means that if the third-party site allows access from other domains, then your unsigned RIAs can invoke services from these sites
  • Setting trusted VM arguments - You do not need to sign your RIA to pass secure VM arguments. You can set secure VM arguments in the JNLP file or specify them directly in the java_arguments parameter in the applet tag. Examples of secure VM arguments include maximum heap size, sun.java2d.noddraw, javax.swing.defaultlf etc.
  • Setting system properties used by your RIA only - You may need to set some system properties that only your RIA needs to use. If the name of the system property begins with jnlp. then you do not need to sign your RIA.

Preloading your Java Web Start application

If you plan to deploy your RIA as a Java Web Start application in an enterprise where you have some administrative control, you can preload your application to various clients so that it is cached and ready to use. Use the following command to preload your Java Web Start application:

javaws -import -silent <jnlp url>

Ensuring that the correct version of Java is installed on the client

With the Deployment Toolkit, you have at least two ways to handle this.

  1. You can check and make sure users have or install the latest JRE as soon as they land on your web site, or,
  2. You can let them surf the site, and check and get the latest JRE only when they attempt to use your rich internet application.

Let's explore each option. To use the Deployment Toolkit, the client's browser should have JavaScript enabled.

Checking and installing the latest JRE as soon as the user lands on your web site

The example below checks if a user has JRE version 1.6.0_13 or greater installed. If not, it installs the latest JRE.

<script src="/old?u=http%3A%2F%2Fjava.com%2Fjs%2FdeployJava.js&y=1999"></script>
<script>
    
    // check if current JRE version is greater than 1.6.0 
    alert("versioncheck " + deployJava.versionCheck('1.6.0_10+'));
    if (deployJava.versionCheck('1.6.0_10+') == false) {                   
        userInput = confirm("You need the latest Java(TM) Runtime Environment. Would you like to update now?");        
        if (userInput == true) {  
    
            // Set deployJava.returnPage to make sure user comes back to 
            // your web site after installing the JRE
            deployJava.returnPage = location.href;
            
            // install latest JRE or redirect user to another page to get JRE from.
            deployJava.installLatestJRE(); 
        }
    }
</script>

Installing correct JRE only when the user attempts to use your RIA

If you deploy your rich internet application using the Deployment Toolkit, you do not have to take any additional steps to ensure that the client has a specific JRE version. The functions described below also deploy your RIA using the correct HTML tags (applet, object, embed), depending on the user's environment.

Use the runApplet function to deploy an applet, as shown in the example below. The last parameter to the runApplet function is the minimum version required to the run your applet.

    
    <script src=/old?u=http%3A%2F%2Fblogs.oracle.com%2Fthejavatutorials%2Ftags%2F%26quot%3Bhttp%3A%2Fjava.com%2Fjs%2FdeployJava.js%26quot%3B%26gt%3B%26lt%3B%2Fscript%26gt&y=1999
		<script>
			var attributes = { code:'components.DynamicTreeApplet',  width:300, height:300};
			var parameters = {jnlp_href: 'dynamictree-applet.jnlp'};
			deployJava.runApplet(attributes, parameters, '1.6');
		</script>

To deploy as a Java Web Start application, use the createWebStartLaunchButton function with the correct minimum version parameter.

    <script src=/old?u=http%3A%2F%2Fblogs.oracle.com%2Fthejavatutorials%2Ftags%2F%26quot%3Bhttp%3A%2Fjava.com%2Fjs%2FdeployJava.js%26quot%3B%26gt%3B%26lt%3B%2Fscript%26gt&y=1999
		<script>
        var url = "dynamictree-applet.jnlp";
        deployJava.createWebStartLaunchButton(url, '1.6.0');
		</script>

The runApplet and createWebStartLaunchButton functions check the client's version of Java. If the minimum version is not installed, they install the latest version of Java.

Customizing RIA's splash screen

You can customize the splash screen for your RIA. This ensures a consistent RIA loading experience across all platforms.

For Java based RIAs, specify the image attribute to customize the splash screen.

    <script src=/old?u=http%3A%2F%2Fblogs.oracle.com%2Fthejavatutorials%2Ftags%2F%26quot%3Bhttp%3A%2Fjava.com%2Fjs%2FdeployJava.js%26quot%3B%26gt%3B%26lt%3B%2Fscript%26gt&y=1999
		<script>
			var attributes = {code:'components.DynamicTreeApplet',  width:300, height:300};
			var parameters = {jnlp_href: 'dynamictree-applet.jnlp', 
                   			image: 'dukeanimated.gif'};
			deployJava.runApplet(attributes, parameters, '1.6');
		</script>

For Java FX based RIAs, specify the loading_image_url and related attributes as shown below

    <script src="/old?u=http%3A%2F%2Fdl.javafx.com%2F1.2%2Fdtfx.js&y=1999"></script>
    javafx({
           archive: "BouncingBall.jar",
           width: 240,
           height: 320,
           code: "bounce.Main",
           name: "BouncingBall",
           loading_image_url: "loading.gif",
           loading_image_height: 100,
           loading_image_width: 100
    }); 

Java FX Packager

If you are building a Java FX application, use the Java FX Packager to deploy your application. The Java FX Packager accepts a few user options and automatically

  • compiles the Java FX source code
  • generates, signs and packs jar files
  • generates JNLP and HTML files

With these neat tools and tips, you should be able to deploy your rich internet applications flawlessly and efficiently across multiple platforms.

Related Reading

Please let us know if you'd like more information on specific topics. As always, we welcome feedback!


-- Sowmya Kannan

Wednesday May 27, 2009

Just released -- Java Tutorials update

To coincide with the JDK7 Preview Release and JavaOne, we have just published an updated version of the Java Tutorials. Besides fixing many typos and errors that you have reported, this release includes:

  • An entirely reworked File I/O lesson, featuring NIO.2. This functionality is part of JDK7, which is available now through the Open JDK project on java.net.
  • A new specialized trail covering Sockets Direct Protocol, also new in JDK7.
  • A new facility for gathering feedback about the tutorial. At the bottom of each tutorial page, under the "Discuss" heading, you can leave a publicly viewable, blog-style comment. Let us know what you think about the inclusion of this JS-Kit mechanism.

Thanks, as always, for your feedback. It helps us improve the tutorial!

-- Sharon Zakhour

Wednesday May 13, 2009

Watching A Directory for Changes — File Change Notification in NIO.2

Here is a sneak peek of the NIO.2 file coverage I am writing for the Java Tutorial. This will be available in the web push of the tutorial that coincides with the upcoming J1 Preview Release. (NIO.2 is part of the JDK 7 release.)

-- Sharon Zakhour


Have you ever found yourself editing a file, using an IDE or another editor, and a dialog pops up to inform you that one of the open files has changed on the file system and needs to be reloaded? Or perhaps, like the NetBeans IDE, it just quietly updates the file without making a fuss. The following sample dialog shows how this looks when using the free editor, jEdit:

Sample jEdit Dialog stating: The following files were changed on disk by another
 program.

jEdit Dialog — Modified File is Detected

To implement this functionality, called file change notification, a program needs to be able to detect what is happening to the relevant directory on the file system. One way to do this is to poll the file system looking for changes, but this approach is inefficient — it does not scale to applications that may have hundreds of open files or directories to monitor.

The java.nio.file package provides a file change notification API, called the Watch Service API. This API allows you to register a directory (or directories) with the watch service — when registering you tell the service which types of events you are interested in: file creation, file deletion, or file modification. When the service detects an event of interest, it is forwarded to the registered process. The registered process has a thread (or a pool of threads) dedicated to watching for any events it has registered for. When one comes in, it is handled as needed.

This section covers:

WatchService Overview

The WatchService API is fairly low-level, allowing you to customize it — you can use it as-is, or you may choose to create a high-level API on top of this mechanism suited to your particular needs.

Here are the basic steps required to implement a watch service:

  • Create a WatchService "watcher" for the file system.
  • For each directory that you want monitored, register it with the watcher. When registering a directory, you specify the type of events for which you want notification. You receive a WatchKey instance for each directory that you register.
  • Implement an infinite loop to wait for incoming events.
  • When an event occurs, the key is signaled and placed into the watcher's queue.
  • The key is retrieved from the watcher's queue. You can obtain the file name from the key.
  • Retrieve each pending event for the key (there may be multiple events) and process as needed.
  • Reset the key and resume waiting for events.
  • The watch service exits when either the thread exits or when each directory being watched becomes inaccessible.

WatchKeys are thread safe and can be used with the java.nio.concurrent package. You can dedicate a thread pool to this effort.

Try it Out

Because this is a more advanced API, we encourage you to try it out before proceeding. Save the WatchDir example to your computer and compile it. Create a test directory — this is passed to the example. WatchDir uses a single thread to process all events, so it blocks while waiting for events — either run it in a separate window or in the background, like this:

java WatchDir test &

Play with creating, deleting and editing files in the test directory. When any of these events occurs, a message is printed to the console. When you have finished, delete the test directory and WatchDir exits. Or, if you prefer, you can manually kill the process.

You can also watch an entire file tree by specifying the -r option. When you specify -r, WatchDir walks the file tree, registering each directory with the watch service.

Creating a Watch Service and Registering for Events

The first step is to create a new WatchService, using the newWatchService method in the FileSystem class:

WatchService watcher = FileSystems.getDefault().newWatchService();

Next, register one or more objects with the watch service. Any object that implements the Watchable interface can be registered. The Path class implements the Watchable interface, so each directory to be monitored is registered as a Path object.

As with any Watchable, the Path class implements two register methods. This section uses the two-argument version, register(WatchService, WatchEvent.Kind<?>...). (The three-argument version takes a WatchEvent.Modifier which is not currently implemented.)

When registering an object with the watch service, you specify the types of events you want to monitor. The supported StandardWatchEventKind event types are:

  • ENTRY_CREATE — a directory entry is created.
  • ENTRY_DELETE — a directory entry is deleted.
  • ENTRY_MODIFY — a directory entry is modified;
  • OVERFLOW — indicates that events may have been lost or discarded. You do not have to register for this event to receive it.

The following code snippet shows how to register a Path instance for all three event types:

import static java.nio.file.StandardWatchEventKind.\*;

Path dir = ...;
try {
    WatchKey key = dir.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
} catch (IOException x) {
    System.err.println(x);
}

Processing Events

The order of events in an event processing loop are:

  1. Get a watch key. There are three methods provided:
    • poll — returns a queued key, if any is available. Returns immediately, with a null value, if none is present.
    • poll(long, TimeUnit) — returns a queued key, if one is available. If one is not immediately available it waits up until the specified time. The TimeUnit argument determines whether the specified time is nanoseconds, milliseconds, or some other unit of time.
    • take — returns a queued key. If none is available, this method waits.
  2. Process the pending events for the key. You fetch the List of WatchEvents from the pollEvents method.
  3. Retrieve the type of event using the kind method. No matter what events the key has registered for, it is possible to receive an OVERFLOW event. You may choose to handle the overflow or ignore it, but you should test for it.
  4. Retrieve the file name associated with the event. The file name is the context of the event, so the context method is used to retrieve it.
  5. After the events for the key have been processed, you need to put it back into a ready state by invoking reset. If this method returns false, the key is no longer valid and the loop can exit. This step is very important — if you fail to invoke reset, this key will not receive any further events.

A watch key has a state — at any given time, its state might be:

  • Ready indicates that the key is ready to accept events. When first created, a key is in the ready state.
  • Signaled indicates that one or more events are queued. Once the key has been signaled, it is no longer in the ready state until the reset method is invoked.
  • Invalid — indicates that the key is no longer active. This happens when one of the following events occurs:
    • The process explicitly cancels the key using the cancel method.
    • The directory becomes inaccessible.
    • The watch service is closed.

Here is an example of an event processing loop. It is lifted from the Email example which watches a directory, waiting for new files to appear. When a new file becomes avaiable, it is examined to see if it is a text/plain file using the probeContentType method. The intention is that plain text files will be emailed to an alias, but that implementation detail is left to the reader.

The methods specific to the watch service API have been bolded:

for (;;) {

    //wait for key to be signaled
    WatchKey key;
    try {
        key = watcher.take();
    } catch (InterruptedException x) {
        return;
    }

    for (WatchEvent<?> event: key.pollEvents()) {
        WatchEvent.Kind<?> kind = event.kind();

        //This key is registered only for ENTRY_CREATE events,
        //but an OVERFLOW event can occur regardless if events are
        //lost or discarded.
        if (kind == OVERFLOW) {
            continue;
        }

        //The filename is the context of the event.
        WatchEvent<Path> ev = (WatchEvent<Path>)event;
        Path filename = ev.context();

        //Verify that the new file is a text file.
        try {
            //Resolve the filename against the directory.
            //If the filename is "test" and the directory is "foo",
            //the resolved name is "test/foo".
            Path child = dir.resolve(filename);
            if (!Files.probeContentType(child).equals("text/plain")) {
                System.err.format("New file '%s' is not a plain text file.%n", filename);
                continue;
            }
        } catch (IOException x) {
            System.err.println(x);
            continue;
        }

        //Email the file to the specified email alias.
        System.out.format("Emailing file %s%n", filename);
        //Details left to reader....
    }

    //Reset the key -- this step is critical if you want to receive
    //further watch events. If the key is no longer valid, the directory
    //is inaccessible so exit the loop.
    boolean valid = key.reset();
    if (!valid) {
        break;
    }
}

Getting the Filename

The file name is retrieved from the event context. The Email example retrieves the file name with this code:

WatchEvent<Path> ev = (WatchEvent<Path>)event;
Path filename = ev.context();

When you compile the Email example, it generates the following error:

Note: Email.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

This is a result of the line of code that casts the WatchEvent<T> to a WatchEvent<Path>. The WatchDir example avoids this error by creating a utility cast method that suppresses the unchecked warning:

@SuppressWarnings("unchecked")
static <T> WatchEvent<T> cast(WatchEvent<?> event) {
    return (WatchEvent<Path>)event;
}
If you are unfamiliar with the @SuppressWarnings syntax, see the Annotations section.

When Not to Use this API

The Watch Service API is designed for applications that need to be notified about file change events. It is well suited for any application, like an editor or IDE, that potentially has many open files and needs to ensure that the files are in sync with the file system. It is also well suited for the app server that watches a directory, perhaps waiting for .jsp or .jar files to drop, in order to deploy them.

This API is not designed for indexing a hard drive. Most file system implementations have native support for file change notification — the Watch Service API takes advantage of this where available. But when a file system does not support this mechanism, the Watch Service will poll the file system, waiting for events.

Thursday Apr 02, 2009

Deployment Toolkit 101

Contents

What is the Deployment Toolkit or DT as it is affectionately referred to? :-)

The Deployment Toolkit is a set of JavaScript functions that can help developers easily deploy applets and Java Web Start applications (aka rich internet applications, RIAs) consistently across various browser and operating system configurations. As a developer, you now do not have to worry about handling the idiosyncracies of different clients. Just use the functions in the Deployment Toolkit - it takes care of all the underlying issues for you and generates the correct HTML.

Note:

  • We will use the phrase "rich internet applications" or "RIAs" in places where some functionality applies to both applets and Java Web Start applications.
  • Depending on the type of browser, you may not be able to see the HTML generated by the Deployment Toolkit when you try to view source for the page. To view the generated HTML, try saving the HTML page after its been loaded, or, use a tool such as Firebug (Mozilla Firefox add-on)

When was the Deployment Toolkit introduced and where can I find it?

The Deployment Toolkit was introduced in Java SE 6u10. It can be found at http://java.com/js/deployJava.js or https://www.java.com/js/deployJava.js

The http://java.com/js/deployJava.txt file contains the un-minimized version with comment blocks describing functions and usage.

Now that the introductions are done, let's move on to the details.

Using the Deployment Toolkit

Deploying an applet using the runApplet function

Use the runApplet function to deploy your applet. The runApplet function ensures that the required minimum version of the Java Runtime Environment (JRE) exists on the client and then runs the applet. It generates an <applet> tag with the information provided.

Function signature: runApplet: function(attributes, parameters, minimumVersion)

Parameters:

  • attributes: The attribute names and values of the generated <applet> tag
  • parameters: The names and values of the <param> tags in the generated <applet> tag
  • minimumVersion: The minimum version of JRE required to run this applet

Usage:

  • Specifying deployment options as attribute and parameter name-value pairs

    The attributes and parameters passed as name-value pairs are written out as attributes and nested <param> tags in the generated <applet> tag.

    // launch the Java 2D applet on JRE version 1.6.0 or higher with one parameter (fontSize)
    <script src="/old?u=http%3A%2F%2Fjava.com%2Fjs%2FdeployJava.js&y=1999"></script>
    <script>
        var attributes = {codebase:'http://java.sun.com/products/plugin/1.5.0/demos/jfc/Java2D',
                          code:'java2d.Java2DemoApplet.class',
                          archive:'Java2Demo.jar',
                          width:710, height:540} ;
        var parameters = {fontSize:16} ;
        var version = '1.6' ;
        deployJava.runApplet(attributes, parameters, version);
    </script>
    	
  • Using jnlp_href parameter to specify deployment options in a JNLP file

    The attributes and parameters (jnlp_href in this case) passed as name-value pairs are written out as attributes and nested <param> tags in the generated <applet> tag. It is better to specify the applet's width and height as attributes, as shown below.

    <script src="/old?u=http%3A%2F%2Fjava.com%2Fjs%2FdeployJava.js&y=1999"></script>
     <script> 
    		var attributes = { code:'java2d.Java2DemoApplet', width:710, height:540} ; 
    		var parameters = {jnlp_href: 'java2d.jnlp'} ; 
    		deployJava.runApplet(attributes, parameters, '1.6'); 
    </script>
    		
  • Specifying attribute and parameter name-value pairs as well as JNLP file

    Applets deployed using JNLP will run only if the end user has the next generation plug-in running on his / her browser (next generation plug-in introduced in Java SE 6u10). If you would like your applet to run on the old plug-in also, specify deployment options using attribute and parameter name-value pairs as well as JNLP file.

    <script src="/old?u=http%3A%2F%2Fjava.com%2Fjs%2FdeployJava.js&y=1999"></script>
    <script>	
    		var attributes = {codebase:'http://java.sun.com/products/plugin/1.5.0/demos/jfc/Java2D',
                            code:'java2d.Java2DemoApplet.class', archive:'Java2Demo.jar', 
                            width:710, height:540} ; 
    		var parameters = {fontSize:16, jnlp_href:'java2d.jnlp'} ; 
    		var version = '1.6' ; 
    		deployJava.runApplet(attributes, parameters, version);  	
    </script>
    
    If you are now wondering what happens if some deployment options have different values in the attributes name-value pairs and in the JNLP, read more about how final deployment information is determined.

Deploying a Java Web Start application using the createWebStartLaunchButton function

Use the createWebStartLaunchButton function to deploy a Java Web Start application. The createWebStartLaunchButton function generates a link (HTML anchor tag - <a> ) to the Java Web Start application's JNLP file.

This generated anchor tag is the Java Web Start application's button. When the end user clicks the Launch button, it ensures that an appropriate JRE is installed and then launches the Java Web Start application.

Function signature: createWebStartLaunchButton: function(jnlp, minimumVersion) or createWebStartLaunchButton: function(jnlp)

Parameters:

  • jnlp: The url of the JNLP file containing deployment information for the Java Web Start application. This needs to be an absolute path.
  • minimumVersion: The minimum version of JRE required to run this application

Usage:

  • Specifying a minimum JRE version that is required to run the application
    <script src="/old?u=http%3A%2F%2Fjava.com%2Fjs%2FdeployJava.js&y=1999"></script>
    <script>
        var url = "http://java.sun.com/javase/technologies/desktop/javawebstart/apps/notepad.jnlp";
        deployJava.createWebStartLaunchButton(url, '1.6.0');
    </script>
        

    Note: Running on any JRE version - Use the createWebStartLaunchButton: function(jnlp) function if your application does not have a minimum JRE requirement.

  • Working around the problem of specifying absolute URL for JNLP file

    The requirement of an absolute URL for the JNLP file of a Java Web Start application means that the web page is no longer easily portable between, for example, development, test and production environments. Obviously, the JNLP file path will be different in these environments and you should not have to change the url at each step. Applets do not have this problem because applets determine the codebase relative to the page in which they are embedded. You can simulate this behaviour with some JavaScript, such that the JNLP file's path is relative to the location of the web page from which the Java Web Start application will be launched. Here is some sample code:

    <script src="/old?u=http%3A%2F%2Fjava.com%2Fjs%2FdeployJava.js&y=1999"></script>		
    <script >
        var dir = location.href.substring(0,location.href.lastIndexOf('/')+1);
        var url = dir + "notepad.jnlp";
        deployJava.createWebStartLaunchButton(url, '1.6.0');
    </script>

Changing the Launch button of your Java Web Start application

You can change your Java Web Start application's Launch button, if you don't like the default button or you have another button that you have standardized on.

Use the deployJava.launchButtonPNG variable to point to the location of your image.

Variable: deployJava.launchButtonPNG

Usage:

  • Providing an alternate image url. In this example, the Launch button will now be an image of our own Duke waving
    		
    <script src=/old?u=http%3A%2F%2Fblogs.oracle.com%2Fthejavatutorials%2Ftags%2F%26quot%3Bhttp%3A%2Fjava.com%2Fjs%2FdeployJava.js%26quot%3B%26gt%3B%26lt%3B%2Fscript%26gt&y=1999
    <script>
        deployJava.launchButtonPNG='http://java.sun.com/products/jfc/tsc/articles/swing2d/WatermarkDemo/duke_wave.png'
        var url = "http://java.sun.com/javase/technologies/desktop/javawebstart/apps/notepad.jnlp";
        deployJava.createWebStartLaunchButton(url, '1.6.0');
    </script>
        

Detecting the client JRE version using the versionCheck function

There are many good reasons to be able to check if a particular version of the JRE is available on a client machine. For example, you may want to launch a different version of your RIA depending on the client's JRE version, or you may want to redirect the user to a different page etc.

Use the versionCheck function to check if a particular version or range of JRE versions is installed on the client.

Function signature: versionCheck: function(versionPattern)

Parameters:

  • versionPattern: String specifying the version or range of versions to check for, such as such as "1.4", "1.5.0\*" (1.5.x family), and "1.6.0_02+" (any version greater than or equal to 1.6.0_02).

Usage:

  • Creating a different user experience depending on the client's JRE version. In this example, we create a Launch button for the application only if the client's JRE version is greater than or equal to 1.6.0. If not, we redirect them to java.sun.com.
        
    <script src=/old?u=http%3A%2F%2Fblogs.oracle.com%2Fthejavatutorials%2Ftags%2F%26quot%3Bhttp%3A%2Fjava.com%2Fjs%2FdeployJava.js%26quot%3B%26gt%3B%26lt%3B%2Fscript%26gt&y=1999
    <script>
        if (deployJava.versionCheck('1.6.0+')) {            
            var url = "http://java.sun.com/javase/technologies/desktop/javawebstart/apps/notepad.jnlp";
            deployJava.createWebStartLaunchButton(url, '1.6.0');
        } else {
            document.location.href=/old?u=http%3A%2F%2Fblogs.oracle.com%2Fthejavatutorials%2Ftags%2F%26quot%3Bhttp%3A%2Fjava.sun.com%26quot%3B%3B&y=1999
        }
    </script>		
    		

Related Reading


As always, we welcome feedback. Tell us about other things you'd like information about!

-- Sowmya Kannan

Wednesday Apr 01, 2009

Converting Pre-JDK7 File I/O Code

Prior to JDK7, the java.io.File class was the mechanism used for file I/O, but it had several drawbacks:

  • Many methods didn't throw exceptions when they failed, so it was impossible to get a useful error message. For example, if a file delete failed, the program would receive a "delete fail" but wouldn't know if it was because the file didn't exist, the user didn't have permissions, or if there was some other problem.

  • The rename method didn't work consistently across platforms.

  • There was no real support for symbolic links.

  • More support for metadata was desired, such as file permissions, file owner and other security attributes.

  • Accessing file metadata was inefficient.

  • Many of the File methods didn't scale. Requesting a large directory listing over a server could result in a hang. Large directories could also cause memory resource problems, resulting in a denial of service.

Perhaps you have legacy code that uses java.io.File and would like to take advantage of the java.nio.file.Path functionality with minimal impact on your code.

The java.io.File class provides the toPath method that converts an oldstyle File instance to a java.nio.file.Path instance:

Path input = file.toPath();

You can then take advantage of the rich feature set available to the Path class.

For example, say you had a some code that deleted a file:

file.delete();

You can modify this code to use the Path.delete method like this:

Path fp = file.toPath();
fp.delete();

That's all you need to do!

However, if you want to take advantage of the new Path feature set, you can examine the exception to learn why the delete failed:

Path fp = file.toPath();
try {
    fp.delete();
} catch (NoSuchFileException x) {
    System.out.format("%s: no such file or directory%n", fp);
} catch (DirectoryNotEmptyException x) {
    System.out.format("%s not empty%n", fp);
} catch (IOException x) {
    //File permission problems will be caught here.
    System.out.format("%s%n", x);
}

-- Sharon Zakhour

About

thejavatutorials

Search
Recent Posts
Top Tags
Categories
Archives
« May 2011
SunMonTueWedThuFriSat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    
       
Today
Bookmarks
Menu
Feeds