|
Ed has updated the Roadmap for OpenMQ with the information related to OpenMQ 4.4, targeted for GlassFish v3. Key features include:
• JMS Bridge -- Connect to other Open MQ clusters, or other JMS products
Full details at OpenMQ 4.4 Feature Page. |
Maia lets you reference JSF 2.0 managed beans directly from Java code and provides completion, usage search and core refactorings for them.

The first Android-powered phone will launch in Japan on July 10th. New Japanese customers will have immediate access to free applications in the Android Market, with paid apps following sometime later. That’s according to a notice sent from Google’s Eric Chu to Android app developers late Wednesday. Bulgaria and Romania are on the target list after Japan, first with phones and free apps and then with paid apps.
In other news, Google says that the over the air roll-out of Android 1.5 (Cupcake) is “nearly complete”. And of course, all new phones come with 1.5 already installed. That means that Android developers can take advantage of 1.5 features such as Home screen app widgets without worrying about trying to support older versions.
(And in other, other news, I just put the finishing touches on an update of Hello, Android that features a new appendix on how to write app widgets in Cupcake. The update will be free to all owners of the PDF, mobi, or epub versions, and cheap for owners of the dead tree version.)
[ Follow me on Twitter at: @eburnette ]
Continue reading: Full text of the notice from Eric Chu >
|
I've posted the May 09 GlassFish Adoption Report. Some growth from April 09, but not back to the March 09 peak; probably some seasonal drop, possibly some impact from the Oracle announcement. The full report includes the usual download data for run-time and tools bundles, a comparison with JBoss downloads, GeoMap, Registration and Update Center. |
I expect to post the June report next week.
DialPlotDemo2.java (alas DialPlotDemo1.java produced no output at all) and ran it on both Harmony and IcedTea (a derivative of OpenJDK). These are the screen shots (the one on the left is from Harmony, the one on the right is from IcedTea):
java.awt.geom.IllegalPathStateException: First segment should be SEG_MOVETO type
at java.awt.geom.GeneralPath.checkBuf(GeneralPath.java:209)
at java.awt.geom.GeneralPath.lineTo(GeneralPath.java:236)
at java.awt.BasicStroke$BufferedPath.createGeneralPath(BasicStroke.java:1791)
at java.awt.BasicStroke.createStrokedShape(BasicStroke.java:269)
at org.apache.harmony.awt.gl.CommonGraphics2D.draw(CommonGraphics2D.java:310)
at org.jfree.chart.plot.dial.StandardDialRange.draw(StandardDialRange.java:339)
at org.jfree.chart.plot.dial.DialPlot.draw(DialPlot.java:565)
at org.jfree.chart.JFreeChart.draw(JFreeChart.java:1235)
at org.jfree.chart.ChartPanel.paintComponent(ChartPanel.java:1669)
at javax.swing.JComponent.paint(JComponent.java:1000)
at javax.swing.JComponent.paintChildren(JComponent.java:979)
at javax.swing.JComponent.paint(JComponent.java:1002)
at javax.swing.JComponent.paintDoubleBuffered(JComponent.java:1438)
at javax.swing.JComponent.paint(JComponent.java:998)
at javax.swing.JComponent.paintChildren(JComponent.java:979)
at javax.swing.JComponent.paint(JComponent.java:1002)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:220)
at javax.swing.JComponent.paintChildren(JComponent.java:979)
at javax.swing.JComponent.paint(JComponent.java:1002)
at java.awt.Container.paintComponentsImpl(Container.java:1007)
at java.awt.Container.paint(Container.java:936)
at java.awt.Component.processPaintEvent(Component.java:3676)
at java.awt.Component.dispatchEvent(Component.java:3502)
at java.awt.EventQueueCore.dispatchEventImpl(EventQueueCore.java:149)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:144)
at java.awt.EventDispatchThread.runModalLoop(EventDispatchThread.java:74)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:48)
Now, this is code completion in the BootStrap.groovy for the above domain class in NetBeans IDE 6.5:
And now, in NetBeans IDE 6.7, here's code completion in the same BootStrap.groovy:
Not bad, right? Get started with Grails in NetBeans IDE here:
http://www.netbeans.org/kb/docs/web/grails-quickstart.html
...or do so here on the Grails site:
http://www.grails.org/NetBeans+Integration
In other news. Now here's an interesting movie about Michael Jackson. Can't find the second part, though.
First of all, I present... a financial application, which is created in Brazil, by Paulo Canedo, and a team of developers around him, who work for the Tribunal de Contas do Estado do Tocantins, a state in Brazil, where all the financial management related to the state is done on the NetBeans Platform. The application was started in 2007 and, in particular, Paulo's team likes the wizard framework of the NetBeans Platform, as well as the update center. Combined, these features enable the application to be responsible for all finances in the city, i.e., purchases and payments. The application processes data via XML and then transforms and stores in a Derby database. Furthermore, the application is used to analyze the data thus obtained and stored.
And here is a sneak preview screenshot (more in an upcoming article):
Next, an application by Ingmar Hendriks, and others, who are students at the Hogeschool van Amsterdam. Not very long ago, they completed a NetBeans Platform Certified Training. (My blog entry "Amsterdam on the NetBeans Platform" tells you all about it.) Ingmar's graduation project was to create a sensor monitoring application. He had to make two programs, a server and a client. Because he didn't have a whole laboratory full of sensors at school, he had to simulate the sensors by generating random values within a certain parameter. The generation of these random values had to be done on the server, with a time interval of a few hundred milliseconds and the server needed to store these values. This itself sounds very doable until you realize that over 400 sensors had to be simulated, each with an interval of a few hundred milliseconds and that these had to be stored into memory and not on the hard drive.
In order to achieve this, the memory had to be controlled, which is not possible with Java because you have no control over memory management... so C++ had to be used. The client, however, was a different story. It only needed to access the values of a sensor and show them in a chart. If a value on the server exceeded its preset safety parameter, it needed to show a warning or error in the client. Here's a sneak preview screenshot of the application that resulted from all of this:
And, finally, let's take a look at Central Washington University's programming tools for the blind that, hopefully, will make them more accessible. These tools are very complicated, as they involve custom compilers, debuggers, and sound architectures. These architectures then need to be built into standard IDEs.
Here is a screen capture of the environment as a whole, annotated with details of what was added at Central Washington University. Notice that, while the screen capture looks just like NetBeans IDE, what has been added is a new programming language (Hop). In addition, the debugger is "omniscient", which means that you can execute code forward and backward. For example, in most debuggers, you can click "Continue" (the green button) and step the code to the next breakpoint. In this debugger, you can also "Rewind" (the blue button) to the previous breakpoint. Similarly, most IDEs let you step over a line of code. This one also lets you step back:
What do these applications gain from being based on the NetBeans Platform? Modularity (i.e., you can create plugins for these applications), while being based on Swing (the standard UI toolkit). That's a combination that no other framework provides natively. Typically, a developer using the NetBeans Platform begins by appreciating the NetBeans Platform's Swing extensions, such as the window system and explorer views. Later, the modularity becomes increasingly useful, both from the side of development (i.e., encapsulate code on a level higher than packages, which makes it easier to create work areas for distributed development teams) and from the side of deployment (i.e., the end user is able to extend the application, by means of plugins, without needing to download/understand the entire codebase).
But, of course, this is simply the tip of the iceberg. To find out about several other NetBeans Platform applications, click here and browse through the whole showcase. Several known applications on the NetBeans Platform cannot be advertized, i.e., must remain secret, since they're the basis of, for example, military or financial systems whose underlying technologies cannot be made public. In many ways, that's a pity, because the full length and breadth of NetBeans Platform usage will probably never be known.
Want to advertize your application on the NetBeans Platform? For free? Drop me an e-mail at geertjan DOT wielenga AT sun DOT com and it will be given all the attention you desire (plus more).
IntelliJ IDEA 9M1 supports debugging of JavaScript code in Mozilla Firefox. Just create a JavaScript Debug configuration, select Firefox from the Browser list and click OK:
IntelliJ IDEA automatically installs plugin for Mozilla Firefox and executes the configuration.
Note that you need to clear Make option under Before launch group before starting debugger to work around a bug that will be fixed in next Maia EAP.
Galileo? Me too :-)
I've just released updates for two of my plugins: Bytecode Outline and Data Hierarchy.
Highlights:
Here is a screenshot which may explain Data Hierarchy better then words (check the "UnreadFields" class node). You see here the data hierarchy of the AnalysisContext class:
Maia supports preview of icons you are using in Java code directly from the editor. For each of the icon definitions (javax.swing.Icon), Maia tries to locate a file from which it is loaded and then shows a preview in the gutter bar. You can click it to open the image for editing, of course.![]()
Not a big fan of Java? Well, get over it, because that’s the primary and recommended way to write applications for Android devices. It’s portable and… what’s that? Android’s Dalvik Java VM not fast enough for you? Granted, it’s an interpreted engine and as of version 1.5 there’s no Just-In-Time compiler. But Dan promises… oh, can’t wait for the JIT to come out? Ok, ok, we’ll let you program in C if you’re really sure.
Introducing the Android Native Development Kit (NDK). With it, you can implement *parts* of your application using native-code languages such as C and C++. You’re familiar with the Java Native Interface (JNI), right? JNI lets you load a shared library and call C code from within Java. The NDK lets you compile and build those libraries for the ARM CPU chip used in all *current* Android devices.
The NDK provides:
Users downloading your program from the Market will not be able to tell whether or not you used native code. In fact, some apps already on the Market use it. However, native code is not for everyone. Google engineer David Turner writes:
Keep in mind that using the NDK will not be relevant for all Android applications. As a developer, you will need to balance its benefits against its drawbacks, which are numerous! Your application will be more complicated, have reduced compatibility, have no access to framework APIs, and be harder to debug. That said, some applications that have self-contained, CPU-intensive operations that don’t allocate much memory may still benefit from increased performance and the ability to reuse existing code. Some examples are signal processing, intensive physics simulations, and some kinds of data processing.
You have been warned. Stay away from the NDK unless you really need it. Try optimizing your Java code first. Try profiling. Acupuncture, cold compresses, anything but… what did you say? “Shut the…,” hey, there’s no need to be rude. Have at it.
We’re happy to announce the first Milestone release of upcoming IntelliJ IDEA 9, nicknamed Maia.
This release delivers a fresh preview of features and improvements we’ve implemented so far for IntelliJ IDEA 9:
You’re welcome to download IntelliJ IDEA 9M1, traditionally available for Windows, Mac OS X and Unix systems.
With Maia it’s easy to target a specific version of Flash player for your Flex/AIR applications. All you need is to specify it on the Flex Compiler Settings tab of a Flex module or facet:
With Flex SDK 3.2.0 or later you can target players of either version 9 or 10. Remember that version of playerglobal.swc library attached to module or facet SDK must match your target selection. Maia takes care of it by automatically changing SDK to an one that contains required library. If there is no such SDK, it will be created for you. By the way, a default Flex SDK name contains major version of target player:
AIR SDK name does not contain target player information because it does not include playerglobal.swc library, and airglobal.swc library does not vary from version.
Note: Changing a target player version for Flex module or facet may lead to changes it its SDK configuration and vice versa — if you change module or facet Flex SDK, it may affect the target player version settings.
In IntelliJ IDEA 8.x there is no special configuration setting for target player version, so to target a custom player version you need to change playerglobal.swc library attached to the used SDK manually (either <Flex SDK>/frameworks/libs/player/9/playerglobal.swc or <Flex SDK>/frameworks/libs/player/10/playerglobal.swc) and also to write Additional compiler option like -target-player=10
Maia brings you an improved Show Usages popup (Ctrl+Alt+F7):

