Tuesday Jun 05, 2007

The Myth of Rapid GUI-based Development

I got my hands on a session pass at Java One's "community one" event, and decided to attend two session for which I am a newbie: JRuby and Matisse - both of which were under the "Netbeans Track".

 Both of the sessions were essentially a demo, which consisted of someone very well versed with both the technology and Netbeans quickly clicking and typing to produce some interesting application in an unreasonably short amount of time. Wow! What really gave me goose bumps was when the audience applauded the results. Not goose bumps because I was impressed, but the kind of goose bumps you get when you are embarrassed for someone else.

For any GUI-based development, whether it's portlets, EJBs, SWT applications, or whatever, there will come a point very quickly when you need to do more than the "hello world" component. At that point, you will need to have an intimate knowledge of the underlying technology. Now, the problems is that the GUI lets you get from 0 to 5 without any real knowledge. To do anything more, you need to go back and learn what the GUI did to get you from 0 to 5, which is more difficult than just going from 0 to 5 the "hard" way, by actually learning.

 Rapid GUI-based development tools make good demos. They impress product managers and sales folks. They even sell products. But they are not solutions for real developers.


Tuesday Mar 20, 2007

Hummer Greener Than Prius?

A Slashot article is reporting that in terms of total energy used over the life of the car, considering the cost of manufacturing, the Hummer is greener than the beloved Prius. Great stuff. And, as is pointed out in several article comments, the environmental impact of mining the materials for the batteries is horrendous.

And a comment on the article that I really liked:

The Prius was never for real environmentalists anyway. It's for lazy yuppies who want to put out an environmentally conscious image. Real environmentalists live close to work, bike, or take the bus.

It's also fairly well known that where the Prius excels in gas mileage is in-city driving. If you are getting a Prius to drive in city, then you can probably easily take a bus / train, walk, or ride your bike.

 

 

 

 

Monday Mar 19, 2007

JSF h:commandLink and onclick events

If you've ever tried to add an onclick handler to a JSF h:commandLink component, you'll notice that the event isn't defined. The reason is that JSF uses onclick for it's own purposes, to POST the click where it would normally be a GET request. For example,

<a id="entriesTableView:feedForm:feedTable:0:deleteEntryLink" 
href="#"
onclick="clearFormHiddenParams_entriesTableView_feedForm('entriesTableView:feedForm');document.forms[ ... and so on ...

This makes it impossible to do one of the most basic onclick tasks: confirm an action. If you Google for this, the suggestion is to set the onmousedown handler, and use it just as you would onclick:

<h:commandLink action="delete" onmousedown="return confirmDelete(this);">

Nice idea, but it turns out that many browser do not treat the "return false" from the onmousedown event the same way as with onclick. Normally, the false return value means abort the user's click. However, it appears that it does NOT necessarily mean abort the onclick event handler. The result is that the onclick is executed regardless of the return value of the onmousedown event handler.

The solve this, you'll need to do some Javascript trickery. The basic idea is to re-assign the link's onclick handler to a new Javascript function that has a pointer to the original (JSF defined) function. The new function does the ok / cancel logic. An "ok" just calls the original JSF-defined onclick function. "Cancel" returns false from onlick, and aborts the click like we want.

... 
var deleteClick;
          
function assignDeleteClick(link) {
  if (link.onclick == confirmDelete) {
    return;
  }
               
  deleteClick = link.onclick;
  deleteMsg = msg;
  link.onclick = confirmDelete;
}
           
           
function confirmDelete() {
  var ans = confirm("Delete?");
  if (ans == true) {
    return deleteClick();
  } else {
    return false;
  }
} 
...
<h:commandLink action="delete" onmousedown="assignDelete(this);">

 Note that this re-assigns the onclick event every time the link is clicked. This is not necessary and it could be done once in the onload event. This would require hardcoding of the big long scary JSF component ID, which I do not like doing. This is the reason that the first lines of assignDelete() check to ensure that the assignment hasn't been done already.

 


Monday Feb 12, 2007

Blogging Portlet

I just committed Blog Portlet to the Portlet Repository java.net project. Blog portlet allows portal users to manage their weblog from a portal page. It depends on the weblog implementing (and turning on) an Atom Publishing Protocol endpoint.

 

