Open Source JavaFX Now!

Steve On Java

Hacking JavaFX and Java with Agility
  • rss
  • Home
  • About
  • Contact
  • SvJugFX
  • Open Source JavaFX Petition

Launching Hyperlinks from JavaFX (including Mobile)

steveonjava | March 4, 2010

Creating hyperlinks in JavaFX should be in the category of things that are trivially easy, but is complicated by various factors, such as deployment mode and Java version. First I will go into detail on all the different permutations of how you can launch links in a browser and under what circumstances each will work. Next I will give you a nice packaged solution that you can use as a library (if you are impatient, just skip to The Easy Way Out now).  Finally, I will show how you can do the same thing for JavaFX Mobile applications.

A Tale of 3 APIs

There are 3 different ways that you can launch hyperlinks in Java/JavaFX. It helps to have an internet connection such as broadband to be able to launch this. Unfortunately, none of them work in all circumstances, so you need to know when to call each. Here is a quick reference table:

AppletStageExtensionWeb Start BasicServiceDesktop.browse
Works in AppletYesYesYes
Works in Web StartNoYesYes
Works in ApplicationNoNoYes
Works on Java 1.5YesYesNo
Can Set TargetYesNoNo
Default Target_self_blank_self

AppletStageExtension

The first option is to use the JavaFX AppletStageExtension. This is only available if you are running as an Applet, but also gives you the most control over how the hyperlink is launched.  In addition to a URL you can also specify a target, which can be any of the standard HTML targets including the following (excerpted from the AppletStageExtension javadocs):

Target ArgumentDescription
"_self"Show in the window and frame that contain the applet.
"_parent"Show in the applet’s parent frame. If the applet’s frame has no parent frame, acts the same as “_self”.
"_top"Show in the top-level frame of the applet’s window. If the applet’s frame is the top-level frame, acts the same as “_self”.
"_blank"Show in a new, unnamed top-level window.
nameShow in the frame or window named name. If a target named name does not already exist, a new top-level window with the specified name is created, and the document is shown there.

Web Start BasicService

The second option is to use the Web Start BasicService.  This works from both JavaFX Applets and Web Start applications, but does not let you specify the HTML target.  It is effectively the same as using the AppletStageExtension with a target of “_blank”.

Here is a small code excerpt showing how you would call the Web Start BasicService from your JavaFX code:

def basicService = ServiceManager.lookup("javax.jnlp.BasicService") as BasicService;
basicService.showDocument(new URL(url));

Desktop.browse

The third option is to use the new Desktop class introduced in Java 1.6.  This works from Applet, Web Start applications, and Standard Execution (within a desktop Frame).  Unfortunately, it did not exist in Java 1.5, so it won’t work from JavaFX without a little hacking.

The quick and dirty hack is to modify your JavaFX distribution to include the rt.jar from Java 1.6 as explained in this earlier post.  The only problem with this is you also have to get all the other developers on your project to do the same (and redo this on every upgrade).

The friendlier approach is to use reflection to check and see if the Desktop class is available, and then invoke the methods dynamically.  There is quite a bit more boilerplate code, but it will allow you to compile with a plain vanilla JavaFX installation, and also handle the odd case where someone is trying to run JavaFX under 1.5.  (Which is unsupported on Windows/Unix, and is now even supported on 32-bit Mac systems with the release of Snow Leopard!).

Since the code is easier to follow without reflection, I will show that first:

Desktop.getDesktop().browse(new URI(url));

And here is the munged version with reflection:

try {
    def desktopClazz = Class.forName("java.awt.Desktop");
    def desktop = desktopClazz.getMethod("getDesktop").invoke(null);
    def browseMethod = desktopClazz.getMethod("browse", [URI.class] as java.lang.Class[]);
    browseMethod.invoke(desktop, new URI(url));
} catch (e) {
    println("Upgrade to Java 6 or later to launch hyperlinks: {url}");
}

The Easy Way Out

When things are easy to do, they will get done right.  To make sure that JavaFX applications do not fall prey to broken and inconsistent linking, I put together a library for JFXtras that takes care of all the plumbing for you.

