Scrollbar Improvements

I think I saw this on Digg a few weeks ago…or perhaps somewhere else. Anyway, I think this is a great idea:

Popup Scrollbar Concept Demo

It seems to address some very obvious limitations of scrollbars, I like the little triangle when the “thumb” gets down to 1 pixel, and I like that it’s easier to grab quickly with the mouse without having to very precisely point at the exact right spot. I suspect that GUIs supporting quick gestures are a lot more productive than GUIs requiring super precise pointing and clicking.

I do not have time to work on this, but I wonder if anyone out there is interested in putting together a Swing implementation of this component?

Next question…is this component a new innovation, or is this something that already exists, for instance, in OSX or some other GUI toolkit?

Bad, Better, Best

Bad…what is the data type of the customer ID?

public Customer getCustomer(Object customerId) { ... }

Better…but a null customer ID makes no sense:

public Customer getCustomer(Integer customerId) { ... }

Best:

public Customer getCustomer(int customerId) { ... }

Death Star Physics

When approaching a Death Star landing bay, it usually looks like a side approach:

Death Star Side Approach

Unfortunately, your artificial gravity generator is broken. From your perspective, as you approach the landing bay, does it feel more like a vertical drop?

Death Star Approach 2

As you get closer, does your perspective immediately “flip” from the horizontal to the vertical sensation, or does it feel more like a sickening plunge over the edge of a giant roller coaster?

And how about those people working in the landing bays. For them, it seems like the bay is on the “side” of the Death Star. So I guess Death Star gravity must be machine-generated, because it always pulls “down”, rather than towards the center of the sphere.

If, like Twitter, the gravity generator fails, wouldn’t people fly towards the center of the station? For people on the top level, this is no problem. But people working in the side landing bays would fly towards the inside walls, and people on the “bottom” levels would fly toward the ceiling.

Is there zero gravity at the center of the station? (again, assuming the artificial gravity is temporarily broken)

Adirondack Chair

I spent more time than I care to admit designing this Adirondack chair in Sketchup:

I then built a prototype, which consumed an entire weekend.

Unfortunately, my chair is not remotely comfortable. Maybe I should stick to tables.

Sunset

Inspired by @dalmaer.

Tunnel from Sun to Adobe

This is my first comic using Adobe Illustrator CS3. First impressions:

  • Illustrator is very expensive, so it had better kick ass.
  • Keybindings are highly unexpected and surprising, not like other graphics apps I’ve used. Why not Ctrl-D to duplicate the selection? Or Esc to unselect?
  • Selecting was awkward in many ways.
  • I really found myself wishing I could easily drag with the mouse to pan around.
  • I really missed Xara’s ability to draw gradients and transparencies by simply dragging interactively on the drawing, rather than clicking through tiny little popup windows.
  • Drawing lines, like the arms on the little people, did some unexpected fills between points, obscuring graphics beneath.
  • Export to PNG is broken. Wow, unbelievable. Regardless of the resolution I tried, I always received an error. I had to copy to the clipboard, and then paste into another program in order to generate the PNG shown above.
  • Getting that gradient right was extremely weird, it took quite a long time with many failed trips back and forth between those annoying, tiny little toolbar windows before I figured out how to adjust the colors.

Overall, Illustrator feels very old-school, with lots of tiny menus, toolbars, popups, and tedious context switching. Contrast this with something like Sketchup. First impressions with Sketchup are generally along the lines of: Holy crap…this kicks ass! I have no doubts I could slog through Illustrator and perhaps eventually become proficient, but this is my hobby and should be fun. :-)

The whole reason I’m looking at other illustration programs is because Xara’s export filters are weak. I’d like to be able to share my original source material, in vector format, so other people can copy, modify, and play with the drawings. Xara’s format is too obscure, and it is unable to export to more common vector formats without bad corruption or crashing.

On the flip side, Xara is an absolute joy to work with, its bitmap exports are first rate, and it is incredibly fast. It uses direct manipulation and mouse dragging whenever possible, avoiding most menus and toolbar windows. There is a new version of Xara that I will definitely try.

Illustrator is probably off my list. I plan to try PhotoShop for the next comic.

Writing a Custom JAAS LoginModule

Today I wrote a custom JAAS LoginModule and configured it to work with JBoss 4.2.2. This post summarizes the steps involved. This is not light reading — this is mostly reference information in case you ever have to write your own LoginModule implementation.

Why do This?

We wanted to add authentication to some web apps, but our administrative database is different than you might expect. Without going into too many proprietary details, the out-of-the-box JAAS LoginModule implementations did not work for us. I had to write a custom implementation of the LoginModule interface.