The intent is not to replace the native weblog user interface, but rather to provide a simplified one that allows users to perform the most common management operations from their portal page: post, edit, delete.

In addition, the portlet has a simplified interface for creating weblogs and weblog users. This feature depends on the AAPP admin interface in Roller - meaning, you have to point the portlet at a Roller weblog server.

There are a couple of caveats at this point ...

  1. The portlet is really a JSF application, and therefore depends on JSF Portlet Bridge. While this is called out in the portlet's pom.xml, the dependency is not available from any repository. Therefore, to build Blog Portlet, you need to get and build the JSF Portlet Bridge and populate the dependency into your local repository. Hopefully this will change in the near future.
  2. While the portlet is setup to use FCKEditor to create and edit weblogs, FCKEditor is also not available as a dependency. So, by default, FCKEditor won't be there, and you'll get a standard ugly text area. To make the portlet is FCKEditor, get the "fckeditor" directory into the web application. You could do this after you deploy the web app by just dropping the files into the right place, or you could do it in the build environment by copying ther directory into src/main/webapp. Or, alternatively, it should be easy to plug in whatever Javascript editor you like by making some small changes to the portlet.
  3. The portlet is only tested with Roller's APP implementation. APP is new and somewhat unstable, so I hope folks can help out and get this tested / working on other APP implementations.
  4. Documentation is slim. I hope to either upload some documentation, or point to the Sun Portal Server 7.x documentation for the portlet that should apply 98% to the open source version. This documentation is not yet posted to docs.sun.com however. In the meantime, if you have questions, please post comments, or better yet, post to the Portlet Repository user mailing list and I will be glad to help you out.

Have fun!

 

Thursday Jan 18, 2007

Flickr Portlet

I've posted Flickr Portlet to the Portlet Repository project. Flickr exposes a (web) service API to their photos. This portlet simply consumes that interface and makes it available from a portlet user interface.

 

 From the portlet, you can browse your photos, upload photos, browse your contacts' photos, and search for photos. Well, the search part is just stubbed out for now.

The portlet is just a front end for Quickr, which does a nice job bridging the Flick services API to Java. One cool thing about the portlet is that it makes use of Lightbox JS to allow for asynchronous browsing of photos in a larger scale:

 

The Portlet Repository project does not have binaries right now, so grab the source and build it to get the portlet WAR. 


Monday Nov 20, 2006

Quickr Flickr

Flickr has a robust set of web services for accessing their hosted photos, and more. There's already a wide variety of API kits to adapt the various response formats (XML-RPC, REST, SOAP) to different languages ... including .NET, PHP, Ruby, Python, Perl, and others. However, the Java contingent is a little weak. To support the Flickr Portlet I am developing for the Portlet Repository project, I started the Quickr Flickr project. This is essentially a Java wrapper around the Flickr REST services. 

I think I've done a fair job of making it simple to use the Flickr web services from Java. If you're interested in writing Java applications or web applications that build on Flickr, take a look at Quickr Flickr! It's not completely built-out yet (it doesn't map to all of the Flickr service methods), but it's getting there.

Wednesday Nov 15, 2006

Goodbye, Pluto

After using the full-featured Sun Portal product to try and do portlet development for a few years now, I've been looking for something more light weight. Essentially, I needed something I can run on my OSX laptop. The obvious choice for me was Apache Pluto. It's been around for a while now. It's the core of Apache Jetspeed-2, and other portals. It's the JSR-168 Portlet RI. Here is my experience ...

First, Pluto 1.1 (beta) requires me to add some heinous blocks into my Maven2 POM in order to deploy. While I think this is a stopgap until 1.1 has a deployment tool, I have to outright refuse anything  that requires vendor-specific aspects to my portlet. So, I ruled 1.1 out immediately.

Pluto 1.0.1 has a palatable GUI deployment tool. However, I never got my portlet to run. Now, I accept the fact that this may be a result of problems in my portlet, but the container has to TELL ME what the problem is. Class not found? JSP compilation error? Nope. Pluto would only tell me that there was an "error in portlet":