There is a new JFXtras class called BrowserUtil that has a very simple API:

BrowserUtil.browse(url);

or

BrowserUtil.browse(url, target);

It is that simple…  Conversion of string URLs to URL or URI objects, selection of the correct API based on your deployment mode, and failover modes based on the Java version are all included.

In addition, I created an extended Hyperlink called the XHyperlink.  This behaves identically to the built-in control, with the addition of simple configuration of URL navigation (this is what hyperlinks are designed for, right?)  The usage of the XHyperlink class is as follows:

XHyperlink {
    text: "Oracle's Homepage", url: "http://oracle.com/"}
}

All of this functionality will be included in the JFXtras 0.6 release.  If you need it now, you can build off the head of our repo.  Otherwise we are working on a release, which I will announce on this blog shortly which you can follow.

What about JavaFX mobile?

None of these desktop techniques actually work on a mobile device, so this is not a 100% solution yet.

Fortunately, there is also a solution for JavaFX Mobile if you are willing to delve in to the Java ME APIs.  To do this you first need to get a handle to the MIDlet like this:

def midlet = com.sun.javafx.runtime.adapter.MIDletAdapter.getMidlet();

And then you can call platformRequest to launch a browser on the mobile device:

midlet.platformRequest(url);

Note: This requires use of private APIs, so this may not work in future JavaFX releases.

It is not possible to merge this in with the desktop solution, because the JavaFX Mobile libraries do not exist on the desktop platform (and vice versa), but it is relatively easy to use this technique yourself by copying and pasting the above code sample into a helper function in your application.

 
Categories
JavaFX, JavaFX Mobile, jfxtras
Tags
hyperlinks, JavaFX, JavaFX Mobile, jfxtras
Comments rss
Comments rss
Trackback
Trackback

« Live Video Streaming Guide – Part 1 : Introduction Live Video Streaming Guide – Part 2 : Hardware »

6 Responses to “Launching Hyperlinks from JavaFX (including Mobile)”

  1. William Antônio Siqueira says:
    March 5, 2010 at 11:36 am

    BrowserUtil will be very useful for me! Thanks :)

    in my atual project user only can access pages using Applet mode, now I ha no more preocupation with this :-)

    Reply
  2. JavaFX links of the week, March 8 // JavaFX News, Demos and Insight // FX Experience says:
    March 7, 2010 at 1:20 am

    [...] Stephen Chin did a good blog post discussing the options to open urls in JavaFX in the users web browser. [...]

    Reply
  3. Mike says:
    March 28, 2010 at 10:14 am

    “also handle the odd case where someone is trying to run JavaFX under 1.5. (Which is unsupported on Windows/Unix, but happens to be the only option for the poor lost souls with 32 bit chips who have been abandoned by Apple).”

    Actually, it is a little known fact that Snow Leopard comes with a 32-bit 1.6 runtime! So there are not quite as many poor lost souls anymore :) .

    Reply
    • steveonjava says:
      March 29, 2010 at 1:28 am

      You are absolutely right! I have updated the post to reflect this. Hopefully supporting JavaFX on 1.5 will be a thing of the past soon.

      Reply
  4. Rajmahendra says:
    July 7, 2010 at 1:22 am

    Woow… i just jumped on this article. very informative :)

    Can we display a html page in a JavaFX ? any control for Htmlviewer ?

    Reply
    • steveonjava says:
      July 8, 2010 at 9:08 am

      Unfortunately there is no HTML control in JavaFX at this time. This is very high on my wanted list as well, so I hope Oracle adds it in to the next release.

      Reply

Leave a Reply

Click here to cancel reply.

Publications


Upcoming Talks



Categories

  • Agile (1)
  • Announcements (15)
  • contest (3)
  • Events (17)
  • JavaFX (37)
  • JavaFX Mobile (1)
  • jfxtras (13)
  • Liferay (2)
  • presentation (7)
  • pro javafx (2)
  • SvJugFx (8)
  • Uncategorized (21)
  • Video (4)
  • widgetfx (9)

Affiliations

Awards

2009 JavaOne Rock Star!

rss Comments rss valid xhtml 1.1 design by jide powered by Wordpress get firefox