Maia includes support for running FlexUnit 4 tests. All you need is to a add dependency to FlexUnit4.swc library and your FlexUnit4-style tests will be recognized and run. FlexUnit4 runner supports legacy tests (FlexUnit 0.9 and Flunit), so you don’t have to worry about existing code. Maia also includes some nifty testing support features:

Test with pleasure!
Besides death and taxes, there is one other certainty in the life of a software developer: slipping schedules. Every year, though, Eclipse continues to defy that expectation by releasing a major new version in late June. Today, the Eclipse Galileo release train arrived exactly on time, for the 6th year in a row.

Galileo is a synchronized release of 33 separate projects all under the umbrella of the Eclipse Foundation. Over 380 committers from 44 different organizations participated to make this release possible.
Many of the projects in Galileo are tools for developers, for example the Java Development Toolkit, C Development Toolkit, Memory Analyzer, Web Tools, Subversion, and of course the Eclipse Platform (version 3.5). Others are more oriented towards end users such as the Business and Reporting Tools.
For 2009, a new category of projects has coalesced under the name “Eclipse Runtime Technology”. This includes Equinox (Eclipse’s implementation of the OSGi standard), the Eclipse Communication Framework, Rich Ajax Platform, Riena (modular business application platform), Swordfish (SOA framework), and EclipseLink (persistence services).
Another major focus of the 2009 release is modeling tools. New innovations in Galileo include Xtext (for creation of domain specific languages) and Connected Data Objects (distributed shared models with transactions).
“The release train continues to be a great achievement of the Eclipse community,” explained Mike Milinkovich, Executive Director of the Eclipse Foundation. “Galileo demonstrates that large distributed software development can be done on a predictable schedule. This predictability makes it possible for our user and adopter community to quickly adopt new releases from Eclipse.”
Eclipse Galileo with Eclipse Platform 3.5 is available immediately from the eclipse.org download site. This year, downloads should fly thanks to a partnership with Amazon Web Services. Package sizes range from 79MB to 367MB depending on what components you need.
Related articles:

The work done by the Cometd team, the java implementation of the Bayeux Protocol, can now run on top of the Atmosphere Framework. Under the hood, the proper Comet API is as usual detected!
The default implementation uses Jetty 7 Continuation under the hood...but now if you run it on top of the Atmosphere Framework, it will auto detect the container's native Comet API (or use the Servlet 3.0 async if available)! So you can now run the same application using GlassFish, Tomcat 5/6, Jetty 6, WebLogic, JBossWeb and event Tomcat 4 (happy 10 years!)
So for the first time (why? read Matthias here), we have finally a PORTABLE Bayeux protocol implementation! See the official announcement here (and how to try it).
For any questions, go to our main site and use our Nabble forum (no subscription needed) or follow us on Twitter and tweet your questions there!
technorati: atmosphere framework bayeux protocol comet
IntelliJ IDEA 8.1.3 update is available. Download the fresh build that includes:
For more information about fixes and improvements see Release Notes.
The competition is heating up in the market for smartphones and other mobile devices. Literally. As competitors try to leap-frog each other in performance we’re seeing a repeat of the desktop computer’s Megahertz arms race, only this time the palm of your hand. You might want to put on some oven mitts.
The story so far:
Continue reading: Megahertz madness >
I'll be spending next week in Zurich at Jazoon'09.
They've got a great lineup of technical sessions
to pump your head full of all the latest everything. The lineup of speakers is pretty impressive.
PS. Several folks have asked why I disappeared from JavaOne so quickly after my Toy Show keynote: my youngest daughter's school was holding a talent show at noon, and I had to be there. Work is not at the top of life's priority list :-)
The latest update to Firefox addresses 67 bugs and enhancements, according to Mozilla. 23 bugs were marked as “critical” or higher. (Coincidentally this was the same number addressed by the 3.0.9 update in April.)
Nine potential security vulnerabilities were patched including 1 marked as “high” and 4 “critical”:
The new release addresses a problem that apparently affected a lot of people (bug 464486). If Firefox crashed or your machine died at just the right time, your bookmarks and history database could have been lost or corrupted. The earliest report I could find of the problem was on September 7th, 2008.
In the end, a 2 line fix to turn on full synchronous operation of the SQLite database used to store bookmarks was all that was needed. Although the fix was known in January, it wasn’t backported to Firefox 3.0 until recently because of concerns about how it might affect performance, especially on Linux. Further study showed, however, that performance was only slightly degraded on newer versions of Linux, and data integrity was deemed to be more important.
Mozilla has been updating Firefox 3 approximately once a month since its release in June of last year. Here’s a list of all the updates so far:
Finally, Atmosphere 0.2 released with support for annotations for REST application, improved support for Tomcat/Jetty/GlassFish, native support for JBossWeb 2.1.x, and EJB/External components broadcast lookup available.
technorati: atmosphere framework jersey comet
Today we’ve released an updated version of the Python plugin, with support for both IntelliJ IDEA 8 and “Maia” EAP. New features of the plugin include:
You can find detailed release notes and screenshots of the new plugin on our Confluence space.
In that part, I describe a simple asynchronous REST application using behaviors.js, prototype.js and the Atmosphere Framework. As usual, you can deploy the app anywhere! If you interested to look for a complex Atmosphere application, take a look at the Twitter revisited one.
To understand the basic of Atmosphere, I recommend you take a quick look at part I and II. This time I will explains a simple application, which uses long polling for suspending connection. First, let's see what the war file structure looks like:
./index.html
./WEB-INF
./WEB-INF/context.xml
./WEB-INF/classes
./WEB-INF/classes/org
./WEB-INF/classes/org/atmosphere
./WEB-INF/classes/org/atmosphere/samples
./WEB-INF/classes/org/atmosphere/samples/rest
./WEB-INF/classes/org/atmosphere/samples/rest/counter
./WEB-INF/classes/org/atmosphere/samples/rest/counter/RestLongPolling.class
./WEB-INF/lib
./WEB-INF/lib/jersey-core-1.1.1-ea-SNAPSHOT.jar
./WEB-INF/lib/atmosphere-core-0.2.jar
./WEB-INF/lib/asm-3.1.jar
./WEB-INF/lib/atmosphere-portable-runtime-0.2.jar
./WEB-INF/lib/jersey-server-1.1.1-ea-SNAPSHOT.jar
./WEB-INF/lib/jsr311-api-1.1.jar
./WEB-INF/web.xml
./javascripts
./javascripts/prototype.js
./javascripts/counter.js
./javascripts/behaviour.js
./META-INF
./META-INF/context.xml
./META-INF/atmosphere.xml
./stylesheets
./stylesheets/styles-site.cssThe two important files are the RestLongPolling, which contains the server side code, and the counter.js, which contains the client side code. The client simply looks like:
1 var counter = {
2 'poll' : function() {
3 new Ajax.Request('dispatch/counter', {
4 method : 'GET',
5 onSuccess : counter.update
6 });
7 },
8 'increment' : function() {
9 var count = $('count').innerHTML * 1;
10 new Ajax.Request('dispatch/counter/' + count, {
11 method : 'POST'
12 });
13 },
14 'update' : function() {
15 var count = $('count').innerHTML * 1;
16 $('count').innerHTML = count + 1;
17 counter.poll();
18 }
19 }
20
21 var rules = {
22 '#increment': function(element) {
23 element.onclick = function() {
24 counter.increment();
25 };
26 }
27 };
28
29 Behaviour.register(rules);
30 Behaviour.addLoadEvent(counter.poll);On the screen, it looks like:
As soon as you click, the counter send a request, appending the count value to the URL. Every browser connected will be updated as soon a click event happens. The idea here is to really show something simple. Now, on the server side, we only have (I'm not kidding!):
1 package org.atmosphere.samples.rest.counter;
2
3 import com.sun.jersey.spi.resource.Singleton;
4 import java.util.concurrent.atomic.AtomicInteger;
5 import javax.ws.rs.GET;
6 import javax.ws.rs.POST;
7 import javax.ws.rs.Path;
8 import javax.ws.rs.PathParam;
9 import org.atmosphere.core.annotation.ResumeOnBroadcast;
10 import org.atmosphere.core.annotation.Suspend;
11
12 @Path("{counter}")
13 @Singleton
14 public class RestLongPolling{
15 private final AtomicInteger counter = new AtomicInteger();
16
17 @GET
18 @Suspend
19 public String suspend(){
20 return "<!-- Atmosphere is your future-->";
21 }
22
23 @POST
24 @Path("{counter}")
25 @ResumeOnBroadcast
26 public String increment(@PathParam("counter") String count){
27 counter.incrementAndGet();
28 return counter.toString();
29 }
30 }So, when the Browser load the page, the counter.poll will invoke, on the server side the suspend() method. Since that method is annotated with the @Suspend annotation, the connection will be suspended after the method execution, waiting for event. You can see the Browser icon spinning in that demo as the GET has not yet returned. As soon as a click happens (line 8), the POST will invoke the increment(..) (line 26) method, and since the method is annotated with the @ResumeOnBroadcast, then the returned value will be broadcasted to all suspended connections, then written on the wire, and then the connection will be resumed. On the Browser side, the spinning will stop for a few milliseconds, as the Browser will re-issue a GET, which will again be suspended. Note that for that simple demo, I'm not updating the client side using the returned value of the increment(..) method to keep it extremely simple.
Now technically this application use the Atmosphere module called core, which build on top of the Comet Portable Runtime (CPR), hence allowing the application to be deployed anywhere. The CPR always auto detect the container is running on top of, like:
First with Glassfish v3:
10-Jun-2009 8:02:05 PM org.atmosphere.cpr.AtmosphereServlet loadAtmosphereDotXml
INFO: Sucessfully loaded org.atmosphere.handler.ReflectorServletProcessor@e1ca74 mapped to context-path /dispatch
10-Jun-2009 8:02:05 PM org.atmosphere.cpr.BroadcasterConfig
INFO: DefaultBroadcaster configured using a Thread Pool of size: 2
10-Jun-2009 8:02:05 PM org.atmosphere.cpr.AtmosphereServlet autoDetectContainer
INFO: Atmosphere Framework running under container javax.servlet version 3.0
...and then Tomcat 6
INFO: DefaultBroadcaster configured using a Thread Pool of size: 2
10-Jun-2009 8:03:46 PM org.atmosphere.cpr.AtmosphereServlet autoDetectContainer
INFO: Forcing the use of the container's native Comet API implementation instead of Servlet 3.0
10-Jun-2009 8:03:46 PM org.atmosphere.cpr.AtmosphereServlet autoDetectContainer
INFO: Atmosphere Framework running under container Tomcat version 6.0.xThe two log above are showing that if the framework detect Servlet 3.0 Async Support implementation, it will use it. If not, then it will use the native Comet implementation.
Finally, two descriptors are needed to make the application works. The first one, the atmosphere.xml, just tells Atmosphere to use Jersey's Servlet to process request. Under the hood, all annotation processing and REST support comes for free from Jersey:
<atmosphere-handlers>
<atmosphere-handler context-root="/dispatch" class-name="org.atmosphere.handler.ReflectorServletProcessor">
<property name="servletClass" value="com.sun.jersey.spi.container.servlet.ServletContainer"/>
</atmosphere-handler>
</atmosphere-handlers>Next, the web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:j2ee="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="3.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_3_0.xsd">
<description>Atmosphere DeadSimple</description>
<display-name>Atmosphere DeadSimple</display-name>
<servlet>
<description>AtmosphereServlet</description>
<servlet-name>AtmosphereServlet</servlet-name>
<servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
<async-supported>true</async-supported>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>org.atmosphere.samples.rest.counter</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>org.atmosphere.core.AtmosphereFilter</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AtmosphereServlet</servlet-name>
<url-pattern>/dispatch/*</url-pattern>
</servlet-mapping>
</web-app>The only important line above is the init-param that tells Jersey were to lookup our resources, e.g. under org.atmosphere.samples.rest.counter. That's it. You can download the sample from here (and many more here).
For any questions, go to our main site and use our Nabble forum (no subscription needed) or follow us on Twitter and tweet your questions there!
technorati: atmosphere framework jersey comet
Groovy language support becomes a little bit better in Maia with the support for named parameters completion. Maia is now capable of displaying all named parameters ever used in method bodies.

At today’s World Wide Developer’s Conference keynote, Apple announce a new, faster version of the iPhone: the iPhone 3GS. The S stands for Speed.
The new device is 2.1x faster to launch Messages, 2.9x faster to launch a big web page. It includes OpenGL|ES 2.0, and has 7.2MBps HSDPA built-in.
Besides the faster processor, the big draw for the 3GS is its new 3.0 megapixel camera. It features:
The new 3GS also features voice control. You hold down the home button for a few seconds in any application. Commands that you can say start floating around on the screen. Say one of them and it happens. Examples: “Dial scott forestall”, “play the killers”, “play more songs like this”, “what’s playing now”.
Other features:
Price and availability:
The iPhone 3GS will be available in 7 countries on June 19th for $199 (16GB) and $299 (32GB). Both come in black and white. The old 3G will continue to be available, but at a lower price-point: $99. All prices are for AT&T new and qualifying customers and may vary on other carriers.
This was another amazing JavaOne. It was also the weirdest: between the Oracle situation, the global meltdown, and the financial situation, it was very different. Early on, we were really concerned (==nearly paniced) that no one would show up. Almost every company that usually sends a crowd of people to JavaOne had travel restrictions that meant that few could attend. From what we had seen from other conferences, we feared the worst. And yet, attendance ended up being about 15,000. Very respectable!
The press, of course, was weird this year: we did few interviews, mostly because there was only one topic they wanted to ask about, and there was nothing we could say.
My favorite part of JavaOne this year was the standing ovation that Scott got on Monday. It was a remarkably emotional moment for everyone. To all of you who contributed to that thundering applause: Thanks!
Our lineup of new technologies was great: JDK7 is looking wonderful; JavaFX reached another release milestone and is maturing nicely, along with it's tools; glassfish V3 is becoming totally wonderful; NetBeans 6.7+kenai is a killer combination; and the store is on it's way to being an amazing addition.
The fun part, for me, is the Toy Show. It's not about strategic initiatives, business issues, corporate relations, or new releases. It's all about jaw-dropping surprise. Everything from the Mifos (MIcroFinance, Open Source) project: bringing millions out of poverty. To Manuel Tijerino's jukebox architected to give indie musicians broad exposure and a source of revenue independent of the studios. To teaching kids through BlueJ and robotics competitions. And saving lives by doing computationally intensive image matching in an EE server with a JavaFX front end to analyse cancer biopsies. And the total victory of technology and style over common sense that is Neil Young's LincVolt. And a whole lot more.
It’s that time again: the annual Apple World Wide Developer’s Conference and its highly anticipated keynote address. Phil Schiller ran the show this year, and while he’s no Steve Jobs most observers agree that he did a pretty good job. Highlights include a revamping of the MacBook Pro line, the introduction this fall of Snow Leopard, and the announcement of a new, faster iPhone called the iPhone 3GS.
[Now that the keynote is over I've rearranged my updates in chronological order. Enjoy! -Ed]
9:21am: Welcome to live coverage of the 2009 Apple World Wide Developer’s Conference (WWDC). I will be your host this morning.
9:25am: WWDC 2009 is being held in Moscone West, the same location as the Google I/O conference.
9:30am: WWDC, of course, is a bit more closely watched.
9:33am: Judging by the posters it looks like the Mac will get some love this time around, in the form of Snow Leopard, 64-bit support, Grand Central, and OpenCL.
9:50am: Ever notice that WiFi becomes useless in a crowded room?
9:57am: Gizmodo live site bites the dust - Ars and Engadget still up.
10:00am: It’s showtime!
Continue reading: Phil Schiller takes the stage >
To my OEM readers such as RIM, SonyEricsson, Nokia, Motorola, and etc. As I progress towards the last seps in the AndCooper Android Build Tool 0.1 release I have moved my blogging to a new platform and site. The new site is:
http://mobilebytes.wordpress.com
on the wordpress blog/CMS platform. since I am able to post sample code easier with wordpress and etc I would like to see my OEM blog readers at my new site of Android Code and Development blogging. Hopefully, I will see yoru readership there. Hopefully, at some point PLanetAndorid changes their blogroll links and feed crawing to include and craw my new Android development Blog.
For those who didn't attended Bill's presentation Defective Java™ Code: Mistakes That Matter on Java One 2009
, here is the link to the FindBugs Eclipse 3.5 RC3 analysis. This link loads a FindBugs instance with recorded analysis results, and you can try out the new "cloud" features built in in the recent FindBugs development release.As requested by Wayne a day before, I've created a new bug for Eclipse 3.5 RC3 analysis results. Feel free to comment on it or to pick and post your own favorite bugs into the Eclipse bugzilla too.
P.S.
FindBugs is open source, and it can only evolve if you participate too. Please do not hesitate to report FindBugs
[update]
It seems that the original FindBugs jnlp link does not work on older Windows Sun VM. Until it's fixed, you ca try this one: http://andrei.gmxhome.de/findbugs/eclipse.jnlp. Of course I've created a bug for it ;-)
High Five from JavaOne, or 5 chances to listen to an ugly Quebecois accent.
This year I'm invading JavaOne again, and 5 times...4 times on Tuesday (nice scheduling tool...NOTD!). Which one I would pick? Well the new Atmosphere baby is certainly the one I like the most! This is the last JavaOne as we know it, so don't miss any party :-) See you there :-)
Google unveiled a new online communications tool Thursday at its annual Google I/O Developer’s Conference. Called “Google Wave“, the new system sets its sights pretty high: replacing email, instant messaging, wikis, blogs, and static documents. If anybody can do it, it just might be Lars Rasmussen, creator of the wildly popular Google Maps application.
“We tried to imagine what email might look like if it were invented today,” said Lars during a keynote address to a packed house of developers. And what an imagination it is. After a masterful series of demonstrations, Lars and his team received a standing ovation that even Steve Jobs would be envious of.
Observing this from the front row I could tell he was moved and energized by the reaction. Heck, *I* was moved and energized by it, as you could probably tell if you followed my twitter feed.
So what is Google Wave?
Google Wave is different things to different people. To ordinary users, it’s a souped-up version of GMail that includes tons of new features like an eerily accurate spell checker, the ability to edit messages after sending them, carry on conversations in real-time seeing everything the other person types as soon as they type it, adding comments to the middle of a message, adding people at any point in a conversation and letting them see the full context and history of who said what, drag-n-drop attachments, and more.
To Ajax web developers Google Wave is a way to embed interactive social content like threaded comments into their web site. To server-side developers it’s a way to manipulate and mash up content on the server from various sources. To gadget developers it’s a new platform for creating interactive extensions. To the corporate IT department, it’s a way to get the latest communications technology without giving up control of data on internal servers and networks. And to big media/social companies like Yahoo! and Microsoft it’s an opportunity to finally tie together the mesh of formerly incompatible mail, messaging, document, and account systems through Federation.
On the shuttle ride to the airport I sat next to a guy from IBM who said they’ve had all this for 10 years in the form of Lotus Notes and Domino. There are similarities, but differences too. First, Wave will be open sourced, with an open protocol that anyone can use and implement without charge. Second, the clients we saw during the demo were web based.
Using the newfound power of HTML5, the Wave client can run inside any modern browser (even IE, eventually). Maybe there’s something to this interweb thing after all.
| MonsterServlet.java |
package monster;And the persistence.xml to put in the WEB-INF/classes/META-INF directory of this Web Application
import java.io.*;
import java.util.*;
import javax.ejb.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;
import javax.naming.*;
import javax.persistence.*;
import javax.servlet.*;
import javax.validation.*;
import javax.validation.constraints.*;
/**
* @author: Not Me!!!
**/
@Stateless @Entity @WebServlet(urlPatterns = "/monster")
@Table(name = "MONSTERTABLE")
@NamedQueries({@NamedQuery(name = "MonsterEJB.findAll", query = "SELECT c FROM MonsterServlet c")})
@PersistenceContext(name = "monsterContext", unitName = "MonsterWebAppPU")
public class MonsterServlet extends HttpServlet {
@Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private int monsterId;
@Max(2) @NotNull private String name;
@Transient @EJB MonsterServlet monsterEJB;
/*@Transient @PersistenceUnit(unitName = "MonsterWebAppPU") //does not work see EclipeLink bug
private EntityManagerFactory emf;*/ //https://bugs.eclipse.org/bugs/show_bug.cgi?id=277550
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().println("In Servlet calling the EJB side " + monsterEJB.EJBBusinessMethod("" + this));
}
public String EJBBusinessMethod(String name) {
try {
InitialContext ic = new InitialContext();
EntityManager em = (EntityManager) ic.lookup("java:comp/env/monsterContext");
this.name = name;
em.persist(this);
Query allMonsterQuery = em.createNamedQuery("MonsterEJB.findAll");
List allMonsters = allMonsterQuery.getResultList();
String error = validateTheMonsterJPA((MonsterServlet) allMonsters.get(0));
return "BusinessMethod from EJB" + allMonsters.toString() + error;
} catch (NamingException ex) {
return "Error in EJBBusinessMethod "+ex.getMessage();
}
}
private String validateTheMonsterJPA(MonsterServlet m) {
String error=" ";
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
Set<ConstraintViolation<MonsterServlet>> s = validator.validate(m);
for (ConstraintViolation<MonsterServlet> c : s) {
error = error+ " Contraint Violation: " + c.getMessage());
}
return error;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="MonsterWebAppPU" transaction-type="JTA">
<jta-data-source>jdbc/__default</jta-data-source>
<properties>
<property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
</properties>
</persistence-unit>
</persistence>
This afternoon at Google I/O 2009 Dave Sparks gave the most technical presentation of the conference so far when he delved into the details of the Android Media Framework. Here are my notes from the talk.
Design Goals of the Media Framework include:
The typical stack for a media function call is pretty complex:
DVM proxy > JNI > Native proxy (C++) > Binder Proxy > Binder Native > Native Implementation
Thankfully you don’t need to make many calls to the framework. Using a native proxy will allow developers to call media from native games in the future.
Internally the media framework has its own handlers for .ogg and .mid files, and sends anything else to the OpenCORE library. That’s why the .ogg format is preferred for lightweight sound effects.
Android video codecs include:
Audio codecs include:
Typical streams look like this:
New features for Cupcake V1.5 include:
AudioTrack and AudioRecord are interesting to low level audio developers:
The JET Interactive MIDI Engine is new for Cupcake:
Dave spent some time in the talk going over common problems with the Media framework that he has seen users encounter. For example, one common problem is that volume control behavior is inconsistent.
In an application that plays sounds periodically the volume behavior is not consistent.
The solution is to set the default stream type in your onCreate() method:
setVolumeControlStream(AudioManager.STREAM_MUSIC);
Unable to play file from a resource?
Out of MediaPlayers?
CPU Overloaded?
During the Q&A Dan revealed that OpenGL 2.0 support was coming in the Eclair version (currently at HEAD in source control). The 2d framework will be running in a 3d context. He also said this would allow the support of video as a texture.
Jeff Sharkey, recently hired by Google, presented an interesting session this afternoon called “Coding for Life - Battery Life, That Is”. In it, he offered several practical tips for Android developers to prolong the life of their users’ batteries.
All apps need to work together to be good citizens and conserve the limited battery power available on today’s mobile devices, according to Jeff. Here are some typical battery capacities:
Most users report under a day’s worth of battery life on the HTC Dream (T-Mobile G1), so where does all the power go?
Waking up in the background when the phone would otherwise be sleeping costs a lot. For example, if an app wakes up every 10 minutes to update, and takes about 8 seconds to update, that’s 350mA. Cost during a given hour: 5mAh resting, plus 6 updates an hour is another 4.6mAh updating. So basically that app cut your battery life in half. On top of that, just one app waking up can trigger a cascade of other apps that try to pile on and do their updates as well.
Bulk data transfer costs a lot. For example a 6MB song costs up to 45mAh on EDGE because it takes 9.1 minutes * 300mA. Moving between cells/networks is another cost because of radio ramp up and BroadcastIntents. Parsing textual data, and doing regex without JIT also contribute.
So what can developers do to improve the situation?
The first way is to be smarter about networking. Check network connection, wait for 3G or WiFi. Check connectivity.getBackgroundDataSetting() (new in Cupcake). Use an efficient data format and parser (XML > JSON > Protobuf; tree parser > steam parser). And use GZip for text data whenever possible. Android GZip libs use native code.
The next way is to look at foreground apps. Wakelocks are costly if forgotten. Pick the lowest level possible, and use specific timeouts to work around unforseen bugs. Use android:keepScreenOn to ensure correctness. Recycle Java objects, especially complex objects. - Use coarse network location - it’s much cheaper. Avoid floating point math, and use a slower accelerometer rate.
Next, consider your background applications. Services should be short-lived; these are not daemons. Each process costs 2MB and risks being killed/restarted as foreground apps need memory. Otherwise keep memory usage low so you’re not the first target. Trigger wake-up through AlarmManager or with <receiver> manifest elements, and call stopSelf() when finished.
Android 1.5 (Cupcake) introduced inexact repeating alarms (the setInexactRepeating() method) which lets the system batch up your update with others to minimize the number of wakeups the system has to do in a given time period.
in the Q&A session, Jeff shared some other insights. One that stuck out for me was that changing the screen brightness didn’t affect battery life all that much. At the lowest brightness, the LCD backlight drew about 70mA, but it only drew about 110mA at its highest brightness. With factory defaults it takes about 90mA.
Thanks, as always, for your feedback. It helps us improve the tutorial!
-- Sharon Zakhour
Small entry for those who aren't following us on twitter.com/project_grizzly. Project Grizzly 2.0.0-M2 is now officially available.
The official announcement was posted here or here. Thanks to all the feedback we have got since 2.0.0-M1 release, and don't stop!
technorati: grizzly nio framework embedded

package at.bestsolution.qt;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QGridLayout;
import com.trolltech.qt.gui.QLabel;
import com.trolltech.qt.gui.QLineEdit;
import com.trolltech.qt.gui.QMainWindow;
import com.trolltech.qt.gui.QWidget;
public class HelloWorld extends QMainWindow {
public HelloWorld() {
setWindowTitle("Hello World!");
QWidget composite = new QWidget();
QGridLayout layout = new QGridLayout();
composite.setLayout(layout);
QLabel label = new QLabel();
label.setText("Label");
layout.addWidget(label,0,0);
QLineEdit text = new QLineEdit();
layout.addWidget(text,0,1);
setCentralWidget(composite);
}
public static void main(String[] args) {
QApplication.initialize(new String[0]);
HelloWorld world = new HelloWorld();
world.show();
QApplication.exec();
}
}

package at.bestsolution.qt;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import com.trolltech.qt.gui.QApplication;
import com.trolltech.qt.gui.QGridLayout;
import com.trolltech.qt.gui.QLabel;
import com.trolltech.qt.gui.QLineEdit;
import com.trolltech.qt.gui.QMainWindow;
import com.trolltech.qt.gui.QPixmap;
import com.trolltech.qt.gui.QPushButton;
import com.trolltech.qt.gui.QWidget;
public class MainWindow extends QMainWindow {
public MainWindow() {
QWidget widget = new QWidget();
widget.setObjectName("main_window");
QGridLayout layout = new QGridLayout();
layout.setMargin(0);
widget.setLayout(layout);
addHeader(layout,"Tom Schindl","at/bestsolution/qt/bookmarks.png");
QWidget content = new QWidget();
QGridLayout contentLayout = new QGridLayout();
content.setLayout(contentLayout);
addLine(0, contentLayout, "Firstname");
addLine(1, contentLayout, "Lastname");
addLine(2, contentLayout, "Age");
QPushButton button = new QPushButton();
button.setObjectName("submit");
button.setText("Submit");
contentLayout.addWidget(button,3,1);
layout.addWidget(content);
setCentralWidget(widget);
}
private void addHeader(QGridLayout layout, String labelText, String icon) {
QLabel header = new QLabel();
layout.addWidget(header);
header.setObjectName("header");
QGridLayout headerLayout = new QGridLayout();
headerLayout.setMargin(0);
header.setLayout(headerLayout);
QLabel headerIcon = new QLabel();
headerIcon.setObjectName("header_icon");
headerIcon.setPixmap(loadImage(icon));
headerLayout.addWidget(headerIcon);
QLabel headerText = new QLabel();
headerLayout.addWidget(headerText,0,1);
headerLayout.setColumnStretch(1, 100);
headerText.setObjectName("header_text");
headerText.setText(labelText);
}
private void addLine(int line, QGridLayout contentLayout, String labelText) {
QLabel label = new QLabel();
label.setText(labelText);
label.setObjectName("label");
contentLayout.addWidget(label);
QLineEdit text = new QLineEdit();
text.setObjectName("text");
contentLayout.addWidget(text,line,1);
}
private QPixmap loadImage(String path) {
try {
InputStream in = getClass().getClassLoader().getResourceAsStream(path);
ByteArrayOutputStream out = new ByteArrayOutputStream();
int l;
byte[] buffer = new byte[1024];
while ((l = in.read(buffer)) != -1) {
out.write(buffer, 0, l);
}
QPixmap pic = new QPixmap();
pic.loadFromData(out.toByteArray());
return pic;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package at.bestsolution.qt;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
import com.trolltech.qt.gui.QApplication;
public class Application implements IApplication {
public Object start(IApplicationContext context) throws Exception {
QApplication.initialize(new String[0]);
MainWindow window = new MainWindow();
window.show();
QApplication.exec();
return IApplication.EXIT_OK;
}
public void stop() {}
}
private String loadStyles(String cssPath) {
InputStream in = getClass().getClassLoader().getResourceAsStream(cssPath);
BufferedReader r = new BufferedReader(new InputStreamReader(in));
StringBuilder s = new StringBuilder();
String line;
try {
while( (line = r.readLine()) != null ) {
s.append(line);
}
} catch (IOException e) {
e.printStackTrace();
}
return s.toString();
}public Object start(IApplicationContext context) throws Exception {
QApplication.initialize(new String[0]);
MainWindow window = new MainWindow();
window.setStyleSheet(loadStyles("at/bestsolution/qt/style.css"));
window.show();
QApplication.exec();
return IApplication.EXIT_OK;
} and we need to define some styles:


This time I will demonstrate how easy and dead simple is to write a REST application using Atmosphere annotations…with the help of Jersey!
In part I I’ve described how easy it is to write an asynchronous/comet based application using an AtmosphereHandler. I strongly recommend you first read part I to understand the steps needed to generate the proper layout for your application. I also assume you already know how to write REST application using Jersey. Why? Let me introduce a new module available with the Atmosphere Framework named atmosphere-core. As a reminder, in part I have introduced atmosphere-cpr (Comet Portable Runtime), which allow a developer to write an AtmosphereHandler and deploy it in any Servlet container. Under the hood, the CPR always make sure its use the native comet support available, e.g if deployed on WebLogic, use the AsyncServlet, if deployed in Grizzy/GlassFish, use the Grizzly Comet Framework etc. Yes, you write once and deploy everywhere your Comet application.
The atmosphere-core module builds on top of the CPR and Jersey! The aim of Atmosphere is to simplify the development of Comet application, and since every time I’ve used Jersey, I always found it is really easy to write powerful application…then I've decided to build on top of Jersey! So here we come: announcing atmosphere-core v.0.2-M1, powered by atmosphere-cpr and Jersey (including all functionality supported by Jersey!).
Like it part I, let’s first define our META-INF/atmosphere.xml:
<atmosphere-handlers>
<atmosphere-handler context-root="/resources" class-name="org.atmosphere.handler.ReflectorServletProcessor">
<property name="servletClass" value="com.sun.jersey.spi.container.servlet.ServletContainer"/>
</atmosphere-handler>
</atmosphere-handlers>
If we compare with part I, this time the class-name we are using is a special AtmosphereHandler called ReflectorServletProcessor (RSP). The RSP listen to AtmosphereEvent like a normal AtmosphereHandler, but delegate the processing on the event to a servlet.service() method (a normal Servlet invocation), with a special addition which consist of storing the AtmosphereEvent as an HttpServletRequest attribute. The idea here is to support existing framework (like Jersey, Strut, JSF, etc.) without the need to modify those to support Atmosphere. Most of those frameworks support extension point, and all of them just need a reference to the AtmosphereEvent in order to suspend, resume and broadcast. Why is it called a Reflector? Mostly because every message broadcasted will be sent back to the client without any filtering or transformation. Say differently all suspended response will write as it is the message they receive (See AtmosphereHandler.onMessage for more info). Anyway as a developer you don’t need to know that…but if you are a framework developer, this is how you can use the Atmosphere Framework easily. In the current case, the RSP is configured using the Jersey’s main Servlet, called ServletContainer. As soon as you deploy your application, the Atmosphere framework will handle the lifecycle of the Jersey Servlet.
Next step is to write the web.xml:
<servlet>
<description>AtmosphereServlet</description>
<servlet-name>AtmosphereServlet</servlet-name>
<servlet-class>org.atmosphere.cpr.AtmosphereServlet</servlet-class>
<!-- Uncomment if you want to use Servlet 3.0 Async Support
<async-supported>true</async-supported>
-->
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>org.atmosphere.samples.chat.resources</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>org.atmosphere.core.AtmosphereFilter</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>AtmosphereServlet</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
In short, we define our usual AtmosphereServlet and maps all requests to /resources to it. There is two Jersey related properties defined. The only one you need to care is com.sun.jersey.config.property.packages. The property is required by Jersey to locate where to look for your application. Eventually Atmosphere will auto detect those, but for now you need to add it. In our case, it the fully qualified name of the package of our application. The second property is the Jersey extension point. No need to talk about it this time.
We are now ready to re-write the chat demo described in part I, re-using the same javascript code on the client side but this time without using any AtmosphereHandler, AtmosphereEvent, or Broadcaster, but instead using annotation (yeah!). Let’s start with the survival tool of Atmosphere annotation, which are @Suspend, @Resume and @Broadcast. You can write very powerful application by just using those I will talk about more annotations in part III). What the annotations are for:
So without going into the details of REST and Jersey (see this tutorial), writing a chat application just consist of:
@Suspend // the returned String will be written and then response suspended
@GET
@Produces("text/html")
public String cometGet() {
return "<!-- Comet is a programming technique that enables web " +
"servers to send data to the client without having any need " +
"for the client to request it. -->\n";
}
@Broadcast // The returned String will be broadcasted to all suspended response.
@Consumes("application/x-www-form-urlencoded")
@POST
@Produces("text/html")
public String cometPost(
@FormParam("action") String action,
@FormParam("name") String name,
MultivaluedMap form) {
if ("login".equals(action)) {
return BEGIN_SCRIPT_TAG + toJsonp("System Message", name + " has joined.") + END_SCRIPT_TAG;
} else if ("post".equals(action)) {
return BEGIN_SCRIPT_TAG + toJsonp(name, form.getFirst("message")) + END_SCRIPT_TAG;
} else {
throw new WebApplicationException(422);
}
}
Simple, is it? The way it works is the cometGet will be invoked, its returned value will be written back to the client and the response suspended. When the cometPost gets invoked, it’s returned value will be broadcasted, e.g. all suspended responses will be invoked and the value written as it is to the client since we are using the ReflectorServletProcessor. That’s it! With the use of two simple annotations, we were able to write our first atmosphere-core REST based application. OK, it's REST twisted, but still :-).
You can download the entire application here, or browse the source code. If you are already using Atmosphere, you must upgrade to Atmosphere 0.2-M1 to take advantages of those new functionality.
As usual, THANKS to the great feedback I’ve got so far. Early adopter, you make a big difference! For any questions, go to our main site and use our Nabble forum (no subscription needed) or follow us on Twitter and tweet your questions there! And if you are going to JavaOne, don’t miss the Atmosphere BOF on Tuesday @ 8h30pm with Jersey lead and Java Champion’s Paul Sandoz, which is a great speaker without a Quebecois accent
technorati: atmosphere comet
To say the past few months have been a whirlwind is an understatement.
And thanks for the reminders, I recognize it's been a while since I've posted a blog. For reasons why, just click here to read the background. And before you ask, SEC regulations and securities laws limit what I can discuss about the Oracle transaction, so don't expect any insights on the topic.
But there's still a ton going on at Sun - with JavaOne (June 2nd, in San Francisco) coming up fastest on the horizon. We're preparing to reveal what I believe is one of the most important advancements ever for the Java community - and this time, it's all about revenue and business opportunity.
As you know, we're fond of throwing great big numbers around when talking about Java's distribution: billions of PCs', mobile devices, and smartcards, millions of enterprise servers, set top boxes, Blu-Ray DVD players and a growing number of very cool Kindles (buy one here). Very few technologies on the internet have anywhere near that kind of distribution muscle. Adobe's Flash, and Microsoft's Windows are just about its only peers when measured by runtime volume.
But not all Java runtimes are the same. For most devices, from RIM's Blackberry to Sony's Blu-Ray DVD players, original equipment manufacturers (known as "OEM's") license core Java technology and brand from Sun, and build their own Java runtime. Although we're moving to help OEM's with more pre-built technology, the only runtimes currently that come direct from Sun are those running on Windows PC's.
And oddly enough, that's made the Windows Java runtime our most profitable Java platform. I thought I'd provide some insight into that business here, and then introduce a project we're planning to unveil at this year's JavaOne, known internally as Project Vector.
As a business model, traffic for traffic's sake isn't that interesting (but never confuse traffic with adoption). Free internet traffic is only interesting if a third party is willing to pay to drive distribution of their content to your audience - from highway billboards to internet runtimes, businesses will pay for exposure and distribution to drive their business, whether through branding/advertising, delivering news, or selling movies or retail products. "Getting distribution" used to mean getting access to bricks and mortar distributors in shopping malls - nowadays, it means having another company propel your content into the market via the internet.
Now to that point, a few years ago, we called our friends at one of the world's largest search companies (you can guess who), to talk about helping them with software distribution - because of Java's ubiquity, we had a greater capacity than almost anyone to distribute software to the Windows installed base. We signed a contract through which we'd make their toolbar optionally available to our audience via the Java update mechanism. They paid us a much appreciated fee, which increased dramatically when we renegotiated the contract a year later. Distribution was becoming quite valuable to us and to them - and given the "take" rates, or the rates at which consumers were choosing to install new content, the Java audience saw value in the new application.
The year following, the revenue increased dramatically again - when an aspiring search company (again, you can figure out who) outbid our first partner to place their toolbar in front of Java users (this time, limited to the US only). Toolbars, it turns out, are a significant driver of search traffic - and the billions of Java runtimes in the market were a clear means of driving value and opportunity.The revenues to Sun were also getting big enough for us to think about building a more formal business around Java's distribution power - to make it available to the entire Java community, not simply one or two search companies on yearly contracts.
And that's what Project Vector is designed to deliver - Vector is a network service to connect companies of all sizes and types to the roughly one billion Java users all over the world. Vector (which we'll likely rename the Java Store), has the potential to deliver the world's largest audience to developers and businesses leveraging Java and JavaFX. What kinds of companies might be interested?
If you talk to a Fortune 500 company or a startup, pretty much everyone craves access to consumers - which is the one problem we've solved with the Java platform. Most folks don't think of Sun as a consumer company, and largely we're not, but our runtimes reach more consumers than just about any other company on earth. That ubiquity has obvious value to search companies, but it's also quite valuable to banks looking to sign up new accounts, sports franchises looking for new viewers, media companies and news organizations looking for new subscribers - basically, any Java developer looking to escape the browser to reach a billion or so consumers.
How will it work? Candidate applications will be submitted via a simple web site, evaluated by Sun for safety and content, then presented under free or fee terms to the broad Java audience via our update mechanism. Over time, developers will bid for position on our storefront, and the relationships won't be exclusive (as they have been for search). As with other app stores, Sun will charge for distribution - but unlike other app stores, whose audiences are tiny, measured in the millions or tens of millions, ours will have what we estimate to be approximately a billion users. That's clearly a lot of traffic, and will position the Java App Store as having just about the world's largest audience.
This creates opportunity for everyone in the developer community - and specifically, for any developer (even those not using Java/JavaFX) seeking to reach beyond the browser to create a durable relationship with their customers (and btw, don't forget to join us for CommunityOne - the day before JavaOne, June 1st, same location - click the graphic to learn more). Remember, when apps are distributed through the Java Store, they're distributed directly to the desktop - JavaFX enables developers, businesses and content owners to bypass potentially hostile browsers.For details on how Vector will work, when it'll be available, how to submit your content or application - alongside insights into Project Vector's technology, roadmap, features and business model, come see us at JavaOne... In the interim, you can learn more about the latest JavaFX news at sun.com/javafx, and download the latest JavaFX design tools at netbeans.org.
And although we obviously don't comment on rumors, we might even have a special guest or two at JavaOne.
See you in San Francsico (or on the webcast...)!
I have decided to quit Sun Microsystems. I spent amazing 5 years at Sun and I am very grateful for all I've learned with the company. Working on both NetBeans and OpenSolaris adoption was real fun so I leave with very mixed feelings.
I am going back to Java developer business and will be going to Java One with my new employer, so you will find me in the Java One pavilion area if you want to say hi. I wish my Sun colleagues good luck with their new adventures!
P.S. Thanks for all the beans.
I came across this couple of times before and I always wanted to blog about it. In my daily work life I see many developers which just don’t get Open Source. For example, some discover issues in libraries they use. But they don’t fix them. They don’t even inform the maintainers of a library. Yet others have a great new use-case to address. Again, the library doesn’t support it. Thus, they write a great deal of new code to address their issue and eventually run into new ones (for example, see this thread).
But it’s that darn simple!