Nov 8, 2006 4:03:16 PM org.apache.pluto.portalImpl.services.log.LoggerImpl errorSEVERE:
Error in Portlet
java.lang.NullPointerException
        at org.apache.pluto.invoker.impl.PortletInvokerImpl.invoke(PortletInvokerImpl.java:109)
        at org.apache.pluto.invoker.impl.PortletInvokerImpl.load(PortletInvokerImpl.java:80)
        at org.apache.pluto.PortletContainerImpl.portletLoad(PortletContainerImpl.java:218)

No other clue. I can hardly believe that there is not some way to get more information ... but I asked (twice) on users@pluto.apache.org and received no response. Also, as a side issue, Apache's spam filter rejects any email I send from my Yahoo! mail account. That makes getting help pretty difficult :)

Enter the java.net Portlet Container project. It's only been live since August 2006, and it's already superior to Pluto. It's simple to install and configure (requires Glassfish), and best of all, IT RUNS MY PORTLET, or if not, TELLS ME WHY.

 As a bonus, it actually lets you undeploy a portlet, something that Pluto 1.0.1 does not (you have to manually edit several XML config files).

Full disclosure: the Portlet Container project is Sun-sponsored and has been developed wholly by Sun employees. However, I want to make it clear that I really, really tried to work with Pluto. This is an honest assessment of the state of the art.

Wednesday Oct 25, 2006

JSF, your killing me here ...

The other day, I started working on a new JSF-based portlet app ... essentially, a JSF app that would use the JSF-Portlet Bridge so it can be sucked into a portal. Without going into details, the app needed to draw a table where each cell contains one object from a set of objects. For example, think of a photo album. Each table cell contains a photo and some meta data about the photo perhaps.

I would have really though this is a common enough pattern that it'd be straightforward in JSF. Well, it's not. The only tabular-type components in JSF are panelGrid and dataTable. panelGrid does not allow a dynamic data sets; you must call out all of the cells statically. dataTable only supports a "one object per row" scenario, as opposed to per-cell as I needed.

For example, suppose I had a tag called dataGrid. I'd want to use it like this:

<h:dataGrid var="photo" value="#{album.photos}" columns="6">
  <h:cell>
    <h:panelGrid columns="1">
      <h:graphicImage url="#{photo.url}"/>
      <h:outputText value="#{photo.title}"/>
      ...
    </h:panelGrid>
  </h:cell>
<h:dataGrid>


But obviously, this tag doesn't exist. Not only doesn't it exist, it's not even possible to do, at all, without writing a custom tag or binding say a panelGrid and building it's contents programmatically (which sort of defeats the point of JSF). Writing a custom tag is an option, but when faced with the decision of whether to spend a week writing a custom tag or writing the entire app in the same amount of time, I chose the latter.

Another thing one would like to do in such a situation is to mix JSF and JSTL for the desired result. For example, use a JSF panelGrid and the JSTL forEach tag:

<h:panelGrid columns="6">
  <c:forEach var="photo" items="${album.photos}">
    <h:panelGrid columns="1">
      <h:graphicImage url="#{photo.url}"/>
      <h:outputText value="#{photo.title}"/>
      ...
    </h:panelGrid>

  </c:forEach>
</h:panelGrid>

But JSF and JSTL don't like each other, and such intermixing is not supported. I don't know all of the technical reasons why this doesn't work.

Another possible solution would be to pick up a third-party component library that had what I needed. Since free is my only option, I have looked into MyFaces Components (AKA Tomahawk) in the past. However, I was not able to get it to work with the specific JSF-portlet bridge, JSF implementation (the RI), and portlet container I was already bought into. Of course, I never really looked into whether MyFaces Components had the component I needed anyway.

Alas, the app is being written with plain old JSP + JSTL

Introduction to the Portlet Open-Source Repository

My article introducing the Portlet Repository open-source project went live today on developer.sun.com. Not exactly a technical article, but it's my first published, so it means something to me :)

Wednesday Aug 09, 2006

RSS Portlet Open Source

RSS Portlet is a simple portlet application for displaying RSS feeds. I wrote this portlet several years ago for the SJS Portal Server product. We recently moved the code for RSS Portlet to the Portlet Open Source Repository (POR) project on java.net. A fully supported version of the portlet is bundled with SJS Portal Server.



