Archive for the ‘Java’ Category
So I’ve gotten past a number of the issues I blogged about previously, and I now have a Tomcat-only no-EJB3 version of the Seam blogging example. I’ve tried rolling the GWTJSF code from my original example back into it, and it looks like Seam 2 has thrown another wrench in the works.
As Chris Alfonso at JBoss warned me, Seam 2 installs the SeamPhaseListener by default. The Seam/GWTJSF integration as it previously existed needed its own phase listener, as explained in my article on the topic. This delegating-PhaseListener technique seems to be impossible in Seam 2. (Unless I’m missing something.)
With the GWT conference breathing down my neck, I may need to sideline this for a while until I get a fallback presentation together — I was hoping to be able to demo GWT 1.5 (if it gets done in time!) with JSF 1.2 and Seam 2, but I can’t count on that at this point, there are only four weeks to go and I don’t have the hacking time I’d need. So it’s Plan B time. I’ll take a week or so and get the presentation together with the previous version of the code, and then I can pound on Seam 2 some more.
Also, it looks like the GWTJSF code has officially been left behind in the Ajax4JSF 1.1.1 code tree, which has been rolled into the RichFaces project — except for GWTJSF, which is nowhere to be found in the RichFaces code tree. GWT can definitely be considered a competitor to RichFaces, so I guess I see why JBoss isn’t supporting GWTJSF, but still it’s a shame. It’d be great to see some more synergy there, but I’m not sure how to bring it about. (other than blog about it and rock the boat a little😉
Anyway, sorry to those who’ve been wanting to use GWTJSF with Seam 2 — it’s going to be a longish road. All help very much appreciated if anyone else has cycles to hack on this with me!!!
Last week I griped about some hassles I was having with Seam 2, Java 6, Tomcat, and JBoss Embedded. I grumpily grouched about the grim gloom of an open source world where things break and people don’t get along very well, and how non-fun it is.
And hey presto, what should happen but two Red Hatters read my kvetching and chimed in with some downright helpfulness. First, Jason Greene mentioned this workaround for the bizarre Java 6 ClassNotFoundException I mentioned. Seems there is a magic JVM flag you can provide to revert to the Java 5 classloading behavior if it causes you too much trouble. That’s good to know, and I appreciated the clue.
Second, Chris Alfonso — who’s been asking me when I’m going to get around to fixing my GWT/JSF/Seam demo to work with Seam 2 — said that he’s got a Maven 2 version of the GWTJSF demo building as an EAR that runs under JBoss with EJB3. Which is cool, because I now have a plain old Hibernate version of the Seam 2 blogging demo that deploys under vanilla Tomcat, so it’s nice to have both flavors. (Chris, can you send me your version? I’d like to poke at it some — I won’t post it without your say-so.)
So that’s the great thing about the open source community — it is a community, and people offer each other helping hands. Thanks for brightening my week, guys! You put the fun back in🙂
A couple of months ago, I was honored to learn that I’ll be doing a presentation at the upcoming Pearson GWT conference in San Francisco in early December. I’m quite grateful for this opportunity.
What’s more, I just learned that they’re giving me a discount code! Head to the site and enter code GW-JELL for $100 off the registration fee. Woo!
Originally I contacted Pearson with the suggestion that I might do a GWT/JSF talk, but there wasn’t enough room on the agenda for that. Instead they’d planned to have Miguel Mendez (the author of the GWT RPC code) do a presentation about RPC in GWT. It turns out that he can’t make it. So I’ll be presenting on it instead. It’ll be impossible for me to do as good a job as Miguel would do, but I’ll give it my best shot. (Thankfully it’s the area of GWT that I understand better than any other!)
So the next question is, what exactly should I discuss? I’d like to throw this open to the community to some extent. If you were going to a presentation on GWT’s RPC, what would you want to learn about?
I’ll start by listing the things I personally want to know more about (from most to least):
- how to use GWT RPC with Hibernate or other Java persistence frameworks (particularly interaction with lazy loading)
- best practices for scoping the object graphs you send in RPC (to manage problems of updating server state in a large object graph)
- Java 5 support in GWT RPC: how generics are handled in GWT 1.5
- organizing your RPC code for best readability and easy sequencing
- integrating with JSF, Spring, and other server frameworks
Obviously this is way too much already for a mere hour-long presentation, but that’s my problem, not yours🙂
I’d appreciate it if people could post their favorite topics. If you can list them in order from most urgently interesting to least, that would help me.
I’ll be working with Miguel to refine the presentation over the next couple of months (thanks, Miguel!). There’ll also be some blog posts coming out of it. And I’ll see you in San Francisco in December!
One of the tough things about open source is that the world never stands still. Actually, it’s not just open source, it’s software in general, but open source exacerbates it. See, one of the main motivations for open source developers is fun and the enjoyment of sharing something cool you did. So you’d like to be able to do something cool and then have it stay cool.
But the problem is, once you get something cool working, it’s almost guaranteed that it’s going to stop working soon. Why? Because everyone else is doing other cool things. Including all the developers whose projects yours depends on. So the odds approach 100% that before long your cool thing is going to break with the latest version of FooBarLib. And broken things are no longer cool.
And fixing your cool thing, that broke for no fault of your own and for reasons you don’t agree with, is the absolute opposite of fun.
Even large developers are vulnerable to this. Right now I’m banging my head against trying to get my Seam + GWT example working with the latest 2.0 release of Seam. But Seam made a number of changes that are frustrating me rather deeply right now. For one thing, they changed the packaging for their embeddable EJB support such that you have to install the JBoss embedded EJB container directly onto your Tomcat. No more delivering a nice simple WAR file that uses Seam and EJB3, now it’s a multi-step process that leaves your Tomcat fairly JBossified.
The nominal rationale for doing this is that it lets the EJB3 services be shared by all the apps inside that Tomcat instance. So you might think, great, now my Seam+EJB3 WAR file is 6MB instead of 20MB. (Which is indeed a problem with the demo version on my page — it’s stinkin’ HUGE.) But, BUT, it turns out you can’t actually run multiple Seam apps under the Embedded EJB3 container!
Why not? Well, because Bill Burke and Gavin King, both of whom work at JBoss and both of whom are fairly bullheaded, can’t agree on whose problem it is that multiple Seam apps collide in the Embedded EJB3 component registry. Not only that, but the Embedded EJB container’s development has stalled. So, Tomcat is a seriously second-class citizen as far as Seam is concerned now. Of course from a JBoss perspective this is arguably good, because JBoss doesn’t get support revenue from Tomcat installations. For me, though, it sucks, because I don’t want my Seam / GWT example to require JBoss.
And the icing on the cake is that the Embedded JBoss container doesn’t run under Java 6. I like to run on the latest Java. It’s just a funny preference I have, I don’t know why. But JBoss does classloader tricks that Sun apparently considers invalid loopholes, which Sun closed in Java 6. This results in charming errors like:
ERROR 01-11 21:56:07,921 (AbstractController.java:incrementState:456) -Error installing to Instantiated: name=DeploymentFilter state=Described java.lang.IllegalStateException: Class not found: [Ljava.lang.String;
And JBoss and Sun are finger-pointing about who broke who. So Seam isn’t at all guaranteed to run under Java 6 in any way, and JBoss and the Seam team consider it Sun’s problem, not theirs.
So what am I going to do? I’ve got a conference presentation coming up and I wanted to use this demo with the latest Seam and latest GWT. But it’s starting to look like I’m going to have to sink way too much time into mucking about with Seam for reasons I’d rather not have anything to do with. I’ll probably follow the path of least resistance, which is just to roll back to Java 5 and grin and bear it. It’s definitely demotivating, though. Definitely. Demotivating.
I really like Java. It’s definitely my favorite language, and the one I’ve written the most code in, by far. Its balance of static typing, great libraries, OS independence, “no surprises” philosophy, and unsurpassed tool support mean that I’m more productive in Java than in any other language I’ve tried.
But that’s not to say it’s perfect. There can never be an objectively perfect language, since there are too many kinds of software that need to be written, and all languages have expressive tradeoffs that affect their usefulness for those purposes. But even on its own merits, Java’s got some major issues.
The biggest issue is the infamously named “classloader hell”. All reasonably experienced Java programmers know it bitterly well: the difficulties of running code within application servers or other kinds of complex deployment situations, where there are multiple sub-projects all loading code at runtime and attempting to operate with each other. (Briefly, for those who don’t know, Java code is loaded by objects named “classloaders”; classloaders define a name space of loaded classes, and a single class, if loaded by multiple classloaders, is considered to be two distinct — and non-interoperable — classes.)
This is one area where Java’s original standard was written in haste. The model of classloaders delegating to each other, the way that classes are considered to be different if loaded from different classloaders, and the many problems this can cause — all are fundamental problems that manifest in a variety of confusing and confounding ways.
The problem gets much worse when you get into code interoperating between multiple systems on a network, each of which may have subtly different versions of the system’s code. The entire Remote Method Invocation standard was predicated on the assumption that Java’s ability to load code over the network would enable code to travel alongside the network messages that reference that code. It feels to me like a case of “wow, Java lets code run anywhere! Just think of what that lets you do for a networking protocol!” The problem was that the versioning issues weren’t well understood, and that has caused bitter pain in actual usage.
It’s not like Sun isn’t aware of the issues. This technical report covers the basics: it’s possible to set up RMI scenarios where perfectly innocent messaging patterns result in systems being unable to send messages to each other at all. Worse, the runtime behavior is difficult to analyze or understand.
These problems aren’t merely abstract. Another Sun paper discusses an entire advanced networking system that was well into development, based on Jini and RMI, when these problems reared their ugly heads and fundamentally destabilized the entire project. The ultimate reason for abandoning the project was its business infeasibility, but it’s clear that Sun’s own technologies — as currently implemented — were deeply broken.
Now, security, versioning, and interoperability are notoriously hard problems, and it’s far from clear that anyone has really great solutions to them. Certainly Sun can’t be too deeply faulted for not getting it right — Java did get many other things right (including OS independence, dynamic compilation, dynamic inlining, garbage collection, and much more). So I don’t mean to pick too deeply on Java; I just mean to highlight some of the biggest outstanding issues with the language.
There’s work going on to fix at least some of this: for example, the Java module JSR, #277, is intended to bring at least some rigor to the entire classloading system. The .NET framework has a better grasp of module loading issues, though I’m not aware of how .NET messaging compares to RMI or whether it’s exposed to any of the same issues. The Fortress language is taking a much more rigorous approach to component versioning and component assembly as well. But most of these seem dedicated to fixing the module loading problems in a single environment; I don’t know of much work on addressing the security and versioning issues associated with network messaging (though JSR 277 does address some of the naming issues that break RMI and Jini).
Still, that’s the great thing about software: there’s always more that needs fixing, and more great things to build! Expect many more posts on this general topic….
Catch-22 with Maven: how can you create a project that has a dependency on another project that hasn’t been stored in some repository somewhere?
I’d love to land my GWT/JSF integration work. But the Ajax4JSF team really likes Maven for some reason. And my code relies on GWT 1.4, which isn’t final yet. So there’s no way for me to check in a Maven build that uses it, because there’s no repository in the world that has it.
Feh. I like what Maven is trying to do, but I would love there to be some middle ground here. Gavin King wants to do lunch next week to talk about the GWT/Seam stuff, though, which is cool.
Meanwhile, Rob Hanson is working on a GWT/Gears ORM implementation, and Ryan Dewsbury (author of the legendary gpokr.com, as well as a book about GWT applications) already has a GWT Blogger client written and working as part of his book. So it looks like gluing those two together would be an offline Blogger client in, like, no time. Ryan’s looking into how soon Addison-Wesley will approve the source for some kind of release, Rob Hanson’s going to have code working by Monday.
Given that the Maven stuff is slowing me down on finalizing the GWT/JSF stuff I did, it may be that Hanson and Dewsbury are going to put this offline Blogger-editor thing to bed before I can get my head out of my butt. Which would be fine — GO GUYS GO! There’s always more code to write, and no sense being selfish😀
I’m writing this in Notepad while riding the BART train on my normal morning commute into San Francisco. This commute takes about forty minutes each way for me. Since there’s no Internet, I can’t connect to work at all. Hence this is dedicated time for reading, or writing, or hacking on things that don’t need a full development environment (my laptop is a bit too old to cope with our entire code base from work anymore).
So of course blogging would be a natural. And sure, writing in Notepad is not torture. But it’s also not the right thing. What I want is to be able to write blog posts, edit them, save drafts, etc., etc., and then the minute I get back online, upload ’em all to Blogger and worry no more about it.
To do that requires some kind of offline application with local storage. As my last post mentioned, I originally wanted to build such an offline app as a standalone Tomcat-based Seam webapp that would run in a local webserver. But Google Gears offers a much more direct route to the same destination.
So this post is a breakdown of how to construct such a client, based on conversations with various Googlers last week at Google’s Mountain View developer day.
Must-have requirements for an offline Blogger editor:
- be a web application running in the browser (duh!)
- support rich text editing at least at the level of Blogger’s own online editor
- support authentication to Blogger
- support local storage of some or all of the user’s blog posts
- support creating, viewing, drafting, and editing of posts whether online or offline
- allow synchronizing any offline edits to Blogger once back online
- allow synchronizing of any posts edited on Blogger down to local storage
- allow very minimal reconciliation of conflicting edits to posts on Blogger
- require minimal installation of plugins or other application-specific software
Nice-to-have requirements for an offline Blogger editor:
- support archiving / backing up of a user’s entire blog
- support re-importing some set of content to a new blog that supports the Blogger API
- support migrating content between blog services
- support deleting postings ahd handling synchronization of offline deletes
- provide a nicer browsing/reading UI (arguably Google Reader has this job sewn up already)
(Needless to say, the nice-to-haves don’t get done until all the must-haves are working!)
- No need for this application to render any static HTML (the blog can presumably still be viewed and searched through Blogger itself; this app can be *just* an editor)
The API Implementation
Clearly this is exactly the kind of application Google Gears was created to support. So let’s assume we’re using Gears. Further, since I like GWT a whole lot, let’s also assume we’re using GWT.
I originally thought that this app could be built as a GWT/Gears webapp connecting directly to the Blogger API. Dan Morrill of the GWT team set me straight on that. The Blogger API is very pure in its REST-fulness, meaning specifically that it uses all the HTTP verbs. However, XMLHTTPRequest, the entire foundation of AJAX, can’t do anything other than GET and POST. So whatever we do is going to have to involve some kind of servlet bridge to the Blogger API.
(Possible workarounds for this: 1) get the Blogger and GData API teams to make GET/POST-only variants of their PUT/DELETE API methods; 2) get the browser vendors to implement PUT/DELETE support in XMLHTTPRequest. Clearly #1 is a lot more doable than #2 given the dreaded words, “legacy support”. You listening, GData team???)
Once we’ve accepted the need for some kind of bridge servlet, we’d better make sure that bridge servlet is fairly scalable and generic. Whoever is hosting this bridge servlet is going to have potentially a lot of traffic. So the bridge servlet needs to be stateless, re-entrant, and as close to a simple pass-through as possible. It shouldn’t have per-session state; it should be just a message relay.
We’ll also need some GWT modules for communicating with the bridge servlet, including beans that map to the data objects defined in the Blogger API, and service interfaces that map to the Blogger API’s methods. And in fact, this suggests that the servlet itself should simply use the Java implementation of the Blogger client API, exporting a GWT-friendly version of it (via GWT RPC) to the GWT client application.
The persistence implementation
Gears has this lovely local SQL database. But how do we get things in and out of it? We could write to the JDBC-like Gears SQL API. But I have tasted Hibernate. And if I’m programming in GWT, then writing JDBC-like code by hand would be like going back to the pre-Hibernate days. And I can’t do it. I CAN’T DO IT, I TELL YOU! I can’t go back. I WON’T go back!
It looks like some other folks on the Gears list have had similar thoughts. Check out this Gears ORM implementation. But since that’s not based on GWT, it’s not directly applicable. Still cool though! But let’s assume we’ll proceed with Bob’s stuff, just for fun. This is all still early days and all experiments still deserve love.
The todo list
So, what do we have?
- GWT beans mapping to Blogger API data objects.
- GWT service interface mapping to Blogger API methods.
- Bridge servlet implementing GWT service interface and using Blogger Java client API implementation to relay messages to Blogger.
- Simple persistence code generator (using a GWT compile-time generator implementation) to take the GWT beans and store them in the Gears local database.
- Business logic to implement the client-side synchronization to the Blogger server. (That’ll be another post, or maybe lots of them!)
- GWT UI code to let the user use all of this infrastructural goodness to meet the must-have requirements!
If we get it right, it hopefully lands in the Google GWT API project. And once Blogger does this, Calendar is next, and then some.
Sounds like a fun project, huh? Interested? Chime in in the comments. Or join this GWT-Contributors thread on the topic.