Now that we have a LoginModule implementation configured, we can use the standard <security-constraint>, <login-config>, and <security-role> tags in our web.xml deployment descriptors.

To summarize, we want to:

  • authenticate against our proprietary administrative database
  • utilize declarative security configuration in web.xml
  • when possible, stick to standard JAAS APIs, avoiding compile-time JBoss dependencies

Implement the Interfaces

The first step involves writing three classes. I am changing the names here in order to avoid publishing proprietary code (sorry!):

  • MyPrincipal – implements java.security.Principal. This class represents either a user or a role.
  • MyGroup – implements java.security.acl.Group. This holds a collection of roles.
  • MyLoginModule – implements javax.security.auth.spi.LoginModule. This ties into JAAS to perform the actual authentication against the database.

The Principal

This is a trivial interface that represents the user’s name, such as “harry”. It also represents a role he belongs to, like “admin” or “guest”. Your Principal should look something like this:

public class MyPrincipal implements Principal, Serializable {   private static final serialVersionUID = 1L;   private final String name;    public MyPrincipal(String name) {     this.name = name;   }    public String getName() {     return name;   }    // also implement equals() and hashCode(), you get the point }

The Group

This is a class that implements java.security.acl.Group:

public class MyGroup implements Group, Serializable {   private static final long serialVersionUID = 1L;   private final String name;   private final Set<Principal> users = new HashSet<Principal>();    public MyGroup(String name) {     this.name = name;   }    public boolean addMember(Principal user) {     return users.add(user);   }    public boolean removeMember(Principal user) {     return users.remove(user);   }    public boolean isMember(Principal member) {     return users.contains(member);   }    public Enumeration<? extends Principal> members() {     return Collections.enumeration(users);   }    public String getName() {     return name;   }    public boolean equals(Object o) {     // you are smart enough to write this; just compare the name   }    // yeah, write your own hashCode method too }

We’ll see how this group works next, with the LoginModule.

The LoginModule

I wrote my class by copying com.sun.jmx.remote.security.FileLoginModule. I won’t duplicate all of the code here because I can’t — it is proprietary. But here are the highlights (it is really easy, I promise):

public class MyLoginModule implements LoginModule {   private Subject subject;   private CallbackHandler callbackHandler;   private Map<String, ?> sharedState;   private Map<String, ?> options;    private boolean commitSucceeded = false;   private boolean loginSucceeded = false;    private String username;   private MyPrincipal user;   private MyPrincipal[] roles;    public void initialize(Subject subject, CallbackHandler callbackHandler,                          Map<String, ?> sharedState, Map<String, ?> options) {     this.subject = subject;     this.callbackHandler = callbackHandler;     this.sharedState = sharedState;     this.options = options;   }    public void login() throws LoginException {     ...     NameCallback nameCallback = new NameCallback("Username");     PasswordCallback passwordCallback = new PasswordCallback("Password", false);      Callback[] callbacks = new Callback[]{nameCallback, passwordCallback};     callbackHandler.handle(callbacks);      username = nameCallback.getName();     char[] password = passwordCallback.getPassword();     passwordCallback.clearPassword();      // you now have the username and password, so authenticate against your db      user = new MyPrincipal(username);     roles = new MyPrincipal[] {       new MyPrincipal("admin") // for example       ...fill in all of the roles from your database     };      // trust me - just do a "find usages" for classes implementing LoginModule   }    public boolean commit() throws LoginException {     ...     // this is the important part to work with JBoss:     subject.getPrincipals().add(user);     // jboss requires the name 'Roles'     MyGroup group = new MyGroup("Roles");     for (MyPrincipal role : roles) {       group.addMember(role);     }     subject.getPrincipals().add(group);      ...     return true;   }    ...other methods are trivial. just copy the general patterns from FileLoginModule }

Packaging

You need to compile those three classes and put them into a JAR file. We’ll call it myJaas.jar. Next, you’ll generate a .sar file. We can call this myapp.sar. This should also work in an EAR file, but mine is a SAR file. The structure of the SAR file is:

myapp.sar  |  +--myapp.war (the web application itself)  +--my-login-config.xml  +--myJaas.jar  +--META-INF       +--jboss-service.xml

The WAR file

This is a normal WAR file, but it does contain a JBoss-specific XML file. It looks like this:

myapp.war   |   +--WEB-INF        +--classes        +--lib        +--jboss-web.xml        +--web.xml

The jboss-web.xml file looks like this:

<jboss-web>   <security-domain>java:/jaas/myjaas</security-domain>   <depends>jboss.jca:service=DataSourceBinding,name=MyDS</depends> </jboss-web>

That “myjaas” is important because it ties your web app to the application policy we will define in my-login-config.xml. That data source dependency ensures the data source “MyDS” is deployed before the WAR file is deployed.

jboss-service.xml

This file looks like this:

<server>   <mbean code="org.jboss.security.auth.login.DynamicLoginConfig"     name="whatever:service=MyLogin">     <attribute name="AuthConfig">my-login-config.xml</attribute>     <depends optional-attribute-name="LoginConfigService">       jboss.security:service=XMLLoginConfig</depends>     <depends optional-attribute-name="SecurityManagerService">       jboss.security:service=JaasSecurityManager</depends>   </mbean> </server>

my-login-config.xml

Here goes:

<policy>   <application-policy name="myjaas">     <authentication>       <login-module code="com.acme.MyLoginModule"         flag="required">         <module-option name="myKey">myValue</module-option>       </login-module>     </authentication>   </application-policy> </policy>

That module-option is critical to my own proprietary implementation. It allowed me to pass along something called the “enterprise ID”, a proprietary piece of data we need for login functionality. You can add whatever options you need, they are available in your LoginModule class in the options map.

Final Steps

The last thing is to ensure your web application deployment descriptor (web.xml) declares the security constraint:

<security-constraint>   <web-resource-collection>     <web-resource-name>Secure Content</web-resource-name>     <url-pattern>/feed/*</url-pattern>   </web-resource-collection>   <auth-constraint>     <role-name>FeedAdmin</role-name>   </auth-constraint>   <user-data-constraint>     <transport-guarantee>NONE</transport-guarantee>   </user-data-constraint> </security-constraint>  <login-config>   <auth-method>BASIC</auth-method>   <realm-name>The Restricted Zone</realm-name> </login-config>  <security-role>   <description>The role required to access restricted content</description>   <role-name>FeedAdmin</role-name> </security-role>

In Summary

I hope this helps someone out there. While there are some JBoss-specific XML files, for the most part the APIs are generic JAAS. Furthermore, the web.xml is completely standard, with no dependencies on JBoss.

Reel Mower Review

My new Scotts 20-inch Push Reel Mower arrived today, and I finished mowing the lawn about 30 minutes ago.

Scotts 20-inch Push Reel Mower

This mower has 271 reviews and received 4 out of 5 stars on Amazon.com. Let me make this very clear: I have never been more misled by Amazon.com reviewers. For example, check out this review:

At the same time, I didn’t want to turn lawn mowing into a huge, difficult task. After researching every model on the market, I decided I would give the Scotts 2000-20 reel mower a try. My idea of lawn mowing has completely changed. What used to be a tedious, annoying task is now pleasant and relaxing, due to the ease of use and functionality of this mower.

This is absolute horse shit. This mower is easily 100% harder to push than my Toro gas mower. It took me nearly twice as long to mow the lawn. Mowing the lawn was my most intense workout in years.

The same review goes on:

I will venture to say that it is actually JUST AS EASY TO USE A REEL MOWER AS IT IS TO USE A GAS-POWERED MODEL. There is NOTHING about a gas-powered mower than makes it easier to use, and gas-powered mowers do not save any time, espcially when you consider all the peripheral needs of owning one.

Liar, liar, pants on fire. Several things make a gas mower easier to use:

  • The engine propels the mower forward
  • The blade cuts through thick grass without bogging down
  • They are faster
  • Did I mention the engine does most of the work?

I Had Doubts…

I’ve been considering one of these mowers for at least three years now, and keep reading positive reviews like this. I waited so long to pull the trigger because I had this fear: Maybe these people are so gung-ho to save the environment, they are unable to provide unbiased, accurate reviews.

I now think I have my answer. Everything you recall about your grandfather’s old-fashioned reel mower remains true to this day. These mowers are hard to use. Damn hard.

Now What?

I paid $119 for this thing, and I still have my Toro. The truth is, I don’t know what I will do. I do plan to mow the lawn with this reel mower the next few times, simply because it provides a kick-ass workout. I need to lose weight, and what better way to get some much needed exercise?

If your lawn is small and flat, a reel mower is just fine. But my yard is 17,000 square feet, with a huge steep hill in the back. For a killer workout, this is good. But for mowing the lawn, it sucks.

The Future

I think battery-powered mowers are the future of lawn care, but current models poop out after 45 minutes to an hour. That is not quite good enough to handle my lawn. I suspect in just a few years, however, battery-powered mowers will finally become a practical alternative.

I really hate how much space my Toro consumes in the garage, and I do not like how loud it is. But until battery technology improves, gas powered mowers remain the best option for most people.