RSS Portlet just wraps a simple UI on top of the ROME feed processing engine. The real work happens there. Being based on ROME, RSS Portlet can consume much more than RSS feeds (the name is a misnomer). It can consume any feed format that ROME understands. As of ROME 0.8 (which is what RSS Portlet currently bundles), that is RSS 0.90, RSS 0.91 Netscape, RSS 0.91 Userland, RSS 0.92, RSS 0.93, RSS 0.94, RSS 1.0, RSS 2.0, Atom 0.3, and Atom 1.0.

We recently got our first code submission for ehancements to RSS Portlet. It's great too see folks interested! I really look forward to seeing this portlet evolve into a fully functional portlet-based feed reader.

Thursday Jul 20, 2006

SJS Portal Server 7.0 Community Feature, A Quick Look

WARNING WARNING WARNING: Marketing content follows ...

In the interest of getting a little more exposure for the feature, I recorded a quick screen cast that highlights the Community feature of SJS Portal Server 7.0. If you have any questions or if there is any areas where you'd like to see a more in-depth screen cast, let me know and I'll do my best.

Wednesday Jul 19, 2006

What Happenend To The Dream of Downloadable Applications?

When I read an intro to .NET a year or so ago, it was touting support for downloadable applications. It's a pretty simple idea. You connect to a web address and download the code for an application. Maybe you authenticate first, or make a payment. The application runs, and leaves no trace on the local system. Moreover, it's zero install. The user can walk up to any PC with access to the web and run their application. There are no more upgrades, because the most current version of the app is downloaded freshly each time. Developers don't need to worry about installing their application.

Sound familiar? Remember Applets? Applets have been around much longer than .NET. Why were they not a success?
  1. Not true zero install. The client had to install a browser plugin.
  2. Compatibility. Said browser plugins were always behind the curve. Developers were stuck writing applets against the oldest possible versions of Java.
  3. Performance. Applets, and Java apps, were slow.
Now we have something calling Web Start, which solves #2, sort of. This downloads the app and runs it using a locally installed JVM, not a browser plugin. This makes it much easier to have the latest, greatest version of the JVM accessible to the app. #1 can't really be solved unless Java can be made part of the major PC OS distributions (OS X, Linux, Windows). By "part", I mean that software developers can assume it's there even on a minimal install of the OS. In reality, I have a hard time understanding that this is a problem. On every modern OS I've every used it's been trivial to make Java available. Sun has even created a license which allows Java to be included directly in Linux distributions. As for #3 ... everyday I use a 100% Java IDE on a less than high-performing desktop system and it is definitely usable. To be fair, the system has a good amount RAM, which is one of the major complaints about Java apps.

Enter Javascript applications. They can run on any browser that supports Javascript (which is all of them). They are truly zero install as they run in the browser application. They perform reasonably with a low memory footprint. On the other hand, you have the problem of browser dependence. As a software engineer, I have for the most part found Javascript based solutions offensive. When using Javascript, one is almost always forced to do "hacky" sort of things. Javascript solutions never seem to be put together cleanly. I am not exactly sure why that is though. Maybe it's because Javascript is often written by web designers not software engineers. Maybe it is because Javascript is less structured and doesn't push developers into writing more structured applications.

And then we have Flash. Flash applications run in a plugin so they don't have the browser dependence issue. However, they suffer from the "not zero install" issue just like Java. And they potentially suffer from compatibility problems as well. Despite this, they are becoming more and more popular.

Both straight Javascript and Flash have taken the downloadable application meal away from Sun + Java. It's quite sad. As a developer, I'd much rather be writing an application using Java's well-designed UI frameworks than writing Flash or Javascript. The problems with Java as a downloadable application seem to me to have been solvable. Either technically, through partnerships, or via some well-designed "examples" that can showcase the solution.

Sun has a good example internally in their bug tracking software. It's 100% Java and deployed via Web Start. It works flawlessly on every platform I've tried it on and it performs well.

I don't know what Sun's plans are around this problem. Considering the popularity of delivering applications over the web, they would be well advised to be looking into this and coming up with some solutions.

Monday Jul 10, 2006

Coffee's Understated Effect In The Workplace

