Plan B
Show me the media
Despite the rave reviews that JavaFX has received, one can't help fretting over Java's future as a "RIA" platform. Considering Java's 2D/3D graphics capabilities, JavaFX/F3 (with tool support) would no doubt leapfrog Flex/Apollo/Silverllight on that front. But what made flash the delivery platform of choice for a Youtube or a Google Video is not its technical superiority : its the support for basic/standard audio and video formats. And that's where Java (with its near-dead JMF) sorely lacks. While the download size can hurt Java on the desktop, the lack of media support is, imho, the principal crippling factor. Once that is addressed, JavaFX might just need to add constructs to leverage the JRE's media capabilities. But until such a time, there's plenty of catching up to do for Java in the Rich Internet Application space.
Update: I find it rather ironical that today's java.com feature video of JavaOne is delivered through - you guessed it - a flash player.
Posted at 10:06AM May 12, 2007 by Bharath Ravikumar in Java |
Google adds Java powered office product
Tonic systems (some name, huh?) is the latest addition to Google's repertoire of online productivity products. What's more, its Java based. While ThinkFree was always around on the text editing front, Power Point equivalents weren't getting enough press, imo. But hey, Tonic or ThinkFree may be some of the first Java based online products, but if you consider webstarted programs, the honor of getting there first probably goes to Gosling's Huckster. :-) (Really, check it out. You won't be disappointed.)
And you thought Java as a web based rich client platform was long dead...
Posted at 07:15AM Apr 18, 2007 by Bharath Ravikumar in Java |
Ruby on rails bites the dust
Interesting post on how twitter has found it hard to scale its ruby on rails infrastructure. While Java EE is often called bulky (true of EJB 2.x), clumsy(blame it on struts) and such names, ruby and its cousins are often lauded as the silver bullet for all web development problems. Though I've found ruby on rails awe inspiring (first saw it demo'd by Charles Nutter) for rapid prototyping and building lightweight applications, I've always doubted its ability to scale. Contrast twitter's case with the scale that eBay has achieved using servlets, custom connection pools etc., and you'll see why Java is leagues ahead in building large-scale server applications. And we haven't even started talking about the wide range of F/OSS middleware and tools available in the Java ecosystem.
Posted at 11:01AM Apr 17, 2007 by Bharath Ravikumar in Java | Comments[4]
BGGA closures and the principle of least surprise
Due to paucity of time (and that's an understatement), I wasn't able to post an elaborate rebuttal to comments on the previous post on closures. But Prof.Cay Horstmann's post on java.net has stirred up enough interest to warrant another post. I concur with one of the comments (that of Mikael Grev) in the blog.
While we all completely agree that Closures are important, one mustn't forget that code is written and (more importantly) read by developers. Humans, that is. And for newbies (and unsurprisingly, for java old-timers too), the principle of least surprise applies. Take a small survey of university students (even those that have started with C) and ask them if (and if yes, why) they prefer Java for application programming - and they'll tell you its the easier learning curve and intuition. When you read a certain segment of Java code, you can make an intelligent guess (knowing just the very basics) as to what the developer was trying to achieve. Its not the "generality" of the language that makes it ubiquitous - can java do a good job of playing various audio formats, or detect your USB drive and launch an application in response to it in a cross platform fashion? No. I hate to admit this, but Java remains dominant on the server side (and on mobile devices perhaps). It still has a long way to go (=>there're plenty of growth opportunities, which is good) on the desktop front. Which means it isn't yet a jack of all trades. A the ease of learning it remains one of its key strengths.
Speaking of readability and intuitive languages, there're very few "gotchas" in the JLS. (As much as one is tempted to compare the BGGA spec to the JLS, the latter is a delight to read.) And you won't hear Java developers talking about how their job interview involved "tell me what this piece of code does" kind of questions or other puzzlers. The fact that after more than a decade, there's just one seminal Java puzzlers book is a tribute to the language's simplicity. While developers are still grappling with changes to the type system brought about by generics (despite the excellent non-reified approach adopted). As one commenter pointed out, there're now entire sites and books devoted to generics. At such a point, how do you explain to a newbie (and we needn't debate how important it is to get more developers to take up Java) that for the sake of completion transparency, you need a new type Unreachable that's a subtype of all types, and of which null is a subtype? And I'll let you make a judgment on which of the following two pieces of unrelated code, each having a different level of conciseness and clarity, appears closer to the existing Java syntax:
{int=>int} plus2 = {int x => x+2};
and
new Thread(Runnable(){ foo(); }).start();
For the former, should the developer be asked to go lookup the BNF in the spec or understand how closure conversion works, to get a better understanding? On similar lines, as useful as it'd be to similarly have first class XML support or embedded SQL in Java, it brings with it clutter and code-obscurity. When you expect to read Java code, you should get to see just that - and not ruby style blocks and or contortions like the absence of semicolon in the last line of a block. Also, I disagree with the argument that only API developers need to be aware of Closures with the rest of the world blissfully using it. As Josh Bloch pointed out, if you code extensively, you're more likely than not an API designer. So there's hardly any escaping the cognitive load of syntax like that of BGGA function types. In conclusion, and IMHO, as a user of the language - I'm no language expert - I'd prefer readability of code and preserving of the existing type system at the cost of feature-richness. It's great to have control abstraction API, expressiveness and conciseness, but it's better achieved in a way that doesn't complicate the type system. I'd rather see the the CICE with ARM blocks or the FCM proposal enhanced to address this need instead of a sledge-hammer panacea proposal. The Java community surely needs Clourses and has asked for it in several polls, but let's make no convenient assumptions about what form of closures it seeks.
P.S: If you found it painful to go through this "rich and expressive" post due to excess of hyphens, brackets, commas at unexpected points, I'd compliment myself for having highlighted the importance of readability (of prose and of code).
P.P.S: Next post : when time permits.
Update: Stefan Schulz notes that there is indeed a proposal to extend FCM to accommodate control abstraction API.
Posted at 01:33PM Apr 14, 2007 by Bharath Ravikumar in Java | Comments[1]
Missing in Java SE 7: Simplicity
First, it was Closures. (If you do not understand the proposal after 2 reads, fret not - you aren't dumb. Its just that you deserve a simpler alternative.) And now its the Properties syntax that's taken center stage. We might next have a language extension where a special syntax like "<%$$%>" will make the runtime play a random MP3 from your favorite playlist. Cool, huh?
I couldn't agree more with Dan Creswell. Why is it hard to understand whether developers really need language extensions, new libraries or simply better IDE support? And what is most worrisome is the (apparent) difficulty that the silent majority of the Java community has in drawing attention to the increasing complexity of the Java language. At a time when Java newbies still struggle to understand generics, we're involved in an arms race with other languages to cram as many new "features" as possible. Is the community clamoring for these features? Has anyone bothered to ask? At this rate, what we'll need to decipher Java code is not an IDE, but this.
Honestly, I'd be tempted to stick to Java SE 6 (and not upgrade to 7 in the next decade) in order to escape the mindless complexity.
Planet earth calling JCP. The power of Java lies in its simplicity. Don't kill it. Can you hear me?
Posted at 08:56PM Feb 01, 2007 by Bharath Ravikumar in Java | Comments[4]
Programmatically looking up Java reserved words
(Warning: the solution discussed is specific to Sun's javac compiler and is not "vendor" agnostic)
Let's say during code generation, you want to make sure that you don't use java reserved words as identifiers. Trivially, you could go through the hassle of creating an Enum for yourself and manually populating it with known reserved words for that version of Java. But, why reinvent the wheel when the compiler already has that information (updated per release)? All you need to do is create an EnumSet from the Enum com.sun.tools.javac.parser.Token and look it up to know if a certain String is a java reserved word.
The only problem with this approach is that it relies upon an implementation specific class/package(com.sun.* can change without notice and do not constitute an API). But if laziness takes over, its still an option worth considering for one-off usage. Of course, I'd like to know better (implementation independent) alternatives.
Thanks to Sundar for providing pointers in the javac source.
Posted at 12:57PM Jan 21, 2007 by Bharath Ravikumar in Java | Comments[3]
Putting type tokens to use
I recently found the need to write a (quasi) command object that's an abstraction of a CLI command. Roughly, it looks like:
public abstract class CLICommand{
//Some implementations go here...
protected abstract String getCLIString();
protected abstract Map getCmdParams();
}
Now you might ask, why not simply have an execute method as in:
public abstract class CLICommand{
//Default implementations go here.
public Object execute();
}
(Or, to further refine my version, why not have a Command interface and an abstract base class providing default implementations of some methods? Agreed, but that's not the point of our discussion now. Moving on...)
The primary reason for not having a conventional command object is circumstantial: in our case, the command objects themselves do not have all the information required to execute the command. In particular, they will not have the authentication information needed to (remote-)execute the command. All they can do is to provide command specific parameters, string representation and such details. Due to legacy reasons the security related information is kept in a ThreadLocal field within the command executor. (Otherwise, the security related information could be stored in a "secure" class could wrap around a bare-bones command and could remain transparent to the executor. Anyways...)
Subclass of the classic Command object might return different types depending on the command executed. So, we'd generify the command object as in:
public abstract class CLICommand<T>{
//Other impl details
public T execute(Map params, ...);
}
But, how would you apply this to the pseudo command object we're dealing with?
Enter type tokens. In Java SE 5, the class Class was generified (with additional type parameters named type tokens). For example, the type of String.class is Class<String> (Of course, Class' methods were further generified in Java SE 6)
So, here's what our neo-Command class would look like:
public abstract class CLICommand<T>{
//Some implementations go here...
protected abstract String getCLIString();
protected abstract Map getCmdParams();
protected abstract T getReturnType();
}
And how would a command executor use this?
public final class CommandExecutor{
public static <T> T executeCommand(CommandIF<T> cmd){
//Relies on a legacy non-generic executor that declares
//return type object, but internally returns a specific type
Object result = oldExecutor.execute(cmd.getCmdString,
cmd.getParams());
return cmd.getReturnType().cast(result);
}
}
And voila! We're done! If you're curious to know how you'd handle a command that returns nothing, here's an implementation of such a command:
public final VoidCommand extends CLICommand<Void>{
public Class<Void> getReturnType() {
return Void.class;
}
//Other details...
}
Update: To be absolutely sure all kinds of type parameters (including parameterized types) can be returned and used, you'd want to use Neal Gafter's super type tokens.
And as if all these considerations weren't enough for the day, a related piece of code that was compiling in Java SE 5 fell apart in 6. The reason: a rather presumptuous, short sighted cast that I had introduced:
Map<String, String> props =
(Map<String, String>) propertiesObject;
It was merrily compiling in Java SE 5 thanks to this compiler bug. Sigh.
Posted at 01:49PM Jan 16, 2007 by Bharath Ravikumar in Java |
RMI sans the rmiregistry
Eamonn McManus recently blogged about ways of securing the RMI registry from local modifications by malicious clients. If you must use the registry, those are effective (if slightly hacky) techniques to secure the RMI registry. (On a related note, a number of RMI-newbies tend to wrongly assume that the rmiregistry is somehow responsible for routing every method invocation and must be used all the time.) But RMI separates the "discovery" of a server object from the actual invocation upon it. (Notice that I said server object and not service - with all the SOA buzz and self-proclaimed "experts" criminally equating SOA to WS-* standards, I hesitate to use the word "service" and have readers make faulty assumptions based on jargon. Anyways...) When you initialize the RMI server implementation and export it through UnicastRemoteObject.exportObject, the returned java.lang.reflect.Proxy object implements Serializable as well (The proxy mechanism became the default instead of rmic generated client stubs in Java SE 5). As a result, you're free to share it with potential clients as you please: write it to a directory server that allows RBAC, persist to a DB, serialize it over a socket, put it up for clients to download from a web/ftp server and so forth.
In fact, such flexible service discovery is one of the key features of Jini: while you're welcome to use the default lookup implementation ("Reggie"), the Jini API makes no assumption of the discovery service implementation. In fact, any host can run a Lookup service and lookup services themselves can be dynamically discovered. No, that was not a circular definition - you can use multicast to lookup a discovery service. How cool is that?
In summary, if you're planning to build a system using RMI, you're free to use your own lookup service if rmiregistry doesn't serve the purpose. You must, however, evaluate the merits/demerits of one approach over another before deciding upon the actual implementation.
(And by the way, wish you a peaceful, healthy and prosperous 2007 :-))
Posted at 01:38PM Jan 01, 2007 by Bharath Ravikumar in Java | Comments[1]