A large percentage of Americans (and others, but let's narrow the scope) start their day by ingesting some sort of coffee beverage. As we all know, caffeine is a moderate stimulant. I did not start drinking coffee until I was into my thirties. I made it through university and much of my professional career without it. I think this experience gives me some insight into the role coffee plays in the work place; it's not something that has always been there in my adult life.

Why did it take me so long to try coffee? My parents were coffee drinkers. After tasting black coffee as a child, by obvious response was "are you people nuts?!?!" People who say they like the taste of coffee are simply lying. They like the caffeine. They may have become accoustomed to drinking coffee socially / cultururally. They may enjoy the more-milkshake-than-coffee blended drinks that everyone serves nowadays. But black coffee or epsresso is bitter. The bitterness by far overpowers any other taste. Human taste buds do not enjoy bitterness. In nature, bitter often indicates poison. We like sweet and fatty, not bitter.

I should state that I am a software engineer, but I think my experience is typical of most office-type jobs. Employers provide free or at the very least easy access coffee to their employees. They're not stupid. They know that they get back ten-fold the $0.20 a cup they lay out for free coffee. Again, coffee is a moderate stimulant. It is highly addicitve. It has various negative health consequences. So, we have employers providing free drugs to their employees in order to increase their efficiency at work, at the expense of potentially negative consequences to their health. Sure, it's a legal drug. Well, most people don't consider coffee (caffeine) a drug, but it's effect on the body is not significantly different that equivalent amounts of various unsavory street drugs.

I can't help recalling Vernor Vinge's great novel A Deepness In The Sky, where people are infected with the "Focus", causing them to single-mindedly pursue a given task, thereby enslaving them.

I'm not sure I have a point. I am not advocating anything like removal of coffee from the workplace, or as silly as the re-classification of coffee as a controlled substance. I just find it interesting that I have never seen this issue discussed. Coffee is so widely used that folks forget what it actually is, and the effects it has upon them.

Tuesday Jun 20, 2006

Oranges and Bananas

I recently ran across what I thought was an interesting thought exercise:

A conveyor belt transports oranges and bananas. A downward facing camera takes digitized pictures of the fruit. There is one image per piece of fruit on the belt. The images are 2 bit. You get a "0" for the conveyor belt, and a "1" for the fruit. The task is to determine the number of oranges and bananas that pass under the camera.

Solution #1

The most obvious solution is to base your answer on the whether the polygon represented by the "1" bits posesses any concavity. If it's convex, then it's an orange. If it has any concavity, then it's a banana. My best guess on how to do this would to be determine if the line drawn between any boundary point goes outside of the area of the fruit. To do this, you'd first need to find the boundary points; the edges of the fruit. You could find these by say taking Y=0...n and for each value of Y, increment X=0 until you hit a fruit point. Then, do the same thing with X=m...0 decrementing X (visually, coming in from each side of the fruit). You could step Y by 2 or 5 or 10 or something to speed things up and still get an approximation of the polygon representing he fruit:

and

You can generate a vector image of the fruit's outline by connecting successive boundary points. Now, for each boundary point, draw a line to every other boundary point. If any of those lines intersect the lines defining the edges of the polygon, then the object has concavity and is banana:



The above solution in O(n squared). We'd like to improve that.

Solution #2

What if the banana is not concave like some of the more exotic banana types that are less common in American grocery stores (I think these are called Chiquita bananas)? What if the object is not a banana, but say a mango (or any other not quite round, but not convex fruit)? Again, assume that we have the vector representation of the object. What if we knew the length and width of the object? We know that for a roughly spherical object, l / w = ~1. We can use this and say that if the ratio of the length over the width is equal to one within some tolerance, that the object is an orange, otherwise, it's a banana. How do we define the length and width of a polygon? Imagine we can draw two parallel lines over the bitmap image. We step them towards each other until they both intersect the polygon. The length is the maximum distance between parallel lines we can achieve if we repeat this process rotating the polygon 360 degrees (or changing the starting position of the lines 360 degrees around the polygon). The width is the minimum value. We can now compute the length and width, and the ratio of the two. We can say if l / w < 1.3 (or something), that the object is an orange, else it's a banana.



This solutiion is O(n), assuming we rotate the polygon 360 degrees in n steps.

Solution #3

Another solution contributed by a reader ...

Count the number of pixels consumed by the object. Now make a copy of the image, and rotate it 90 degrees. XOR the bits in the original with the rotated copy. The result is an image that contains the bits that are 1's in the original but not in the rotated. If the object is a perfect circle, then there should be no 1's in the XOR'd image. Of course an orange is not a perfect circle, so you'd want to compare with some tolerance (some small percent of the original 1 bits remain). A non-circular object would contain a much larger proportion of 1 bits in the XOR'd image.
 vs.

This assumes that the object is perfectly centered in the larger image. This is not likely, so before attempting this you'd need to find the boundary square for the object, and only rotate and XOR that subset of the larger image.

Solution #4

Also submitted by a reader ...

Start with the assumption that object is roughly circular, and try to prove that it's not. Find the actual area consumed by the object by counting the 1 bits in the image. Find the bounding rectangle. If the object is circular, then the bounding rectangle is actually a square. If so, we know the diameter d of the circle is equal to the length of the sides of the square. We know that the area of the circle is pi\*r squared, so we can compute the expected area based on the assumption that the object is circular. If the object is truly circular, then the actual area should be equal to the expected area within some tolerance. If so, then we assume it's an orange, else it's a banana.

Any corrections or better solutions would be appreciated.

Thursday Jun 08, 2006

Take the Bus

I live in San Jose and have been commuting via public transit to the Santa Clara campus ever since it it opened. The SCA campus is about 1/2 mile from VTA Light Rail. It's about 1.5 miles from the Santa Clara Caltrain station. Sun has a free shuttle that goes between the Caltrain station and the Santa Clara campus (and lots of other places too). VTA has a bus stop literally right outside the Santa Clara campus. Sun offers its employees EcoPasses. For those that don't know, this is a one-year unlimited pass on all of VTA (a ~$600 value). All in all, Sun offers its employees a lot on this front, and particularly, the Santa Clara campus is ideally located for transit commuters.

So what's the problem?

I take light rail and the bus nearly every day. I take it at various hours: between 6 and 9 in the morning, and between 4 and 10 in the evening. In all the years I've been taking it to the Santa Clara campus, I've only ever seen one other employee taking the bus to work. If there were others, I'd have seen them (unless they work graveyard shift). I'm not sure of the exact numbers, but I believe there are about 4k employees at this campus. And it's not just Sun. The bus line I take to and from work skirts through various high-tech areas. On a bus that holds 50+ passengers, I've seen a maximum of 6 people on the bus at one time. Often, there are no other riders beside myself. Something is wrong.

I have a couple of guesses as to the cause. First, I think the valley's culture is broken in this regard. Taking the bus, or transit in general, is considered a sort of poor-mans way to get around; if you're taking transit, it's because you can't afford a car. Couple that with the fact that the entire culture of the valley is around making money and flaunting it. Now consider that a person's car is the single largest (external) indicator of their wealth.

While waiting for the bus, I've had colleagues stop and pittyingly offer me a ride. After all, I must be really hard up to be waiting on the street for a bus! I don't judge them for the attitude. It's quite nice of them to offer. However, it is a fairly clear indicator of how they feel about transit and those who use it.

The second issue is transit service & reliability. I won't go into details, but the first time you have a bus pass you up because they do not see you sitting at the stop at 9pm at night, and it's raining and your laptop is getting wet, you're going to think twice about using transit the next day. I really have no idea whether VTA is worse or better than other transit agencies. One thing for sure: low ridership compounds the problem. Low ridership means less frequent runs. If a bus runs every 10 minutes, it hardly matters if you miss it or if any particular bus running the route is late. If it runs every 1/2 hour or less, it's a problem. You miss connections, compounding the situation. Again, the first time you miss an important meeting because your bus didn't show, you're going to think twice about riding it the next day.

The places where I've seen transit work are where driving is such an utter nightmare that it drives the majority of people out of there cars. Places like San Francisco, New York, and other large cities. So, maybe the solution is that we have to let things like traffic and fuel costs spiral out of control before we see our culture change.
About

jtb

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today